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 FILE *codeOutFile;
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 // pic16_emitpcomment("ic: %s\n", printILine(ic));
961 val += (int) operandLitValue(IC_RIGHT(ic));
962 } else if (ic->op == '-') {
963 val -= (int) operandLitValue(IC_RIGHT(ic));
967 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
970 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
973 if(!op->isaddr)viaimmd++; else viaimmd=0;
975 /* set the following if to 1 to revert to good old immediate code */
976 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
979 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
981 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
984 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
986 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
989 PCOI(aop->aopu.pcop)->index = val;
991 aop->size = getSize( sym->type );
993 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__, getSize( OP_SYMBOL( IC_LEFT(ic))->type));
995 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
996 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
998 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
1002 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
1003 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
1005 val, IS_PTR_CONST(operandType(op)));
1007 val, IS_CODEPTR(operandType(op)));
1010 // DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
1012 pic16_allocDirReg (IC_LEFT(ic));
1014 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
1021 static int aopIdx (asmop *aop, int offset)
1026 if(aop->type != AOP_REG)
1029 return aop->aopu.aop_reg[offset]->rIdx;
1034 /*-----------------------------------------------------------------*/
1035 /* regsInCommon - two operands have some registers in common */
1036 /*-----------------------------------------------------------------*/
1037 static bool regsInCommon (operand *op1, operand *op2)
1039 symbol *sym1, *sym2;
1042 /* if they have registers in common */
1043 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1046 sym1 = OP_SYMBOL(op1);
1047 sym2 = OP_SYMBOL(op2);
1049 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1052 for (i = 0 ; i < sym1->nRegs ; i++) {
1057 for (j = 0 ; j < sym2->nRegs ;j++ ) {
1061 if (sym2->regs[j] == sym1->regs[i])
1069 /*-----------------------------------------------------------------*/
1070 /* operandsEqu - equivalent */
1071 /*-----------------------------------------------------------------*/
1072 static bool operandsEqu ( operand *op1, operand *op2)
1074 symbol *sym1, *sym2;
1076 /* if they not symbols */
1077 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1080 sym1 = OP_SYMBOL(op1);
1081 sym2 = OP_SYMBOL(op2);
1083 /* if both are itemps & one is spilt
1084 and the other is not then false */
1085 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1086 sym1->isspilt != sym2->isspilt )
1089 /* if they are the same */
1093 if (sym1->rname[0] && sym2->rname[0]
1094 && strcmp (sym1->rname, sym2->rname) == 0)
1098 /* if left is a tmp & right is not */
1099 if (IS_ITEMP(op1) &&
1102 (sym1->usl.spillLoc == sym2))
1105 if (IS_ITEMP(op2) &&
1109 (sym2->usl.spillLoc == sym1))
1115 /*-----------------------------------------------------------------*/
1116 /* pic16_sameRegs - two asmops have the same registers */
1117 /*-----------------------------------------------------------------*/
1118 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1125 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1126 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1128 if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1130 if (aop1->type != AOP_REG ||
1131 aop2->type != AOP_REG )
1134 /* This is a bit too restrictive if one is a subset of the other...
1135 if (aop1->size != aop2->size )
1139 for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1140 // if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1142 // if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1143 if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1150 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1152 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1153 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1155 if(aop1 == aop2)return TRUE;
1156 if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1158 if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1164 /*-----------------------------------------------------------------*/
1165 /* pic16_aopOp - allocates an asmop for an operand : */
1166 /*-----------------------------------------------------------------*/
1167 void pic16_aopOp (operand *op, iCode *ic, bool result)
1176 DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1178 /* if this a literal */
1179 if (IS_OP_LITERAL(op)) {
1180 op->aop = aop = newAsmop(AOP_LIT);
1181 aop->aopu.aop_lit = op->operand.valOperand;
1182 aop->size = getSize(operandType(op));
1187 sym_link *type = operandType(op);
1189 if(IS_PTR_CONST(type))
1191 if(IS_CODEPTR(type))
1193 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1196 /* if already has a asmop then continue */
1200 /* if the underlying symbol has a aop */
1201 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1202 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1203 op->aop = OP_SYMBOL(op)->aop;
1207 /* if this is a true symbol */
1208 if (IS_TRUE_SYMOP(op)) {
1209 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1210 op->aop = aopForSym(ic, op, result);
1214 /* this is a temporary : this has
1220 e) can be a return use only */
1222 sym = OP_SYMBOL(op);
1224 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1225 /* if the type is a conditional */
1226 if (sym->regType == REG_CND) {
1227 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1232 /* if it is spilt then two situations
1234 b) has a spill location */
1235 if (sym->isspilt || sym->nRegs == 0) {
1237 // debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1238 DEBUGpic16_emitcode(";","%d",__LINE__);
1239 /* rematerialize it NOW */
1242 sym->aop = op->aop = aop = aopForRemat (op, result);
1243 // aop->size = getSize(sym->type);
1244 // DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1251 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1252 aop->size = getSize(sym->type);
1253 for ( i = 0 ; i < 1 ; i++ ) {
1254 aop->aopu.aop_str[i] = accUse[i];
1255 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1257 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1258 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1266 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1267 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1268 //pic16_allocDirReg (IC_LEFT(ic));
1269 aop->size = getSize(sym->type);
1274 aop = op->aop = sym->aop = newAsmop(AOP_REG);
1275 aop->size = getSize(sym->type);
1276 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1277 aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1279 DEBUGpic16_emitcode(";","%d",__LINE__);
1283 /* else spill location */
1284 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1285 /* force a new aop if sizes differ */
1286 sym->usl.spillLoc->aop = NULL;
1290 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1291 __FUNCTION__,__LINE__,
1292 sym->usl.spillLoc->rname,
1293 sym->rname, sym->usl.spillLoc->offset);
1296 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1297 if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1298 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1299 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1301 sym->usl.spillLoc->offset, op);
1302 } else if (getSize(sym->type) <= 1) {
1303 //fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK (size:%u)!\n", __FUNCTION__, __LINE__, getSize(sym->type));
1304 pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1305 assert (getSize(sym->type) <= 1);
1306 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1307 aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1309 /* We need some kind of dummy area for getSize(sym->type) byte,
1310 * use WREG for all storage locations.
1311 * XXX: This only works if we are implementing a `dummy read',
1312 * the stored value will not be retrievable...
1313 * See #1503234 for a case requiring this. */
1314 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1315 aop->size = getSize(sym->type);
1316 for ( i = 0 ; i < aop->size ;i++)
1317 aop->aopu.aop_reg[i] = pic16_pc_wreg.r;
1319 aop->size = getSize(sym->type);
1325 sym_link *type = operandType(op);
1327 if(IS_PTR_CONST(type))
1329 if(IS_CODEPTR(type))
1331 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1334 /* must be in a register */
1335 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1336 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1337 aop->size = sym->nRegs;
1338 for ( i = 0 ; i < sym->nRegs ;i++)
1339 aop->aopu.aop_reg[i] = sym->regs[i];
1342 /*-----------------------------------------------------------------*/
1343 /* pic16_freeAsmop - free up the asmop given to an operand */
1344 /*----------------------------------------------------------------*/
1345 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1362 /* depending on the asmop type only three cases need work AOP_RO
1363 , AOP_R1 && AOP_STK */
1365 switch (aop->type) {
1367 if (_G.fsr0Pushed ) {
1369 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1370 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1371 // pic16_emitcode ("pop","ar0");
1375 bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1379 bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1385 pic16_emitcode ("pop","ar0");
1389 bitVectUnSetBit(ic->rUsed,R0_IDX);
1395 pic16_emitcode ("pop","ar1");
1399 bitVectUnSetBit(ic->rUsed,R1_IDX);
1406 /* we must store the result on stack */
1407 if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1408 // operands on stack are accessible via "FSR2 + index" with index
1409 // starting at 2 for arguments and growing from 0 downwards for
1410 // local variables (index == 0 is not assigned so we add one here)
1411 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1416 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1417 for(i=0;i<aop->size;i++) {
1418 /* initialise for stack access via frame pointer */
1419 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1420 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1421 aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1424 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1428 for(i=0;i<aop->size;i++) {
1429 PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1431 if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx)) {
1432 bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1433 // pic16_popReleaseTempReg(aop->aopu.stk.pop[i], 0);
1440 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
1441 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setFirstItem(_G.sregsAllocSet)) {
1442 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
1443 deleteSetItem( &_G.sregsAllocSet, sr );
1454 int stk = aop->aopu.aop_stk + aop->size;
1455 bitVectUnSetBit(ic->rUsed,R0_IDX);
1456 bitVectUnSetBit(ic->rUsed,R1_IDX);
1458 getFreePtr(ic,&aop,FALSE);
1460 if (options.stack10bit)
1462 /* I'm not sure what to do here yet... */
1465 "*** Warning: probably generating bad code for "
1466 "10 bit stack mode.\n");
1470 pic16_emitcode ("mov","a,_bp");
1471 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1472 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1474 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1478 pic16_emitcode("pop","acc");
1479 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1481 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1484 pic16_freeAsmop(op,NULL,ic,TRUE);
1486 pic16_emitcode("pop","ar0");
1491 pic16_emitcode("pop","ar1");
1501 /* all other cases just dealloc */
1505 OP_SYMBOL(op)->aop = NULL;
1506 /* if the symbol has a spill */
1508 SPIL_LOC(op)->aop = NULL;
1513 /*-----------------------------------------------------------------*/
1514 /* pic16_aopGet - for fetching value of the aop */
1515 /*-----------------------------------------------------------------*/
1516 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1521 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1523 /* offset is greater than size then zero */
1524 if (offset > (aop->size - 1) &&
1525 aop->type != AOP_LIT)
1528 /* depending on type */
1529 switch (aop->type) {
1533 sprintf(s, "%s", aop->aopu.aop_ptr->name);
1534 rs = Safe_calloc(1, strlen(s)+1);
1539 /* if we need to increment it */
1540 while (offset > aop->coff)
1542 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1546 while (offset < aop->coff)
1548 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1554 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1555 return (dname ? "acc" : "a");
1557 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1558 rs = Safe_calloc (1, strlen (s) + 1);
1566 sprintf (s,"%s",aop->aopu.aop_immd);
1569 sprintf(s,"(%s >> %d)",
1574 aop->aopu.aop_immd);
1575 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1576 rs = Safe_calloc(1,strlen(s)+1);
1582 sprintf(s,"(%s + %d)",
1585 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1587 sprintf(s,"%s",aop->aopu.aop_dir);
1588 rs = Safe_calloc(1,strlen(s)+1);
1593 return aop->aopu.aop_reg[offset]->name;
1596 return aop->aopu.aop_dir;
1599 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1600 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1602 // return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1603 rs = Safe_strdup("WREG");
1607 sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1608 rs = Safe_calloc(1,strlen(s)+1);
1613 aop->coff = offset ;
1615 // if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1618 if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1619 aop->type = AOP_ACC;
1620 return Safe_strdup("_WREG");
1622 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1624 return aop->aopu.aop_str[offset];
1628 pCodeOp *pcop = aop->aopu.pcop;
1629 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1631 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1632 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1634 sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1636 sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1639 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1642 rs = Safe_calloc(1,strlen(s)+1);
1648 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1650 sprintf(s,"(%s + %d)",
1654 sprintf(s,"%s",aop->aopu.aop_dir);
1655 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1656 rs = Safe_calloc(1,strlen(s)+1);
1662 rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1666 // pCodeOp *pcop = aop->aop
1671 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1672 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1673 "aopget got unsupported aop->type");
1679 /* lock has the following meaning: When allocating temporary registers
1680 * for stack variables storage, the value of the temporary register is
1681 * saved on stack. Its value is restored at the end. This procedure is
1682 * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1683 * a possibility that before a call to pic16_aopOp, a temporary register
1684 * is allocated for a while and it is freed after some time, this will
1685 * mess the stack and values will not be restored properly. So use lock=1
1686 * to allocate temporary registers used internally by the programmer, and
1687 * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1688 * to inform the compiler developer about a possible bug. This is an internal
1689 * feature for developing the compiler -- VR */
1691 int _TempReg_lock = 0;
1692 /*-----------------------------------------------------------------*/
1693 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1694 /*-----------------------------------------------------------------*/
1695 pCodeOp *pic16_popGetTempReg(int lock)
1700 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1702 // werror(W_POSSBUG2, __FILE__, __LINE__);
1705 _TempReg_lock += lock;
1715 /* this code might seem better but it does the *same* job with
1716 * the old code, it all depends on ralloc.c to get a free/unused
1720 while(i < pic16_nRegs) {
1721 rr = pic16_typeRegWithIdx(i, REG_GPR, 0);
1722 fprintf(stderr, "%s:%d checking for TempReg Idx=%d rr=%p\n", __FILE__, __LINE__, i, rr);
1723 if((!rr || (rr && rr->isFree))
1724 && !bitVectBitValue(cfunc->regsUsed, i)) {
1725 pcop = pic16_newpCodeOpReg( i );
1726 PCOR(pcop)->r->wasUsed = 1;
1727 PCOR(pcop)->r->isFree = 0;
1734 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1738 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1739 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1740 PCOR(pcop)->r->wasUsed=1;
1741 PCOR(pcop)->r->isFree=0;
1743 /* push value on stack */
1744 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1753 /*-----------------------------------------------------------------*/
1754 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which */
1755 /* is not part of f, but don't save if */
1757 /*-----------------------------------------------------------------*/
1758 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1764 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1767 // werror(W_POSSBUG2, __FILE__, __LINE__);
1770 _TempReg_lock += lock;
1775 i = bitVectFirstBit(f);
1778 /* bypass registers that are used by function */
1779 if(!bitVectBitValue(f, i)) {
1781 /* bypass registers that are already allocated for stack access */
1782 if(!bitVectBitValue(v, i)) {
1784 // debugf("getting register rIdx = %d\n", i);
1785 /* ok, get the operand */
1786 pcop = pic16_newpCodeOpReg( i );
1788 /* should never by NULL */
1789 assert( pcop != NULL );
1793 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1796 PCOR(pcop)->r->wasUsed=1;
1797 PCOR(pcop)->r->isFree=0;
1803 for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1805 if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1806 /* already used in previous steps, break */
1813 /* caller takes care of the following */
1814 // bitVectSetBit(v, i);
1817 /* push value on stack */
1818 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1819 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1835 /*-----------------------------------------------------------------*/
1836 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1837 /*-----------------------------------------------------------------*/
1838 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1840 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1842 _TempReg_lock -= lock;
1844 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1845 PCOR(pcop)->r->isFree = 1;
1847 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1850 /*-----------------------------------------------------------------*/
1851 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1852 /*-----------------------------------------------------------------*/
1853 pCodeOp *pic16_popGetLabel(int key)
1856 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1861 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1864 /*-----------------------------------------------------------------*/
1865 /* pic16_popCopyReg - copy a pcode operator */
1866 /*-----------------------------------------------------------------*/
1867 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1871 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1872 memcpy (pcor, pc, sizeof (pCodeOpReg));
1873 pcor->r->wasUsed = 1;
1875 //pcor->pcop.type = pc->pcop.type;
1877 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1878 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1880 pcor->pcop.name = NULL;
1883 //pcor->rIdx = pc->rIdx;
1884 //pcor->r->wasUsed=1;
1885 //pcor->instance = pc->instance;
1887 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1892 /*-----------------------------------------------------------------*/
1893 /* pic16_popGetLit - asm operator to pcode operator conversion */
1894 /*-----------------------------------------------------------------*/
1895 pCodeOp *pic16_popGetLit(int lit)
1897 return pic16_newpCodeOpLit(lit);
1900 /* Allow for 12 bit literals (LFSR x, <here!>). */
1901 pCodeOp *pic16_popGetLit12(int lit)
1903 return pic16_newpCodeOpLit12(lit);
1906 /*-----------------------------------------------------------------*/
1907 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1908 /*-----------------------------------------------------------------*/
1909 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1911 return pic16_newpCodeOpLit2(lit, arg2);
1915 /*-----------------------------------------------------------------*/
1916 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1917 /*-----------------------------------------------------------------*/
1918 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1920 return pic16_newpCodeOpImmd(name, offset,index, 0);
1924 /*-----------------------------------------------------------------*/
1925 /* pic16_popGet - asm operator to pcode operator conversion */
1926 /*-----------------------------------------------------------------*/
1927 pCodeOp *pic16_popGetWithString(char *str)
1933 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1937 pcop = pic16_newpCodeOp(str,PO_STR);
1942 /*-----------------------------------------------------------------*/
1943 /* pic16_popRegFromString - */
1944 /*-----------------------------------------------------------------*/
1945 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1948 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1949 pcop->type = PO_DIR;
1951 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1952 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1957 pcop->name = Safe_calloc(1,strlen(str)+1);
1958 strcpy(pcop->name,str);
1960 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1962 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1963 // PCOR(pcop)->r->wasUsed = 1;
1965 /* make sure that register doesn't exist,
1966 * and operand isn't NULL
1967 * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1968 if((PCOR(pcop)->r == NULL)
1970 && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1971 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1972 // __FUNCTION__, __LINE__, str, size, offset);
1974 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1975 //fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1978 PCOR(pcop)->instance = offset;
1983 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1987 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1988 // fprintf(stderr, "%s:%d rIdx = 0x%0x\n", __FUNCTION__, __LINE__, rIdx);
1990 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1991 PCOR(pcop)->rIdx = rIdx;
1992 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1994 PCOR(pcop)->r = pic16_allocWithIdx(rIdx);
1996 PCOR(pcop)->r->isFree = 0;
1997 PCOR(pcop)->r->wasUsed = 1;
1999 pcop->type = PCOR(pcop)->r->pc_type;
2004 /*---------------------------------------------------------------------------------*/
2005 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
2007 /*---------------------------------------------------------------------------------*/
2008 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
2010 pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
2011 pic16_popGet(aop_src, offset), pic16_popGet(aop_dst, offset));
2017 /*--------------------------------------------------------------------------------.-*/
2018 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
2019 /* VR 030601 , adapted by Hans Dorn */
2020 /*--------------------------------------------------------------------------------.-*/
2021 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
2024 pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(src, dst);
2028 /*---------------------------------------------------------------------------------*/
2029 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
2030 /* movff instruction */
2031 /*---------------------------------------------------------------------------------*/
2032 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
2034 pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
2035 pic16_popCopyReg(src), pic16_popCopyReg(dst) );
2041 /*-----------------------------------------------------------------*/
2042 /* pic16_popGet - asm operator to pcode operator conversion */
2043 /*-----------------------------------------------------------------*/
2044 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
2046 // char *s = buffer ;
2052 /* offset is greater than size then zero */
2054 // if (offset > (aop->size - 1) &&
2055 // aop->type != AOP_LIT)
2056 // return NULL; //zero;
2058 /* depending on type */
2059 switch (aop->type) {
2064 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2065 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2071 pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2072 PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */
2073 PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2074 PCOR(pcop)->r->wasUsed = 1;
2075 PCOR(pcop)->r->isFree = 0;
2077 PCOR(pcop)->instance = offset;
2078 pcop->type = PCOR(pcop)->r->pc_type;
2082 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2083 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2086 /* pCodeOp is already allocated from aopForSym */
2087 DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2088 pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2093 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
2095 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2097 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2099 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2100 PCOR(pcop)->rIdx = rIdx;
2101 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2102 PCOR(pcop)->r->wasUsed=1;
2103 PCOR(pcop)->r->isFree=0;
2105 PCOR(pcop)->instance = offset;
2106 pcop->type = PCOR(pcop)->r->pc_type;
2107 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2111 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2112 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2118 DEBUGpic16_emitcode(";","%d\tAOP_DIR (name = %s)", __LINE__, aop->aopu.aop_dir);
2119 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2123 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2124 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2131 // debugf2("aop = %p\toffset = %d\n", aop, offset);
2132 // assert (aop && aop->aopu.aop_reg[offset] != NULL);
2133 rIdx = aop->aopu.aop_reg[offset]->rIdx;
2135 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2137 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2138 // pcop->type = PO_GPR_REGISTER;
2139 PCOR(pcop)->rIdx = rIdx;
2140 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
2141 PCOR(pcop)->r->wasUsed=1;
2142 PCOR(pcop)->r->isFree=0;
2144 PCOR(pcop)->instance = offset;
2145 pcop->type = PCOR(pcop)->r->pc_type;
2147 DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2148 // rs = aop->aopu.aop_reg[offset]->name;
2149 // DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2154 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2156 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2157 PCOR(pcop)->instance = offset;
2158 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2159 //if(PCOR(pcop)->r == NULL)
2160 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2164 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2165 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2168 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2169 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2172 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2173 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2174 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2175 pcop->type = PCOR(pcop)->r->pc_type;
2176 pcop->name = PCOR(pcop)->r->name;
2182 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2184 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2185 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2186 switch( aop->aopu.pcop->type ) {
2187 case PO_DIR: PCOR(pcop)->instance += offset; break;
2188 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2193 fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2194 assert( 0 ); /* should never reach here */;
2199 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2200 "pic16_popGet got unsupported aop->type");
2203 /*-----------------------------------------------------------------*/
2204 /* pic16_aopPut - puts a string for a aop */
2205 /*-----------------------------------------------------------------*/
2206 void pic16_aopPut (asmop *aop, char *s, int offset)
2213 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2215 if (aop->size && offset > ( aop->size - 1)) {
2216 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2217 "pic16_aopPut got offset > aop->size");
2221 /* will assign value to value */
2222 /* depending on where it is ofcourse */
2223 switch (aop->type) {
2226 sprintf(d,"(%s + %d)",
2227 aop->aopu.aop_dir,offset);
2228 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2231 sprintf(d,"%s",aop->aopu.aop_dir);
2234 DEBUGpic16_emitcode(";","%d",__LINE__);
2236 pic16_emitcode("movf","%s,w",s);
2237 pic16_emitcode("movwf","%s",d);
2240 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
2241 if(offset >= aop->size) {
2242 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2245 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2248 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2255 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2256 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2259 strcmp(s,"r0") == 0 ||
2260 strcmp(s,"r1") == 0 ||
2261 strcmp(s,"r2") == 0 ||
2262 strcmp(s,"r3") == 0 ||
2263 strcmp(s,"r4") == 0 ||
2264 strcmp(s,"r5") == 0 ||
2265 strcmp(s,"r6") == 0 ||
2266 strcmp(s,"r7") == 0 )
2267 pic16_emitcode("mov","%s,%s ; %d",
2268 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2272 if(strcmp(s,"W")==0 )
2273 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
2275 pic16_emitcode("movwf","%s",
2276 aop->aopu.aop_reg[offset]->name);
2278 if(strcmp(s,zero)==0) {
2279 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2281 } else if(strcmp(s,"W")==0) {
2282 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2283 pcop->type = PO_GPR_REGISTER;
2285 PCOR(pcop)->rIdx = -1;
2286 PCOR(pcop)->r = NULL;
2288 DEBUGpic16_emitcode(";","%d",__LINE__);
2289 pcop->name = Safe_strdup(s);
2290 pic16_emitpcode(POC_MOVFW,pcop);
2291 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2292 } else if(strcmp(s,one)==0) {
2293 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2294 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2296 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2304 if (aop->type == AOP_DPTR2)
2310 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2311 "pic16_aopPut writting to code space");
2315 while (offset > aop->coff) {
2317 pic16_emitcode ("inc","dptr");
2320 while (offset < aop->coff) {
2322 pic16_emitcode("lcall","__decdptr");
2327 /* if not in accumulater */
2330 pic16_emitcode ("movx","@dptr,a");
2332 if (aop->type == AOP_DPTR2)
2340 while (offset > aop->coff) {
2342 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2344 while (offset < aop->coff) {
2346 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2352 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2357 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2359 if (strcmp(s,"r0") == 0 ||
2360 strcmp(s,"r1") == 0 ||
2361 strcmp(s,"r2") == 0 ||
2362 strcmp(s,"r3") == 0 ||
2363 strcmp(s,"r4") == 0 ||
2364 strcmp(s,"r5") == 0 ||
2365 strcmp(s,"r6") == 0 ||
2366 strcmp(s,"r7") == 0 ) {
2368 sprintf(buffer,"a%s",s);
2369 pic16_emitcode("mov","@%s,%s",
2370 aop->aopu.aop_ptr->name,buffer);
2372 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2377 if (strcmp(s,"a") == 0)
2378 pic16_emitcode("push","acc");
2380 pic16_emitcode("push","%s",s);
2385 /* if bit variable */
2386 if (!aop->aopu.aop_dir) {
2387 pic16_emitcode("clr","a");
2388 pic16_emitcode("rlc","a");
2391 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2394 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2397 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2399 lbl = newiTempLabel(NULL);
2401 if (strcmp(s,"a")) {
2404 pic16_emitcode("clr","c");
2405 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2406 pic16_emitcode("cpl","c");
2407 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2408 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2415 if (strcmp(aop->aopu.aop_str[offset],s))
2416 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2421 if (!offset && (strcmp(s,"acc") == 0))
2424 if (strcmp(aop->aopu.aop_str[offset],s))
2425 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2429 fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2430 // werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2431 // "pic16_aopPut got unsupported aop->type");
2437 /*-----------------------------------------------------------------*/
2438 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type */
2439 /*-----------------------------------------------------------------*/
2440 void pic16_mov2w (asmop *aop, int offset)
2442 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2445 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2447 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2450 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2452 if(is_LitAOp(src)) {
2453 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2454 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2456 if(pic16_sameRegsOfs(src, dst, offset))return;
2457 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2458 pic16_popGet(dst, offset)));
2462 static void pic16_movLit2f(pCodeOp *pc, int lit)
2464 if (0 == (lit & 0x00ff))
2466 pic16_emitpcode (POC_CLRF, pc);
2467 } else if (0xff == (lit & 0x00ff))
2469 pic16_emitpcode (POC_SETF, pc);
2471 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2472 if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2476 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2478 if(is_LitAOp(src)) {
2479 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2480 pic16_emitpcode(POC_MOVWF, dst);
2482 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2486 void pic16_testStackOverflow(void)
2488 #define GSTACK_TEST_NAME "_gstack_test"
2490 pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2495 sym = newSymbol( GSTACK_TEST_NAME , 0 );
2496 sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME);
2497 // strcpy(sym->rname, GSTACK_TEST_NAME);
2498 checkAddSym(&externs, sym);
2503 /* push pcop into stack */
2504 void pic16_pushpCodeOp(pCodeOp *pcop)
2506 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2507 if (pcop->type == PO_LITERAL) {
2508 pic16_emitpcode(POC_MOVLW, pcop);
2509 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2511 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
2513 if(pic16_options.gstack)
2514 pic16_testStackOverflow();
2518 /* pop pcop from stack */
2519 void pic16_poppCodeOp(pCodeOp *pcop)
2521 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2522 if(pic16_options.gstack)
2523 pic16_testStackOverflow();
2527 /*-----------------------------------------------------------------*/
2528 /* pushw - pushes wreg to stack */
2529 /*-----------------------------------------------------------------*/
2532 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2533 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2534 if(pic16_options.gstack)
2535 pic16_testStackOverflow();
2539 /*-----------------------------------------------------------------*/
2540 /* pushaop - pushes aop to stack */
2541 /*-----------------------------------------------------------------*/
2542 void pushaop(asmop *aop, int offset)
2544 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2546 if(_G.resDirect)return;
2548 if(is_LitAOp(aop)) {
2549 pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2550 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2552 pic16_emitpcode(POC_MOVFF,
2553 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2556 if(pic16_options.gstack)
2557 pic16_testStackOverflow();
2560 /*-----------------------------------------------------------------*/
2561 /* popaop - pops aop from stack */
2562 /*-----------------------------------------------------------------*/
2563 void popaop(asmop *aop, int offset)
2565 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2566 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2567 if(pic16_options.gstack)
2568 pic16_testStackOverflow();
2571 void popaopidx(asmop *aop, int offset, int index)
2575 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2577 if(STACK_MODEL_LARGE)ofs++;
2579 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2580 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2581 if(pic16_options.gstack)
2582 pic16_testStackOverflow();
2585 #if !(USE_GENERIC_SIGNED_SHIFT)
2586 /*-----------------------------------------------------------------*/
2587 /* reAdjustPreg - points a register back to where it should */
2588 /*-----------------------------------------------------------------*/
2589 static void reAdjustPreg (asmop *aop)
2593 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2595 if ((size = aop->size) <= 1)
2598 switch (aop->type) {
2602 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2606 if (aop->type == AOP_DPTR2)
2612 pic16_emitcode("lcall","__decdptr");
2615 if (aop->type == AOP_DPTR2)
2627 /*-----------------------------------------------------------------*/
2628 /* opIsGptr: returns non-zero if the passed operand is */
2629 /* a generic pointer type. */
2630 /*-----------------------------------------------------------------*/
2631 static int opIsGptr(operand *op)
2633 sym_link *type = operandType(op);
2635 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2636 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2644 /*-----------------------------------------------------------------*/
2645 /* pic16_getDataSize - get the operand data size */
2646 /*-----------------------------------------------------------------*/
2647 int pic16_getDataSize(operand *op)
2649 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2652 return AOP_SIZE(op);
2654 // tsd- in the pic port, the genptr size is 1, so this code here
2655 // fails. ( in the 8051 port, the size was 4).
2658 size = AOP_SIZE(op);
2659 if (size == GPTRSIZE)
2661 sym_link *type = operandType(op);
2662 if (IS_GENPTR(type))
2664 /* generic pointer; arithmetic operations
2665 * should ignore the high byte (pointer type).
2668 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2675 /*-----------------------------------------------------------------*/
2676 /* pic16_outAcc - output Acc */
2677 /*-----------------------------------------------------------------*/
2678 void pic16_outAcc(operand *result)
2681 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2682 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2685 size = pic16_getDataSize(result);
2687 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2690 /* unsigned or positive */
2692 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2697 /*-----------------------------------------------------------------*/
2698 /* pic16_outBitC - output a bit C */
2699 /* Move to result the value of Carry flag -- VR */
2700 /*-----------------------------------------------------------------*/
2701 void pic16_outBitC(operand *result)
2705 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2707 /* if the result is bit */
2708 if (AOP_TYPE(result) == AOP_CRY) {
2709 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2710 pic16_aopPut(AOP(result),"c",0);
2713 i = AOP_SIZE(result);
2715 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2717 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2721 /*-----------------------------------------------------------------*/
2722 /* pic16_outBitOp - output a bit from Op */
2723 /* Move to result the value of set/clr op -- VR */
2724 /*-----------------------------------------------------------------*/
2725 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2729 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2731 /* if the result is bit */
2732 if (AOP_TYPE(result) == AOP_CRY) {
2733 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2734 pic16_aopPut(AOP(result),"c",0);
2737 i = AOP_SIZE(result);
2739 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2741 pic16_emitpcode(POC_RRCF, pcop);
2742 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2746 /*-----------------------------------------------------------------*/
2747 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2748 /*-----------------------------------------------------------------*/
2749 void pic16_toBoolean(operand *oper)
2751 int size = AOP_SIZE(oper) - 1;
2754 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2756 if ( AOP_TYPE(oper) != AOP_ACC) {
2757 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2760 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2764 /*-----------------------------------------------------------------*/
2765 /* genUminusFloat - unary minus for floating points */
2766 /*-----------------------------------------------------------------*/
2767 static void genUminusFloat(operand *op,operand *result)
2769 int size ,offset =0 ;
2772 /* for this we just need to flip the
2773 first it then copy the rest in place */
2774 size = AOP_SIZE(op);
2775 assert( size == AOP_SIZE(result) );
2778 pic16_mov2f(AOP(result), AOP(op), offset);
2782 /* toggle the MSB's highest bit */
2783 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2786 /*-----------------------------------------------------------------*/
2787 /* genUminus - unary minus code generation */
2788 /*-----------------------------------------------------------------*/
2789 static void genUminus (iCode *ic)
2792 sym_link *optype, *rtype;
2799 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2800 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2802 /* if both in bit space then special case */
2803 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2804 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2806 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2807 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2808 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2812 optype = operandType(IC_LEFT(ic));
2813 rtype = operandType(IC_RESULT(ic));
2816 /* if float then do float stuff */
2817 if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2818 if(IS_FIXED(optype))
2819 debugf("implement fixed16x16 type\n", 0);
2821 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2825 /* otherwise subtract from zero by taking the 2's complement */
2826 size = AOP_SIZE(IC_LEFT(ic));
2827 assert( size == AOP_SIZE(IC_RESULT(ic)) );
2828 label = newiTempLabel ( NULL );
2830 if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2831 for (i=size-1; i > 0; i--) {
2832 pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2834 pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2835 for (i=1; i < size; i++) {
2836 if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2837 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2840 for (i=size-1; i >= 0; i--) {
2841 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2842 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2845 for (i=0; i < size-2; i++) {
2846 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2847 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2849 pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2851 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2854 pic16_emitpLabel (label->key);
2857 /* release the aops */
2858 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2859 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2863 /*-----------------------------------------------------------------*/
2864 /* saveRegisters - will look for a call and save the registers */
2865 /*-----------------------------------------------------------------*/
2866 static void saveRegisters(iCode *lic)
2873 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2875 for (ic = lic ; ic ; ic = ic->next)
2876 if (ic->op == CALL || ic->op == PCALL)
2880 fprintf(stderr,"found parameter push with no function call\n");
2884 /* if the registers have been saved already then
2886 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2889 /* find the registers in use at this time
2890 and push them away to safety */
2891 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2895 if (options.useXstack) {
2896 if (bitVectBitValue(rsave,R0_IDX))
2897 pic16_emitcode("mov","b,r0");
2898 pic16_emitcode("mov","r0,%s",spname);
2899 for (i = 0 ; i < pic16_nRegs ; i++) {
2900 if (bitVectBitValue(rsave,i)) {
2902 pic16_emitcode("mov","a,b");
2904 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2905 pic16_emitcode("movx","@r0,a");
2906 pic16_emitcode("inc","r0");
2909 pic16_emitcode("mov","%s,r0",spname);
2910 if (bitVectBitValue(rsave,R0_IDX))
2911 pic16_emitcode("mov","r0,b");
2913 //for (i = 0 ; i < pic16_nRegs ; i++) {
2914 // if (bitVectBitValue(rsave,i))
2915 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2918 dtype = operandType(IC_LEFT(ic));
2919 if (currFunc && dtype &&
2920 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2921 IFFUNC_ISISR(currFunc->type) &&
2924 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2927 /*-----------------------------------------------------------------*/
2928 /* unsaveRegisters - pop the pushed registers */
2929 /*-----------------------------------------------------------------*/
2930 static void unsaveRegisters (iCode *ic)
2935 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2936 /* find the registers in use at this time
2937 and push them away to safety */
2938 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2941 if (options.useXstack) {
2942 pic16_emitcode("mov","r0,%s",spname);
2943 for (i = pic16_nRegs ; i >= 0 ; i--) {
2944 if (bitVectBitValue(rsave,i)) {
2945 pic16_emitcode("dec","r0");
2946 pic16_emitcode("movx","a,@r0");
2948 pic16_emitcode("mov","b,a");
2950 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2954 pic16_emitcode("mov","%s,r0",spname);
2955 if (bitVectBitValue(rsave,R0_IDX))
2956 pic16_emitcode("mov","r0,b");
2958 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2959 // if (bitVectBitValue(rsave,i))
2960 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2967 /*-----------------------------------------------------------------*/
2969 /*-----------------------------------------------------------------*/
2970 static void pushSide(operand * oper, int size)
2973 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2975 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2976 if (AOP_TYPE(oper) != AOP_REG &&
2977 AOP_TYPE(oper) != AOP_DIR &&
2979 pic16_emitcode("mov","a,%s",l);
2980 pic16_emitcode("push","acc");
2982 pic16_emitcode("push","%s",l);
2987 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2989 if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2990 pic16_emitpcode(POC_MOVFW, src);
2991 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2993 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2994 src, pic16_popGet(AOP(op), offset)));
2999 /*-----------------------------------------------------------------*/
3000 /* assignResultValue - assign results to oper, rescall==1 is */
3001 /* called from genCall() or genPcall() */
3002 /*-----------------------------------------------------------------*/
3003 static void assignResultValue(operand * oper, int res_size, int rescall)
3005 int size = AOP_SIZE(oper);
3009 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
3010 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
3013 /* assign result from a call/pcall function() */
3015 /* function results are stored in a special order,
3016 * see top of file with Function return policy, or manual */
3019 /* 8-bits, result in WREG */
3020 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3022 if(size > 1 && res_size > 1) {
3023 /* 16-bits, result in PRODL:WREG */
3024 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3027 if(size > 2 && res_size > 2) {
3028 /* 24-bits, result in PRODH:PRODL:WREG */
3029 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3032 if(size > 3 && res_size > 3) {
3033 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3034 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3037 pic16_addSign(oper, res_size, IS_UNSIGNED(operandType(oper)));
3040 /* >32-bits, result on stack, and FSR0 points to beginning.
3041 * Fix stack when done */
3043 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3045 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3046 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3048 popaopidx(AOP(oper), size, GpsuedoStkPtr);
3053 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3054 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3055 if(STACK_MODEL_LARGE) {
3057 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3061 int areg = 0; /* matching argument register */
3063 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3064 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3067 /* its called from genReceive (probably) -- VR */
3068 /* I hope this code will not be called from somewhere else in the future!
3069 * We manually set the pseudo stack pointer in genReceive. - dw
3071 if(!GpsuedoStkPtr && _G.useWreg) {
3072 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3074 /* The last byte in the assignment is in W */
3075 if(areg <= GpsuedoStkPtr) {
3077 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3079 // debugf("receive from WREG\n", 0);
3081 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3084 _G.stack_lat = AOP_SIZE(oper)-1;
3089 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3090 // debugf("receive from STACK\n", 0);
3097 /*-----------------------------------------------------------------*/
3098 /* genIpush - generate code for pushing this gets a little complex */
3099 /*-----------------------------------------------------------------*/
3100 static void genIpush (iCode *ic)
3102 // int size, offset=0;
3105 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3108 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3110 /* send to stack as normal */
3111 addSet(&_G.sendSet,ic);
3112 // addSetHead(&_G.sendSet,ic);
3113 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3118 int size, offset = 0 ;
3122 /* if this is not a parm push : ie. it is spill push
3123 and spill push is always done on the local stack */
3124 if (!ic->parmPush) {
3126 /* and the item is spilt then do nothing */
3127 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3130 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3131 size = AOP_SIZE(IC_LEFT(ic));
3132 /* push it on the stack */
3134 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3139 pic16_emitcode("push","%s",l);
3144 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3148 /*-----------------------------------------------------------------*/
3149 /* genIpop - recover the registers: can happen only for spilling */
3150 /*-----------------------------------------------------------------*/
3151 static void genIpop (iCode *ic)
3154 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3159 /* if the temp was not pushed then */
3160 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3163 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3164 size = AOP_SIZE(IC_LEFT(ic));
3167 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3170 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3175 /*-----------------------------------------------------------------*/
3176 /* unsaverbank - restores the resgister bank from stack */
3177 /*-----------------------------------------------------------------*/
3178 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3180 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3186 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3188 if (options.useXstack) {
3190 r = getFreePtr(ic,&aop,FALSE);
3193 pic16_emitcode("mov","%s,_spx",r->name);
3194 pic16_emitcode("movx","a,@%s",r->name);
3195 pic16_emitcode("mov","psw,a");
3196 pic16_emitcode("dec","%s",r->name);
3199 pic16_emitcode ("pop","psw");
3202 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3203 if (options.useXstack) {
3204 pic16_emitcode("movx","a,@%s",r->name);
3205 //pic16_emitcode("mov","(%s+%d),a",
3206 // regspic16[i].base,8*bank+regspic16[i].offset);
3207 pic16_emitcode("dec","%s",r->name);
3210 pic16_emitcode("pop",""); //"(%s+%d)",
3211 //regspic16[i].base,8*bank); //+regspic16[i].offset);
3214 if (options.useXstack) {
3216 pic16_emitcode("mov","_spx,%s",r->name);
3217 pic16_freeAsmop(NULL,aop,ic,TRUE);
3223 /*-----------------------------------------------------------------*/
3224 /* saverbank - saves an entire register bank on the stack */
3225 /*-----------------------------------------------------------------*/
3226 static void saverbank (int bank, iCode *ic, bool pushPsw)
3228 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3234 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3235 if (options.useXstack) {
3238 r = getFreePtr(ic,&aop,FALSE);
3239 pic16_emitcode("mov","%s,_spx",r->name);
3243 for (i = 0 ; i < pic16_nRegs ;i++) {
3244 if (options.useXstack) {
3245 pic16_emitcode("inc","%s",r->name);
3246 //pic16_emitcode("mov","a,(%s+%d)",
3247 // regspic16[i].base,8*bank+regspic16[i].offset);
3248 pic16_emitcode("movx","@%s,a",r->name);
3250 pic16_emitcode("push","");// "(%s+%d)",
3251 //regspic16[i].base,8*bank+regspic16[i].offset);
3255 if (options.useXstack) {
3256 pic16_emitcode("mov","a,psw");
3257 pic16_emitcode("movx","@%s,a",r->name);
3258 pic16_emitcode("inc","%s",r->name);
3259 pic16_emitcode("mov","_spx,%s",r->name);
3260 pic16_freeAsmop (NULL,aop,ic,TRUE);
3263 pic16_emitcode("push","psw");
3265 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3273 static int wparamCmp(void *p1, void *p2)
3275 return (!strcmp((char *)p1, (char *)p2));
3278 int inWparamList(char *s)
3280 return isinSetWith(wparamList, s, wparamCmp);
3284 /*-----------------------------------------------------------------*/
3285 /* genCall - generates a call statement */
3286 /*-----------------------------------------------------------------*/
3287 static void genCall (iCode *ic)
3297 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3298 /* if caller saves & we have not saved then */
3299 // if (!ic->regsSaved)
3300 // saveRegisters(ic);
3302 /* initialise stackParms for IPUSH pushes */
3303 // stackParms = psuedoStkPtr;
3304 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3305 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3306 inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3309 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3312 /* if send set is not empty the assign */
3315 int psuedoStkPtr=-1;
3316 int firstTimeThruLoop = 1;
3319 /* reverse sendSet if function is not reentrant */
3320 if(!IFFUNC_ISREENT(ftype))
3321 _G.sendSet = reverseSet(_G.sendSet);
3323 /* First figure how many parameters are getting passed */
3327 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3331 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3332 size = AOP_SIZE(IC_LEFT(sic));
3336 /* pass the last byte through WREG */
3340 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3341 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3342 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3344 if(!firstTimeThruLoop) {
3345 /* If this is not the first time we've been through the loop
3346 * then we need to save the parameter in a temporary
3347 * register. The last byte of the last parameter is
3351 // --psuedoStkPtr; // sanity check
3355 firstTimeThruLoop=0;
3357 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3362 /* all arguments are passed via stack */
3366 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3367 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3368 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3370 // pushaop(AOP(IC_LEFT(sic)), size);
3371 pic16_mov2w( AOP(IC_LEFT(sic)), size );
3378 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3382 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3383 pushw(); /* save last parameter to stack if functions has varargs */
3387 } else use_wreg = 0;
3389 _G.stackRegSet = _G.sendSet;
3394 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3398 /* if we need to assign a result value */
3399 if ((IS_ITEMP(IC_RESULT(ic))
3400 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3401 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3402 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3405 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3408 /* Must not assign an 8-bit result to a 16-bit variable;
3409 * this would use (used...) the uninitialized PRODL! */
3410 /* FIXME: Need a proper way to obtain size of function result type,
3411 * OP_SYM_ETYPE does not work: it dereferences pointer types! */
3412 assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next), 1);
3414 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3415 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3417 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3420 if(!stackParms && ic->parmBytes) {
3421 stackParms = ic->parmBytes;
3424 stackParms -= use_wreg;
3427 if(stackParms == 1) {
3428 pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3430 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3431 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3433 if(STACK_MODEL_LARGE) {
3435 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3440 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3443 /* adjust the stack for parameters if required */
3444 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3447 /* if register bank was saved then pop them */
3449 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3451 /* if we hade saved some registers then unsave them */
3452 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3453 unsaveRegisters (ic);
3459 /*-----------------------------------------------------------------*/
3460 /* genPcall - generates a call by pointer statement */
3461 /* new version, created from genCall - HJD */
3462 /*-----------------------------------------------------------------*/
3463 static void genPcall (iCode *ic)
3467 symbol *retlbl = newiTempLabel(NULL);
3468 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3472 fntype = operandType( IC_LEFT(ic) )->next;
3474 /* if send set is not empty the assign */
3477 int psuedoStkPtr=-1;
3479 /* reverse sendSet if function is not reentrant */
3480 if(!IFFUNC_ISREENT(fntype))
3481 _G.sendSet = reverseSet(_G.sendSet);
3485 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3488 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3489 size = AOP_SIZE(IC_LEFT(sic));
3492 /* all parameters are passed via stack, since WREG is clobbered
3493 * by the calling sequence */
3495 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3496 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3497 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3499 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3503 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3506 _G.stackRegSet = _G.sendSet;
3510 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3512 // push return address
3513 // push $ on return stack, then replace with retlbl
3515 /* Thanks to Thorsten Klose for pointing out that the following
3516 * snippet should be interrupt safe */
3517 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3518 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3520 pic16_emitpcodeNULLop(POC_PUSH);
3522 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3523 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3524 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3525 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3526 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3527 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3530 /* restore interrupt control register */
3531 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3532 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3534 /* make the call by writing the pointer into pc */
3535 mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
3536 mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
3538 // note: MOVFF to PCL not allowed
3539 pic16_mov2w(AOP(IC_LEFT(ic)), 0);
3540 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3543 /* return address is here: (X) */
3544 pic16_emitpLabelFORCE(retlbl->key);
3546 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3549 /* if we need assign a result value */
3550 if ((IS_ITEMP(IC_RESULT(ic))
3551 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3552 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3553 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3556 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3559 /* FIXME: Need proper way to obtain the function result's type.
3560 * OP_SYM_TYPE(IC_LEFT(ic))->next does not work --> points to function pointer */
3561 assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next->next), 1);
3563 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3564 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3566 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3569 // stackParms -= use_wreg;
3572 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3573 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3574 if(STACK_MODEL_LARGE) {
3576 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3581 /*-----------------------------------------------------------------*/
3582 /* resultRemat - result is rematerializable */
3583 /*-----------------------------------------------------------------*/
3584 static int resultRemat (iCode *ic)
3586 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3587 if (SKIP_IC(ic) || ic->op == IFX)
3590 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3591 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3592 if (sym->remat && !POINTER_SET(ic))
3599 #if defined(__BORLANDC__) || defined(_MSC_VER)
3600 #define STRCASECMP stricmp
3602 #define STRCASECMP strcasecmp
3606 /*-----------------------------------------------------------------*/
3607 /* inExcludeList - return 1 if the string is in exclude Reg list */
3608 /*-----------------------------------------------------------------*/
3609 static bool inExcludeList(char *s)
3611 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3614 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3615 if (options.excludeRegs[i] &&
3616 STRCASECMP(options.excludeRegs[i],"none") == 0)
3619 for ( i = 0 ; options.excludeRegs[i]; i++) {
3620 if (options.excludeRegs[i] &&
3621 STRCASECMP(s,options.excludeRegs[i]) == 0)
3628 /*-----------------------------------------------------------------*/
3629 /* genFunction - generated code for function entry */
3630 /*-----------------------------------------------------------------*/
3631 static void genFunction (iCode *ic)
3637 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3639 pic16_labelOffset += (max_key+4);
3644 ftype = operandType(IC_LEFT(ic));
3645 sym = OP_SYMBOL(IC_LEFT(ic));
3647 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3648 /* create an absolute section at the interrupt vector:
3649 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3654 // debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3656 if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3657 sprintf(asymname, "ivec_%s", sym->name);
3659 sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3661 /* when an interrupt is declared as naked, do not emit the special
3662 * wrapper segment at vector address. The user should take care for
3663 * this instead. -- VR */
3665 if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3666 asym = newSymbol(asymname, 0);
3667 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3668 pic16_addpBlock( apb );
3670 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3671 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3672 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3673 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3674 pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3676 /* mark the end of this tiny function */
3677 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3679 sprintf(asymname, "%s", sym->rname);
3685 abSym = Safe_calloc(1, sizeof(absSym));
3686 strcpy(abSym->name, asymname);
3688 switch( FUNC_INTNO(sym->type) ) {
3689 case 0: abSym->address = 0x000000; break;
3690 case 1: abSym->address = 0x000008; break;
3691 case 2: abSym->address = 0x000018; break;
3694 // fprintf(stderr, "no interrupt number is given\n");
3695 abSym->address = -1; break;
3698 /* relocate interrupt vectors if needed */
3699 if(abSym->address != -1)
3700 abSym->address += pic16_options.ivt_loc;
3702 addSet(&absSymSet, abSym);
3706 /* create the function header */
3707 pic16_emitcode(";","-----------------------------------------");
3708 pic16_emitcode(";"," function %s",sym->name);
3709 pic16_emitcode(";","-----------------------------------------");
3711 /* prevent this symbol from being emitted as 'extern' */
3712 pic16_stringInSet(sym->rname, &pic16_localFunctions, 1);
3714 pic16_emitcode("","%s:",sym->rname);
3715 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3720 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3721 if(!strcmp(ab->name, sym->rname)) {
3722 pic16_pBlockConvert2Absolute(pb);
3728 if(IFFUNC_ISNAKED(ftype)) {
3729 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3733 /* if critical function then turn interrupts off */
3734 if (IFFUNC_ISCRITICAL(ftype)) {
3735 //pic16_emitcode("clr","ea");
3738 currFunc = sym; /* update the currFunc symbol */
3739 _G.fregsUsed = sym->regsUsed;
3740 _G.sregsAlloc = newBitVect(128);
3743 /* if this is an interrupt service routine then
3744 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3745 if (IFFUNC_ISISR(sym->type)) {
3746 _G.usefastretfie = 1; /* use shadow registers by default */
3748 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3749 if(!FUNC_ISSHADOWREGS(sym->type)) {
3750 /* do not save WREG,STATUS,BSR for high priority interrupts
3751 * because they are stored in the hardware shadow registers already */
3752 _G.usefastretfie = 0;
3753 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3754 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3755 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3758 /* these should really be optimized somehow, because not all
3759 * interrupt handlers modify them */
3760 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3761 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3762 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3763 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3764 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3765 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3767 // pic16_pBlockConvert2ISR(pb);
3770 /* emit code to setup stack frame if user enabled,
3771 * and function is not main() */
3773 // debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3774 if(strcmp(sym->name, "main")) {
3776 || !options.ommitFramePtr
3778 || IFFUNC_ARGS(sym->type)
3779 || FUNC_HASSTACKPARM(sym->etype)
3781 /* setup the stack frame */
3782 if(STACK_MODEL_LARGE)
3783 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3784 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3786 if(STACK_MODEL_LARGE)
3787 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3788 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3792 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3795 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3797 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3798 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3800 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3803 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3804 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3811 /* if callee-save to be used for this function
3812 * then save the registers being used in this function */
3813 // if (IFFUNC_CALLEESAVES(sym->type))
3814 if(strcmp(sym->name, "main")) {
3817 /* if any registers used */
3818 if (sym->regsUsed) {
3819 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3822 /* save the registers used */
3823 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3824 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3825 if (bitVectBitValue(sym->regsUsed,i)) {
3827 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3829 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3832 if(!pic16_regWithIdx(i)->wasUsed) {
3833 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3834 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3835 pic16_regWithIdx(i)->wasUsed = 1;
3842 DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3843 for(i=0;i<sym->regsUsed->size;i++) {
3844 if(bitVectBitValue(sym->regsUsed, i)) {
3849 // pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3852 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3857 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3858 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3861 /*-----------------------------------------------------------------*/
3862 /* genEndFunction - generates epilogue for functions */
3863 /*-----------------------------------------------------------------*/
3864 static void genEndFunction (iCode *ic)
3866 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3870 if(IFFUNC_ISNAKED(sym->type)) {
3871 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3877 /* add code for ISCRITICAL */
3878 if(IFFUNC_ISCRITICAL(sym->type)) {
3879 /* if critical function, turn on interrupts */
3881 /* TODO: add code here -- VR */
3884 // sym->regsUsed = _G.fregsUsed;
3886 /* now we need to restore the registers */
3887 /* if any registers used */
3889 /* first restore registers that might be used for stack access */
3890 if(_G.sregsAllocSet) {
3893 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3894 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3895 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3899 if (strcmp(sym->name, "main") && sym->regsUsed) {
3902 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3903 /* restore registers used */
3904 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3905 for ( i = sym->regsUsed->size; i >= 0; i--) {
3906 if (bitVectBitValue(sym->regsUsed,i)) {
3907 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3911 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3916 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3918 if (sym->stack == 1) {
3919 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3920 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3922 // we have to add more than one...
3923 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3924 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3925 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3927 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3928 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3929 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3933 if(strcmp(sym->name, "main")) {
3935 || !options.ommitFramePtr
3937 || IFFUNC_ARGS(sym->type)
3938 || FUNC_HASSTACKPARM(sym->etype)
3940 /* restore stack frame */
3941 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3942 if(STACK_MODEL_LARGE)
3943 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3949 if (IFFUNC_ISISR(sym->type)) {
3950 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3951 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3952 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3953 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3954 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3955 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3957 if(!FUNC_ISSHADOWREGS(sym->type)) {
3958 /* do not restore interrupt vector for WREG,STATUS,BSR
3959 * for high priority interrupt, see genFunction */
3960 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3961 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3962 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3964 // _G.interruptvector = 0; /* sanity check */
3967 /* if debug then send end of function */
3968 /* if (options.debug && currFunc) */
3970 debugFile->writeEndFunction (currFunc, ic, 1);
3973 if(_G.usefastretfie)
3974 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3976 pic16_emitpcodeNULLop(POC_RETFIE);
3978 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3980 _G.usefastretfie = 0;
3984 if (IFFUNC_ISCRITICAL(sym->type)) {
3985 pic16_emitcode("setb","ea");
3988 /* if debug then send end of function */
3990 debugFile->writeEndFunction (currFunc, ic, 1);
3993 /* insert code to restore stack frame, if user enabled it
3994 * and function is not main() */
3997 pic16_emitpcodeNULLop(POC_RETURN);
3999 /* Mark the end of a function */
4000 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
4004 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
4006 unsigned long lit=1;
4011 // this fails for is_LitOp(op) (if op is an AOP_PCODE)
4012 if(AOP_TYPE(op) == AOP_LIT) {
4013 if(!IS_FLOAT(operandType( op ))) {
4014 lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
4017 unsigned long lit_int;
4021 /* take care if literal is a float */
4022 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
4027 if (AOP_TYPE(op) == AOP_LIT) {
4028 /* FIXME: broken for
4029 * char __at(0x456) foo;
4031 * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */
4032 pic16_movLit2f(dest, (lit >> (8ul*offset)));
4033 } else if (AOP_TYPE(op) == AOP_PCODE
4034 && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
4035 /* char *s= "aaa"; return s; */
4036 /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so
4037 * that the generic pointer is interpreted correctly
4038 * as referring to __code space, but this is fragile! */
4039 pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset ));
4040 /* XXX: should check that dest != WREG */
4041 pic16_emitpcode(POC_MOVWF, dest);
4043 if(dest->type == PO_WREG && (offset == 0)) {
4044 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4047 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4051 /*-----------------------------------------------------------------*/
4052 /* genRet - generate code for return statement */
4053 /*-----------------------------------------------------------------*/
4054 static void genRet (iCode *ic)
4060 /* if we have no return value then
4061 * just generate the "ret" */
4066 /* we have something to return then
4067 * move the return value into place */
4068 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4069 size = AOP_SIZE(IC_LEFT(ic));
4073 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4076 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4079 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4081 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4084 /* >32-bits, setup stack and FSR0 */
4086 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4087 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4089 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4091 // popaopidx(AOP(oper), size, GpseudoStkPtr);
4096 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4097 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4099 if(STACK_MODEL_LARGE) {
4100 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4101 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4103 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4108 /* old code, left here for reference -- VR */
4112 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4114 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4115 pic16_emitpcomment("push %s",l);
4118 DEBUGpic16_emitcode(";", "%d", __LINE__);
4119 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4120 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
4122 if (strcmp(fReturn[offset],l)) {
4123 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4124 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4125 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4127 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4131 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4141 if (strcmp(fReturn[pushed],"a"))
4142 pic16_emitcode("pop",fReturn[pushed]);
4144 pic16_emitcode("pop","acc");
4150 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4153 /* generate a jump to the return label
4154 * if the next is not the return statement */
4155 if (!(ic->next && ic->next->op == LABEL
4156 && IC_LABEL(ic->next) == returnLabel)) {
4158 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4159 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4163 /*-----------------------------------------------------------------*/
4164 /* genLabel - generates a label */
4165 /*-----------------------------------------------------------------*/
4166 static void genLabel (iCode *ic)
4170 /* special case never generate */
4171 if (IC_LABEL(ic) == entryLabel)
4174 pic16_emitpLabel(IC_LABEL(ic)->key);
4175 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4178 /*-----------------------------------------------------------------*/
4179 /* genGoto - generates a goto */
4180 /*-----------------------------------------------------------------*/
4182 static void genGoto (iCode *ic)
4185 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4186 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4190 /*-----------------------------------------------------------------*/
4191 /* genMultbits :- multiplication of bits */
4192 /*-----------------------------------------------------------------*/
4193 static void genMultbits (operand *left,
4199 if(!pic16_sameRegs(AOP(result),AOP(right)))
4200 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
4202 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4203 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4204 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4209 /*-----------------------------------------------------------------*/
4210 /* genMultOneByte : 8 bit multiplication & division */
4211 /*-----------------------------------------------------------------*/
4212 static void genMultOneByte (operand *left,
4218 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4219 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4221 /* (if two literals, the value is computed before) */
4222 /* if one literal, literal on the right */
4223 if (AOP_TYPE(left) == AOP_LIT){
4229 /* size is already checked in genMult == 1 */
4230 // size = AOP_SIZE(result);
4232 if (AOP_TYPE(right) == AOP_LIT){
4233 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4234 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4235 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4236 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4238 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4239 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4240 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4241 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4244 pic16_genMult8X8_n (left, right,result);
4248 /*-----------------------------------------------------------------*/
4249 /* genMultOneWord : 16 bit multiplication */
4250 /*-----------------------------------------------------------------*/
4251 static void genMultOneWord (operand *left,
4256 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4257 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4259 /* (if two literals, the value is computed before)
4260 * if one literal, literal on the right */
4261 if (AOP_TYPE(left) == AOP_LIT){
4267 /* size is checked already == 2 */
4268 // size = AOP_SIZE(result);
4270 if (AOP_TYPE(right) == AOP_LIT) {
4271 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4272 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4273 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4274 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4276 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4277 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4278 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4279 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4282 pic16_genMult16X16_16(left, right,result);
4287 /*-----------------------------------------------------------------*/
4288 /* genMultOneLong : 32 bit multiplication */
4289 /*-----------------------------------------------------------------*/
4290 static void genMultOneLong (operand *left,
4295 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4296 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4298 /* (if two literals, the value is computed before)
4299 * if one literal, literal on the right */
4300 if (AOP_TYPE(left) == AOP_LIT){
4306 /* size is checked already == 4 */
4307 // size = AOP_SIZE(result);
4309 if (AOP_TYPE(right) == AOP_LIT) {
4310 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4311 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4312 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4313 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4315 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4316 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4317 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4318 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4321 pic16_genMult32X32_32(left, right,result);
4327 /*-----------------------------------------------------------------*/
4328 /* genMult - generates code for multiplication */
4329 /*-----------------------------------------------------------------*/
4330 static void genMult (iCode *ic)
4332 operand *left = IC_LEFT(ic);
4333 operand *right = IC_RIGHT(ic);
4334 operand *result= IC_RESULT(ic);
4337 /* assign the amsops */
4338 pic16_aopOp (left,ic,FALSE);
4339 pic16_aopOp (right,ic,FALSE);
4340 pic16_aopOp (result,ic,TRUE);
4342 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4344 /* special cases first *
4346 if (AOP_TYPE(left) == AOP_CRY
4347 && AOP_TYPE(right)== AOP_CRY) {
4348 genMultbits(left,right,result);
4352 /* if both are of size == 1 */
4353 if(AOP_SIZE(left) == 1
4354 && AOP_SIZE(right) == 1) {
4355 genMultOneByte(left,right,result);
4360 /* if both are of size == 2 */
4361 if(AOP_SIZE(left) == 2
4362 && AOP_SIZE(right) == 2) {
4363 genMultOneWord(left, right, result);
4367 /* if both are of size == 4 */
4368 if(AOP_SIZE(left) == 4
4369 && AOP_SIZE(right) == 4) {
4370 genMultOneLong(left, right, result);
4375 fprintf( stderr, "%s: should have been transformed into function call\n",__FUNCTION__ );
4376 assert( !"Multiplication should have been transformed into function call!" );
4378 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4381 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4382 /* should have been converted to function call */
4386 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4387 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4388 pic16_freeAsmop(result,NULL,ic,TRUE);
4392 /*-----------------------------------------------------------------*/
4393 /* genDivbits :- division of bits */
4394 /*-----------------------------------------------------------------*/
4395 static void genDivbits (operand *left,
4402 /* the result must be bit */
4403 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4404 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4408 pic16_emitcode("div","ab");
4409 pic16_emitcode("rrc","a");
4410 pic16_aopPut(AOP(result),"c",0);
4413 /*-----------------------------------------------------------------*/
4414 /* genDivOneByte : 8 bit division */
4415 /*-----------------------------------------------------------------*/
4416 static void genDivOneByte (operand *left,
4420 sym_link *opetype = operandType(result);
4425 /* result = divident / divisor
4426 * - divident may be a register or a literal,
4427 * - divisor may be a register or a literal,
4428 * so there are 3 cases (literal / literal is optimized
4429 * by the front-end) to handle.
4430 * In addition we must handle signed and unsigned, which
4431 * result in 6 final different cases -- VR */
4435 size = AOP_SIZE(result) - 1;
4437 /* signed or unsigned */
4438 if (SPEC_USIGN(opetype)) {
4439 pCodeOp *pct1, /* count */
4442 symbol *label1, *label2, *label3;;
4445 /* unsigned is easy */
4447 pct1 = pic16_popGetTempReg(1);
4448 pct2 = pic16_popGetTempReg(1);
4449 pct3 = pic16_popGetTempReg(1);
4451 label1 = newiTempLabel(NULL);
4452 label2 = newiTempLabel(NULL);
4453 label3 = newiTempLabel(NULL);
4455 /* the following algorithm is extracted from divuint.c */
4457 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4458 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4460 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4462 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4464 pic16_emitpLabel(label1->key);
4467 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4471 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4475 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4477 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4478 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4480 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4481 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4482 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4484 pic16_emitpLabel( label3->key );
4485 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4486 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4490 pic16_emitpLabel(label2->key);
4491 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4492 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4493 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4495 /* result is in wreg */
4496 if(AOP_TYPE(result) != AOP_ACC)
4497 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4499 pic16_popReleaseTempReg( pct3, 1);
4500 pic16_popReleaseTempReg( pct2, 1);
4501 pic16_popReleaseTempReg( pct1, 1);
4506 /* signed is a little bit more difficult */
4508 /* save the signs of the operands */
4509 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4511 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4512 pic16_emitcode("push","acc"); /* save it on the stack */
4514 /* now sign adjust for both left & right */
4515 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4517 lbl = newiTempLabel(NULL);
4518 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4519 pic16_emitcode("cpl","a");
4520 pic16_emitcode("inc","a");
4521 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4522 pic16_emitcode("mov","b,a");
4524 /* sign adjust left side */
4525 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4528 lbl = newiTempLabel(NULL);
4529 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4530 pic16_emitcode("cpl","a");
4531 pic16_emitcode("inc","a");
4532 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4534 /* now the division */
4535 pic16_emitcode("div","ab");
4536 /* we are interested in the lower order
4538 pic16_emitcode("mov","b,a");
4539 lbl = newiTempLabel(NULL);
4540 pic16_emitcode("pop","acc");
4541 /* if there was an over flow we don't
4542 adjust the sign of the result */
4543 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4544 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4546 pic16_emitcode("clr","a");
4547 pic16_emitcode("subb","a,b");
4548 pic16_emitcode("mov","b,a");
4549 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4551 /* now we are done */
4552 pic16_aopPut(AOP(result),"b",0);
4554 pic16_emitcode("mov","c,b.7");
4555 pic16_emitcode("subb","a,acc");
4558 pic16_aopPut(AOP(result),"a",offset++);
4563 /*-----------------------------------------------------------------*/
4564 /* genDiv - generates code for division */
4565 /*-----------------------------------------------------------------*/
4566 static void genDiv (iCode *ic)
4568 operand *left = IC_LEFT(ic);
4569 operand *right = IC_RIGHT(ic);
4570 operand *result= IC_RESULT(ic);
4572 int leftVal = 0, rightVal = 0;
4574 char *functions[2][2] = { { "__divschar", "__divuchar" }, { "__modschar", "__moduchar" } };
4577 /* Division is a very lengthy algorithm, so it is better
4578 * to call support routines than inlining algorithm.
4579 * Division functions written here just in case someone
4580 * wants to inline and not use the support libraries -- VR */
4584 /* assign the amsops */
4585 pic16_aopOp (left,ic,FALSE);
4586 pic16_aopOp (right,ic,FALSE);
4587 pic16_aopOp (result,ic,TRUE);
4591 else if (ic->op == '%')
4594 assert( !"invalid operation requested in genDivMod" );
4596 /* get literal values */
4597 if (IS_VALOP(left)) {
4598 leftVal = (int)floatFromVal( OP_VALUE(left) );
4599 assert( leftVal >= -128 && leftVal < 256 );
4600 if (leftVal < 0) { signedLits++; }
4602 if (IS_VALOP(right)) {
4603 rightVal = (int)floatFromVal( OP_VALUE(right) );
4604 assert( rightVal >= -128 && rightVal < 256 );
4605 if (rightVal < 0) { signedLits++; }
4608 /* We should only come here to convert all
4609 * / : {u8_t, s8_t} x {u8_t, s8_t} -> {u8_t, s8_t}
4610 * with exactly one operand being s8_t into
4611 * u8_t x u8_t -> u8_t. All other cases should have been
4612 * turned into calls to support routines beforehand... */
4613 if ((AOP_SIZE(left) == 1 || IS_VALOP(left))
4614 && (AOP_SIZE(right) == 1 || IS_VALOP(right)))
4616 if ((!IS_UNSIGNED(operandType(right)) || rightVal < 0)
4617 && (!IS_UNSIGNED(operandType(left)) || leftVal < 0))
4619 /* Both operands are signed or negative, use _divschar
4620 * instead of _divuchar */
4621 pushaop(AOP(right), 0);
4622 pushaop(AOP(left), 0);
4624 /* call _divschar */
4625 pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][0]));
4629 sym = newSymbol( functions[op][0], 0 );
4631 strcpy(sym->rname, functions[op][0]);
4632 checkAddSym(&externs, sym);
4636 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4637 if (AOP_SIZE(result) > 1)
4639 pic16_emitpcode(POC_MOVFF,
4640 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
4641 pic16_popGet(AOP(result), 1)));
4643 pic16_addSign(result, 2, 1);
4646 /* clean up stack */
4647 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4648 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4653 /* push right operand */
4654 if (IS_VALOP(right)) {
4656 pic16_pushpCodeOp( pic16_popGetLit(-rightVal) );
4659 pushaop(AOP(right), 0);
4661 } else if (!IS_UNSIGNED(operandType(right))) {
4662 pic16_mov2w(AOP(right), 0);
4663 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4664 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4665 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
4668 pushaop(AOP(right), 0);
4671 /* push left operand */
4672 if (IS_VALOP(left)) {
4674 pic16_pushpCodeOp(pic16_popGetLit(-leftVal));
4677 pushaop(AOP(left), 0);
4679 } else if (!IS_UNSIGNED(operandType(left))) {
4680 pic16_mov2w(AOP(left),0);
4681 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4682 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4683 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
4686 pushaop(AOP(left), 0);
4689 /* call _divuchar */
4690 pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][1]));
4694 sym = newSymbol( functions[op][1], 0 );
4696 strcpy(sym->rname, functions[op][1]);
4697 checkAddSym(&externs, sym);
4700 /* Revert negation(s) from above.
4701 * This is inefficient: if both operands are negative, this
4702 * should not touch WREG. However, determining that exactly
4703 * one operand was negated costs at least 3 instructions,
4704 * so there is nothing to be gained here, is there?
4706 * I negate WREG because either operand might share registers with
4707 * result, so assigning first might destroy an operand. */
4709 /* For the modulus operator, (a/b)*b == a shall hold.
4710 * Thus: a>0, b>0 --> a/b >= 0 and a%b >= 0
4711 * a>0, b<0 --> a/b <= 0 and a%b >= 0 (e.g. 128 / -5 = -25, -25*(-5) = 125 and +3 remaining)
4712 * a<0, b>0 --> a/b <= 0 and a%b < 0 (e.g. -128 / 5 = -25, -25* 5 = -125 and -3 remaining)
4713 * a<0, b<0 --> a/b >= 0 and a%b < 0 (e.g. -128 / -5 = 25, 25*(-5) = -125 and -3 remaining)
4714 * Only invert the result if the left operand is negative (sigh).
4716 if (AOP_SIZE(result) <= 1 || !negated)
4720 if (IS_VALOP(right)) {
4722 /* we negated this operand above */
4723 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4725 } else if (!IS_UNSIGNED(operandType(right))) {
4726 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4727 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4731 if (IS_VALOP(left)) {
4733 /* we negated this operand above */
4734 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4736 } else if (!IS_UNSIGNED(operandType(left))) {
4737 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4738 pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4741 /* Move result to destination. */
4742 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4744 /* Zero-extend: no operand was signed (or result is just a byte). */
4745 pic16_addSign(result, 1, 0);
4747 assert( AOP_SIZE(result) > 1 );
4748 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1));
4751 if (IS_VALOP(right)) {
4753 /* we negated this operand above */
4754 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4756 } else if (!IS_UNSIGNED(operandType(right))) {
4757 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4758 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4762 if (IS_VALOP(left)) {
4764 /* we negated this operand above */
4765 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4767 } else if (!IS_UNSIGNED(operandType(left))) {
4768 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4769 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4772 /* Move result to destination. */
4773 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4775 /* Negate result if required. */
4776 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(result), 1, 7));
4777 pic16_emitpcode(POC_NEGF, pic16_popGet(AOP(result), 0));
4780 pic16_addSign(result, 2, 1);
4783 /* clean up stack */
4784 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4785 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4790 /* special cases first */
4792 if (AOP_TYPE(left) == AOP_CRY &&
4793 AOP_TYPE(right)== AOP_CRY) {
4794 genDivbits(left,right,result);
4798 /* if both are of size == 1 */
4799 if (AOP_SIZE(left) == 1 &&
4800 AOP_SIZE(right) == 1 ) {
4801 genDivOneByte(left,right,result);
4806 /* should have been converted to function call */
4809 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4810 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4811 pic16_freeAsmop(result,NULL,ic,TRUE);
4815 /*-----------------------------------------------------------------*/
4816 /* genModbits :- modulus of bits */
4817 /*-----------------------------------------------------------------*/
4818 static void genModbits (operand *left,
4826 werror(W_POSSBUG2, __FILE__, __LINE__);
4827 /* the result must be bit */
4828 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4829 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4833 pic16_emitcode("div","ab");
4834 pic16_emitcode("mov","a,b");
4835 pic16_emitcode("rrc","a");
4836 pic16_aopPut(AOP(result),"c",0);
4839 /*-----------------------------------------------------------------*/
4840 /* genModOneByte : 8 bit modulus */
4841 /*-----------------------------------------------------------------*/
4842 static void genModOneByte (operand *left,
4846 sym_link *opetype = operandType(result);
4851 werror(W_POSSBUG2, __FILE__, __LINE__);
4853 /* signed or unsigned */
4854 if (SPEC_USIGN(opetype)) {
4855 /* unsigned is easy */
4856 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4857 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4859 pic16_emitcode("div","ab");
4860 pic16_aopPut(AOP(result),"b",0);
4864 /* signed is a little bit more difficult */
4866 /* save the signs of the operands */
4867 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4870 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4871 pic16_emitcode("push","acc"); /* save it on the stack */
4873 /* now sign adjust for both left & right */
4874 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4877 lbl = newiTempLabel(NULL);
4878 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4879 pic16_emitcode("cpl","a");
4880 pic16_emitcode("inc","a");
4881 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4882 pic16_emitcode("mov","b,a");
4884 /* sign adjust left side */
4885 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4888 lbl = newiTempLabel(NULL);
4889 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4890 pic16_emitcode("cpl","a");
4891 pic16_emitcode("inc","a");
4892 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4894 /* now the multiplication */
4895 pic16_emitcode("div","ab");
4896 /* we are interested in the lower order
4898 lbl = newiTempLabel(NULL);
4899 pic16_emitcode("pop","acc");
4900 /* if there was an over flow we don't
4901 adjust the sign of the result */
4902 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4903 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4905 pic16_emitcode("clr","a");
4906 pic16_emitcode("subb","a,b");
4907 pic16_emitcode("mov","b,a");
4908 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4910 /* now we are done */
4911 pic16_aopPut(AOP(result),"b",0);
4916 /*-----------------------------------------------------------------*/
4917 /* genMod - generates code for division */
4918 /*-----------------------------------------------------------------*/
4919 static void genMod (iCode *ic)
4921 /* Task deferred to genDiv */
4924 operand *left = IC_LEFT(ic);
4925 operand *right = IC_RIGHT(ic);
4926 operand *result= IC_RESULT(ic);
4930 /* assign the amsops */
4931 pic16_aopOp (left,ic,FALSE);
4932 pic16_aopOp (right,ic,FALSE);
4933 pic16_aopOp (result,ic,TRUE);
4935 /* special cases first */
4937 if (AOP_TYPE(left) == AOP_CRY &&
4938 AOP_TYPE(right)== AOP_CRY) {
4939 genModbits(left,right,result);
4943 /* if both are of size == 1 */
4944 if (AOP_SIZE(left) == 1 &&
4945 AOP_SIZE(right) == 1 ) {
4946 genModOneByte(left,right,result);
4950 /* should have been converted to function call */
4954 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4955 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4956 pic16_freeAsmop(result,NULL,ic,TRUE);
4960 /*-----------------------------------------------------------------*/
4961 /* genIfxJump :- will create a jump depending on the ifx */
4962 /*-----------------------------------------------------------------*/
4964 note: May need to add parameter to indicate when a variable is in bit space.
4966 static void genIfxJump (iCode *ic, char *jval)
4970 /* if true label then we jump if condition
4972 if ( IC_TRUE(ic) ) {
4974 if(strcmp(jval,"a") == 0)
4976 else if (strcmp(jval,"c") == 0)
4979 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4980 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4983 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4984 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4988 /* false label is present */
4989 if(strcmp(jval,"a") == 0)
4991 else if (strcmp(jval,"c") == 0)
4994 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4995 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4998 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4999 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
5004 /* mark the icode as generated */
5008 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
5012 /* if true label then we jump if condition
5014 if ( IC_TRUE(ic) ) {
5015 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
5016 pic16_emitpcode(POC_BTFSC, jop);
5018 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
5019 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
5022 /* false label is present */
5023 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
5024 pic16_emitpcode(POC_BTFSS, jop);
5026 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
5027 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
5031 /* mark the icode as generated */
5038 /*-----------------------------------------------------------------*/
5040 /*-----------------------------------------------------------------*/
5041 static void genSkip(iCode *ifx,int status_bit)
5043 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5047 if ( IC_TRUE(ifx) ) {
5048 switch(status_bit) {
5063 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5064 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5068 switch(status_bit) {
5082 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5083 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5090 /*-----------------------------------------------------------------*/
5092 /*-----------------------------------------------------------------*/
5093 static void genSkipc(resolvedIfx *rifx)
5095 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
5105 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
5106 rifx->generated = 1;
5109 #if !(USE_SIMPLE_GENCMP)
5110 /*-----------------------------------------------------------------*/
5112 /*-----------------------------------------------------------------*/
5113 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
5115 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
5120 if( (rifx->condition ^ invert_condition) & 1)
5125 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
5126 rifx->generated = 1;
5131 /*-----------------------------------------------------------------*/
5133 /*-----------------------------------------------------------------*/
5134 static void genSkipz(iCode *ifx, int condition)
5145 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5147 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5150 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5152 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5157 #if !(USE_SIMPLE_GENCMP)
5158 /*-----------------------------------------------------------------*/
5160 /*-----------------------------------------------------------------*/
5161 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
5167 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
5169 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
5172 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
5173 rifx->generated = 1;
5178 /*-----------------------------------------------------------------*/
5179 /* genChkZeroes :- greater or less than comparison */
5180 /* For each byte in a literal that is zero, inclusive or the */
5181 /* the corresponding byte in the operand with W */
5182 /* returns true if any of the bytes are zero */
5183 /*-----------------------------------------------------------------*/
5184 static int genChkZeroes(operand *op, int lit, int size)
5191 i = (lit >> (size*8)) & 0xff;
5195 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
5197 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
5207 /*-----------------------------------------------------------------*/
5208 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
5209 /* aop (if it's NOT a literal) or from lit (if */
5210 /* aop is a literal) */
5211 /*-----------------------------------------------------------------*/
5212 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
5213 if (aop->type == AOP_LIT) {
5214 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
5216 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
5220 /*-----------------------------------------------------------------*/
5221 /* genCmp :- greater or less than comparison */
5222 /*-----------------------------------------------------------------*/
5224 #if USE_SIMPLE_GENCMP /* { */
5226 /* genCmp performs a left < right comparison, stores
5227 * the outcome in result (if != NULL) and generates
5228 * control flow code for the ifx (if != NULL).
5230 * This version leaves in sequences like
5231 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
5232 * which should be optmized by the peephole
5233 * optimizer - RN 2005-01-01 */
5234 static void genCmp (operand *left,operand *right,
5235 operand *result, iCode *ifx, int sign)
5248 assert (left && right);
5249 assert (AOP_SIZE(left) == AOP_SIZE(right));
5251 size = AOP_SIZE(right) - 1;
5252 mask = (0x100UL << (size*8)) - 1;
5253 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5258 resolveIfx (&rIfx, ifx);
5260 /* handle for special cases */
5261 if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5264 /**********************************************************************
5265 * handle bits - bit compares are promoted to int compares seemingly! *
5266 **********************************************************************/
5268 // THIS IS COMPLETELY UNTESTED!
5269 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5270 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5271 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5272 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5275 // 1 < {0,1} is false --> clear C by skipping the next instruction
5276 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5277 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5278 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5279 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5280 emitCLRC; // only skipped for left=0 && right=1
5282 goto correct_result_in_carry;
5286 /*************************************************
5287 * make sure that left is register (or the like) *
5288 *************************************************/
5289 if (!isAOP_REGlike(left)) {
5290 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5291 assert (isAOP_LIT(left));
5292 assert (isAOP_REGlike(right));
5293 // swap left and right
5294 // left < right <==> right > left <==> (right >= left + 1)
5295 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5297 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5298 // MAXVALUE < right? always false
5299 if (performedLt) emitCLRC; else emitSETC;
5300 goto correct_result_in_carry;
5303 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5304 // that's why we handled it above.
5311 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5312 } else if (isAOP_LIT(right)) {
5313 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5316 assert (isAOP_REGlike(left)); // left must be register or the like
5317 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5319 /*************************************************
5320 * special cases go here *
5321 *************************************************/
5323 if (isAOP_LIT(right)) {
5325 // unsigned comparison to a literal
5326 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5328 // unsigned left < 0? always false
5329 if (performedLt) emitCLRC; else emitSETC;
5330 goto correct_result_in_carry;
5333 // signed comparison to a literal
5334 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5335 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5336 // signed left < 0x80000000? always false
5337 if (performedLt) emitCLRC; else emitSETC;
5338 goto correct_result_in_carry;
5339 } else if (lit == 0) {
5340 // compare left < 0; set CARRY if SIGNBIT(left) is set
5341 if (performedLt) emitSETC; else emitCLRC;
5342 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5343 if (performedLt) emitCLRC; else emitSETC;
5344 goto correct_result_in_carry;
5347 } // right is literal
5349 /*************************************************
5350 * perform a general case comparison *
5351 * make sure we get CARRY==1 <==> left >= right *
5352 *************************************************/
5353 // compare most significant bytes
5354 //DEBUGpc ("comparing bytes at offset %d", size);
5356 // unsigned comparison
5357 mov2w_regOrLit (AOP(right), lit, size);
5358 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5360 // signed comparison
5361 // (add 2^n to both operands then perform an unsigned comparison)
5362 if (isAOP_LIT(right)) {
5363 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5364 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5366 if (litbyte == 0x80) {
5367 // left >= 0x80 -- always true, but more bytes to come
5368 pic16_mov2w (AOP(left), size);
5369 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5372 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5373 pic16_mov2w (AOP(left), size);
5374 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5375 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5378 /* using PRODL as a temporary register here */
5379 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5380 //pCodeOp *pctemp = pic16_popGetTempReg(1);
5381 pic16_mov2w (AOP(left), size);
5382 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5383 pic16_emitpcode (POC_MOVWF, pctemp);
5384 pic16_mov2w (AOP(right), size);
5385 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5386 pic16_emitpcode (POC_SUBFW, pctemp);
5387 //pic16_popReleaseTempReg(pctemp, 1);
5391 // compare remaining bytes (treat as unsigned case from above)
5392 templbl = newiTempLabel ( NULL );
5395 //DEBUGpc ("comparing bytes at offset %d", offs);
5396 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5397 mov2w_regOrLit (AOP(right), lit, offs);
5398 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5400 pic16_emitpLabel (templbl->key);
5401 goto result_in_carry;
5405 /****************************************************
5406 * now CARRY contains the result of the comparison: *
5407 * SUBWF sets CARRY iff *
5408 * F-W >= 0 <==> F >= W <==> !(F < W) *
5409 * (F=left, W=right) *
5410 ****************************************************/
5413 if (result && AOP_TYPE(result) != AOP_CRY) {
5414 // value will be stored
5417 // value wil only be used in the following genSkipc()
5418 rIfx.condition ^= 1;
5422 correct_result_in_carry:
5424 // assign result to variable (if neccessary)
5425 if (result && AOP_TYPE(result) != AOP_CRY) {
5426 //DEBUGpc ("assign result");
5427 size = AOP_SIZE(result);
5429 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5431 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5434 // perform conditional jump
5436 //DEBUGpc ("generate control flow");
5445 static void genCmp (operand *left,operand *right,
5446 operand *result, iCode *ifx, int sign)
5448 int size; //, offset = 0 ;
5449 unsigned long lit = 0L,i = 0;
5450 resolvedIfx rFalseIfx;
5451 // resolvedIfx rTrueIfx;
5453 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5456 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5457 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5463 resolveIfx(&rFalseIfx,ifx);
5464 truelbl = newiTempLabel(NULL);
5465 size = max(AOP_SIZE(left),AOP_SIZE(right));
5467 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5471 /* if literal is on the right then swap with left */
5472 if ((AOP_TYPE(right) == AOP_LIT)) {
5473 operand *tmp = right ;
5474 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5475 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5478 lit = (lit - 1) & mask;
5481 rFalseIfx.condition ^= 1;
5484 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5485 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5489 //if(IC_TRUE(ifx) == NULL)
5490 /* if left & right are bit variables */
5491 if (AOP_TYPE(left) == AOP_CRY &&
5492 AOP_TYPE(right) == AOP_CRY ) {
5493 assert (0 && "bit variables used in genCmp");
5494 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5495 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5497 /* subtract right from left if at the
5498 end the carry flag is set then we know that
5499 left is greater than right */
5501 symbol *lbl = newiTempLabel(NULL);
5504 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5505 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5509 if(AOP_TYPE(right) == AOP_LIT) {
5511 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5513 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5520 genSkipCond(&rFalseIfx,left,size-1,7);
5522 /* no need to compare to 0...*/
5523 /* NOTE: this is a de-generate compare that most certainly
5524 * creates some dead code. */
5525 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5527 if(ifx) ifx->generated = 1;
5534 //i = (lit >> (size*8)) & 0xff;
5535 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5537 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5539 i = ((0-lit) & 0xff);
5542 /* lit is 0x7f, all signed chars are less than
5543 * this except for 0x7f itself */
5544 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5545 genSkipz2(&rFalseIfx,0);
5547 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5548 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5549 genSkipc(&rFalseIfx);
5554 genSkipz2(&rFalseIfx,1);
5556 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5557 genSkipc(&rFalseIfx);
5561 if(ifx) ifx->generated = 1;
5565 /* chars are out of the way. now do ints and longs */
5568 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5575 genSkipCond(&rFalseIfx,left,size,7);
5576 if(ifx) ifx->generated = 1;
5581 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5583 //rFalseIfx.condition ^= 1;
5584 //genSkipCond(&rFalseIfx,left,size,7);
5585 //rFalseIfx.condition ^= 1;
5587 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5588 if(rFalseIfx.condition)
5589 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5591 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5593 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5594 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5595 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5598 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5600 if(rFalseIfx.condition) {
5602 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5608 genSkipc(&rFalseIfx);
5609 pic16_emitpLabel(truelbl->key);
5610 if(ifx) ifx->generated = 1;
5617 if( (lit & 0xff) == 0) {
5618 /* lower byte is zero */
5619 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5620 i = ((lit >> 8) & 0xff) ^0x80;
5621 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5622 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5623 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5624 genSkipc(&rFalseIfx);
5627 if(ifx) ifx->generated = 1;
5632 /* Special cases for signed longs */
5633 if( (lit & 0xffffff) == 0) {
5634 /* lower byte is zero */
5635 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5636 i = ((lit >> 8*3) & 0xff) ^0x80;
5637 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5638 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5639 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5640 genSkipc(&rFalseIfx);
5643 if(ifx) ifx->generated = 1;
5651 if(lit & (0x80 << (size*8))) {
5652 /* lit is negative */
5653 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5655 //genSkipCond(&rFalseIfx,left,size,7);
5657 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5659 if(rFalseIfx.condition)
5660 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5662 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5666 /* lit is positive */
5667 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5668 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5669 if(rFalseIfx.condition)
5670 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5672 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5677 This works, but is only good for ints.
5678 It also requires a "known zero" register.
5679 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5680 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5681 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5682 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5683 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5684 genSkipc(&rFalseIfx);
5686 pic16_emitpLabel(truelbl->key);
5687 if(ifx) ifx->generated = 1;
5691 /* There are no more special cases, so perform a general compare */
5693 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5694 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5698 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5700 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5702 //rFalseIfx.condition ^= 1;
5703 genSkipc(&rFalseIfx);
5705 pic16_emitpLabel(truelbl->key);
5707 if(ifx) ifx->generated = 1;
5714 /* sign is out of the way. So now do an unsigned compare */
5715 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5718 /* General case - compare to an unsigned literal on the right.*/
5720 i = (lit >> (size*8)) & 0xff;
5721 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5722 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5724 i = (lit >> (size*8)) & 0xff;
5727 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5729 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5731 /* this byte of the lit is zero,
5732 *if it's not the last then OR in the variable */
5734 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5739 pic16_emitpLabel(lbl->key);
5740 // pic16_emitpLabel(truelbl->key);
5741 //if(emitFinalCheck)
5742 genSkipc(&rFalseIfx);
5744 pic16_emitpLabel(truelbl->key);
5746 if(ifx) ifx->generated = 1;
5753 if(AOP_TYPE(left) == AOP_LIT) {
5754 //symbol *lbl = newiTempLabel(NULL);
5756 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5759 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5762 if((lit == 0) && (sign == 0)){
5765 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5767 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5769 genSkipz2(&rFalseIfx,0);
5770 if(ifx) ifx->generated = 1;
5777 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5778 /* degenerate compare can never be true */
5779 if(rFalseIfx.condition == 0)
5780 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5782 if(ifx) ifx->generated = 1;
5787 /* signed comparisons to a literal byte */
5789 int lp1 = (lit+1) & 0xff;
5791 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5794 rFalseIfx.condition ^= 1;
5795 genSkipCond(&rFalseIfx,right,0,7);
5798 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5799 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5800 genSkipz2(&rFalseIfx,1);
5803 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5804 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5805 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5806 rFalseIfx.condition ^= 1;
5807 genSkipc(&rFalseIfx);
5811 /* unsigned comparisons to a literal byte */
5813 switch(lit & 0xff ) {
5815 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5816 genSkipz2(&rFalseIfx,0);
5819 rFalseIfx.condition ^= 1;
5820 genSkipCond(&rFalseIfx,right,0,7);
5824 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5825 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5826 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5827 rFalseIfx.condition ^= 1;
5828 if (AOP_TYPE(result) == AOP_CRY)
5829 genSkipc(&rFalseIfx);
5831 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5832 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5838 if(ifx) ifx->generated = 1;
5839 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5845 /* Size is greater than 1 */
5853 /* this means lit = 0xffffffff, or -1 */
5856 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5857 rFalseIfx.condition ^= 1;
5858 genSkipCond(&rFalseIfx,right,size,7);
5859 if(ifx) ifx->generated = 1;
5861 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5870 if(rFalseIfx.condition) {
5871 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5872 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5875 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5877 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5881 if(rFalseIfx.condition) {
5882 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5883 pic16_emitpLabel(truelbl->key);
5885 rFalseIfx.condition ^= 1;
5886 genSkipCond(&rFalseIfx,right,s,7);
5889 if(ifx) ifx->generated = 1;
5891 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5897 if((size == 1) && (0 == (lp1&0xff))) {
5898 /* lower byte of signed word is zero */
5899 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5900 i = ((lp1 >> 8) & 0xff) ^0x80;
5901 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5902 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5903 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5905 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5907 if(ifx) ifx->generated = 1;
5910 rFalseIfx.condition ^= 1;
5911 genSkipc(&rFalseIfx);
5912 if(ifx) ifx->generated = 1;
5918 if(lit & (0x80 << (size*8))) {
5919 /* Lit is less than zero */
5920 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5921 //rFalseIfx.condition ^= 1;
5922 //genSkipCond(&rFalseIfx,left,size,7);
5923 //rFalseIfx.condition ^= 1;
5924 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5925 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5927 if(rFalseIfx.condition)
5928 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5930 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5934 /* Lit is greater than or equal to zero */
5935 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5936 //rFalseIfx.condition ^= 1;
5937 //genSkipCond(&rFalseIfx,right,size,7);
5938 //rFalseIfx.condition ^= 1;
5940 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5941 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5943 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5944 if(rFalseIfx.condition)
5945 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5947 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5951 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5952 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5956 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5958 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5960 rFalseIfx.condition ^= 1;
5961 //rFalseIfx.condition = 1;
5962 genSkipc(&rFalseIfx);
5964 pic16_emitpLabel(truelbl->key);
5966 if(ifx) ifx->generated = 1;
5969 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5976 /* compare word or long to an unsigned literal on the right.*/
5981 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5984 break; /* handled above */
5987 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5989 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5990 genSkipz2(&rFalseIfx,0);
5994 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5996 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5999 if(rFalseIfx.condition)
6000 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6002 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6005 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6006 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6008 rFalseIfx.condition ^= 1;
6009 genSkipc(&rFalseIfx);
6012 pic16_emitpLabel(truelbl->key);
6014 if(ifx) ifx->generated = 1;
6016 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6024 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6025 i = (lit >> (size*8)) & 0xff;
6027 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6028 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6031 i = (lit >> (size*8)) & 0xff;
6034 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6036 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6038 /* this byte of the lit is zero,
6039 * if it's not the last then OR in the variable */
6041 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6046 pic16_emitpLabel(lbl->key);
6048 rFalseIfx.condition ^= 1;
6050 genSkipc(&rFalseIfx);
6054 pic16_emitpLabel(truelbl->key);
6055 if(ifx) ifx->generated = 1;
6057 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6063 /* Compare two variables */
6065 DEBUGpic16_emitcode(";sign","%d",sign);
6069 /* Sigh. thus sucks... */
6073 pctemp = pic16_popGetTempReg(1);
6074 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6075 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6076 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6077 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6078 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6079 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6080 pic16_popReleaseTempReg(pctemp, 1);
6082 /* Signed char comparison */
6083 /* Special thanks to Nikolai Golovchenko for this snippet */
6084 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6085 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6086 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
6087 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6088 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6089 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6091 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6092 genSkipc(&rFalseIfx);
6094 if(ifx) ifx->generated = 1;
6096 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6104 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6105 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6109 /* The rest of the bytes of a multi-byte compare */
6113 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
6116 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6117 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6122 pic16_emitpLabel(lbl->key);
6124 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6125 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
6126 (AOP_TYPE(result) == AOP_REG)) {
6127 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6128 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6130 genSkipc(&rFalseIfx);
6132 //genSkipc(&rFalseIfx);
6133 if(ifx) ifx->generated = 1;
6136 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6144 if ((AOP_TYPE(result) != AOP_CRY)
6145 && AOP_SIZE(result)) {
6146 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6148 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6150 pic16_outBitC(result);
6152 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6153 /* if the result is used in the next
6154 ifx conditional branch then generate
6155 code a little differently */
6157 genIfxJump (ifx,"c");
6159 pic16_outBitC(result);
6160 /* leave the result in acc */
6165 #elif 0 /* VR version of genCmp() */ /* } else { */
6167 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
6168 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
6169 operand *result, int offset, int invert_op)
6173 /* check condition, > or < ?? */
6174 if(rIfx->condition != 0)invert_op ^= 1;
6176 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
6178 if(!ifx)invert_op ^= 1;
6180 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
6181 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
6184 if(!invert_op)return POC_CPFSGT;
6185 else return POC_CPFSLT;
6188 static int compareAopfirstpass=1;
6190 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
6191 operand *oper, int offset, operand *result,
6192 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
6198 /* invert if there is a result to be loaded, in order to fit,
6199 * SETC/CLRC sequence */
6200 if(AOP_SIZE(result))invert_op ^= 1;
6202 // if(sign && !offset)invert_op ^= 1;
6204 // if(sign)invert_op ^= 1;
6206 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
6208 if(AOP_SIZE(result) && compareAopfirstpass) {
6211 pic16_emitpcode(POC_SETF, pcop2);
6216 pic16_emitpcode(POC_CLRF, pcop2);
6222 compareAopfirstpass = 0;
6224 /* there is a bug when comparing operands with size > 1,
6225 * because higher bytes can be equal and test should be performed
6226 * to the next lower byte, current algorithm, considers operands
6227 * inequal in these cases! -- VR 20041107 */
6231 pic16_emitpcode(op, pcop);
6233 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
6236 if((!sign || !offset) && AOP_SIZE(result)) {
6239 pic16_emitpcode(POC_CLRF, pcop2);
6244 pic16_emitpcode(POC_SETF, pcop2);
6249 /* don't emit final branch (offset == 0) */
6253 pic16_emitpcode(POC_RRCF, pcop2);
6255 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
6258 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6259 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6260 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6262 truelbl = newiTempLabel( NULL );
6263 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6264 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6265 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6267 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6268 pic16_emitpLabel(truelbl->key);
6270 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6275 static void genCmp (operand *left, operand *right,
6276 operand *result, iCode *ifx, int sign)
6280 resolvedIfx rFalseIfx;
6281 symbol *falselbl, *tlbl;
6285 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6287 resolveIfx(&rFalseIfx, ifx);
6288 size = max(AOP_SIZE(left), AOP_SIZE(right));
6290 /* if left & right are bit variables */
6291 if(AOP_TYPE(left) == AOP_CRY
6292 && AOP_TYPE(right) == AOP_CRY ) {
6294 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6295 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6297 werror(W_POSSBUG2, __FILE__, __LINE__);
6301 /* if literal is on the right then swap with left */
6302 if((AOP_TYPE(right) == AOP_LIT)) {
6303 operand *tmp = right ;
6304 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
6306 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6308 // lit = (lit - 1) & mask;
6311 rFalseIfx.condition ^= 1; /* reverse compare */
6313 if ((AOP_TYPE(left) == AOP_LIT)) {
6314 /* float compares are handled by support functions */
6315 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6318 /* actual comparing algorithm */
6319 // size = AOP_SIZE( right );
6321 falselbl = newiTempLabel( NULL );
6322 if(AOP_TYPE(left) == AOP_LIT) {
6323 /* compare to literal */
6324 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6327 pCodeOp *pct, *pct2;
6330 /* signed compare */
6331 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6333 /* using PRODL:PRODH as a temporary register here */
6334 pct = pic16_popCopyReg(&pic16_pc_prodl);
6335 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6336 tlbl = newiTempLabel( NULL );
6338 /* first compare signs:
6339 * a. if both are positive, compare just like unsigned
6340 * b. if both are negative, invert cmpop, compare just like unsigned
6341 * c. if different signs, determine the result directly */
6347 tlbl1 = newiTempLabel( NULL );
6348 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
6352 /* literal is zero or positive:
6353 * a. if carry is zero, too, continue compare,
6354 * b. if carry is set, then continue depending on cmpop ^ condition:
6355 * 1. '<' return false (literal < variable),
6356 * 2. '>' return true (literal > variable) */
6357 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6358 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6361 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6362 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6366 /* literal is negative:
6367 * a. if carry is set, too, continue compare,
6368 * b. if carry is zero, then continue depending on cmpop ^ condition:
6369 * 1. '<' return true (literal < variable),
6370 * 2. '>' return false (literal > variable) */
6371 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6372 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6374 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6375 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6380 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6382 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6383 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6388 pic16_emitpLabel( tlbl1->key );
6391 compareAopfirstpass=1;
6392 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6393 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6394 // pic16_emitpcode(POC_MOVWF, pct);
6396 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6397 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6398 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6399 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6403 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6404 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6405 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6406 // pic16_emitpcode(POC_MOVWF, pct);
6408 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6409 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6410 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6411 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6412 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6415 if(ifx)ifx->generated = 1;
6417 if(AOP_SIZE(result)) {
6418 pic16_emitpLabel(tlbl->key);
6419 pic16_emitpLabel(falselbl->key);
6420 pic16_outBitOp( result, pct2 );
6422 pic16_emitpLabel(tlbl->key);
6426 /* unsigned compare */
6427 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6429 compareAopfirstpass=1;
6432 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6433 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6436 if(ifx)ifx->generated = 1;
6438 if(AOP_SIZE(result)) {
6439 pic16_emitpLabel(falselbl->key);
6440 pic16_outBitC( result );
6445 /* compare registers */
6446 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6450 pCodeOp *pct, *pct2;
6452 /* signed compare */
6453 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6455 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6456 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6457 tlbl = newiTempLabel( NULL );
6459 compareAopfirstpass=1;
6462 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6463 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6464 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6465 pic16_emitpcode(POC_MOVWF, pct);
6467 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6468 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6469 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6471 /* WREG already holds left + 0x80 */
6472 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6475 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6476 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6477 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6478 pic16_emitpcode(POC_MOVWF, pct);
6480 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6481 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6482 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6484 /* WREG already holds left + 0x80 */
6485 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6486 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6489 if(ifx)ifx->generated = 1;
6491 if(AOP_SIZE(result)) {
6492 pic16_emitpLabel(tlbl->key);
6493 pic16_emitpLabel(falselbl->key);
6494 pic16_outBitOp( result, pct2 );
6496 pic16_emitpLabel(tlbl->key);
6500 /* unsigned compare */
6501 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6503 compareAopfirstpass=1;
6506 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6507 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6511 if(ifx)ifx->generated = 1;
6512 if(AOP_SIZE(result)) {
6514 pic16_emitpLabel(falselbl->key);
6515 pic16_outBitC( result );
6526 /*-----------------------------------------------------------------*/
6527 /* genCmpGt :- greater than comparison */
6528 /*-----------------------------------------------------------------*/
6529 static void genCmpGt (iCode *ic, iCode *ifx)
6531 operand *left, *right, *result;
6532 sym_link *letype , *retype;
6538 right= IC_RIGHT(ic);
6539 result = IC_RESULT(ic);
6541 letype = getSpec(operandType(left));
6542 retype =getSpec(operandType(right));
6543 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6544 /* assign the amsops */
6545 pic16_aopOp (left,ic,FALSE);
6546 pic16_aopOp (right,ic,FALSE);
6547 pic16_aopOp (result,ic,TRUE);
6549 genCmp(right, left, result, ifx, sign);
6551 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6552 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6553 pic16_freeAsmop(result,NULL,ic,TRUE);
6556 /*-----------------------------------------------------------------*/
6557 /* genCmpLt - less than comparisons */
6558 /*-----------------------------------------------------------------*/
6559 static void genCmpLt (iCode *ic, iCode *ifx)
6561 operand *left, *right, *result;
6562 sym_link *letype , *retype;
6568 right= IC_RIGHT(ic);
6569 result = IC_RESULT(ic);
6571 letype = getSpec(operandType(left));
6572 retype =getSpec(operandType(right));
6573 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6575 /* assign the amsops */
6576 pic16_aopOp (left,ic,FALSE);
6577 pic16_aopOp (right,ic,FALSE);
6578 pic16_aopOp (result,ic,TRUE);
6580 genCmp(left, right, result, ifx, sign);
6582 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6583 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6584 pic16_freeAsmop(result,NULL,ic,TRUE);
6589 // FIXME reenable literal optimisation when the pic16 port is stable
6591 /*-----------------------------------------------------------------*/
6592 /* genc16bit2lit - compare a 16 bit value to a literal */
6593 /*-----------------------------------------------------------------*/
6594 static void genc16bit2lit(operand *op, int lit, int offset)
6598 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6599 if( (lit&0xff) == 0)
6604 switch( BYTEofLONG(lit,i)) {
6606 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6609 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6612 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6615 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6616 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6621 switch( BYTEofLONG(lit,i)) {
6623 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6627 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6631 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6634 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6636 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6645 /*-----------------------------------------------------------------*/
6646 /* gencjneshort - compare and jump if not equal */
6647 /*-----------------------------------------------------------------*/
6648 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6650 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6652 int res_offset = 0; /* the result may be a different size then left or right */
6653 int res_size = AOP_SIZE(result);
6655 symbol *lbl, *lbl_done;
6657 unsigned long lit = 0L;
6658 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6660 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6661 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6663 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6664 resolveIfx(&rIfx,ifx);
6665 lbl = newiTempLabel(NULL);
6666 lbl_done = newiTempLabel(NULL);
6669 /* if the left side is a literal or
6670 if the right is in a pointer register and left
6672 if ((AOP_TYPE(left) == AOP_LIT) ||
6673 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6678 if(AOP_TYPE(right) == AOP_LIT)
6679 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6681 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6682 preserve_result = 1;
6684 if(result && !preserve_result)
6687 for(i = 0; i < AOP_SIZE(result); i++)
6688 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6692 /* if the right side is a literal then anything goes */
6693 if (AOP_TYPE(right) == AOP_LIT &&
6694 AOP_TYPE(left) != AOP_DIR ) {
6697 genc16bit2lit(left, lit, 0);
6699 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6702 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6705 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6706 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6708 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6712 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6714 if(res_offset < res_size-1)
6722 /* if the right side is in a register or in direct space or
6723 if the left is a pointer register & right is not */
6724 else if (AOP_TYPE(right) == AOP_REG ||
6725 AOP_TYPE(right) == AOP_DIR ||
6726 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6727 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6728 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6729 int lbl_key = lbl->key;
6732 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6733 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6735 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6736 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6737 __FUNCTION__,__LINE__);
6741 /* switch(size) { */
6743 /* genc16bit2lit(left, lit, 0); */
6745 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6750 if((AOP_TYPE(left) == AOP_DIR) &&
6751 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6753 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6754 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6756 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6758 switch (lit & 0xff) {
6760 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6763 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6764 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6765 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6769 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6770 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6771 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6772 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6776 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6777 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6782 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6785 if(AOP_TYPE(result) == AOP_CRY) {
6786 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6791 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6793 /* fix me. probably need to check result size too */
6794 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6799 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6800 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6807 if(res_offset < res_size-1)
6812 } else if(AOP_TYPE(right) == AOP_REG &&
6813 AOP_TYPE(left) != AOP_DIR){
6816 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6817 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6818 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6823 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6825 if(res_offset < res_size-1)
6830 /* right is a pointer reg need both a & b */
6832 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6834 pic16_emitcode("mov","b,%s",l);
6835 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6836 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6841 if(result && preserve_result)
6844 for(i = 0; i < AOP_SIZE(result); i++)
6845 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6848 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6850 if(result && preserve_result)
6851 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6854 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6856 pic16_emitpLabel(lbl->key);
6858 if(result && preserve_result)
6861 for(i = 0; i < AOP_SIZE(result); i++)
6862 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6864 pic16_emitpLabel(lbl_done->key);
6867 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6875 /*-----------------------------------------------------------------*/
6876 /* gencjne - compare and jump if not equal */
6877 /*-----------------------------------------------------------------*/
6878 static void gencjne(operand *left, operand *right, iCode *ifx)
6880 symbol *tlbl = newiTempLabel(NULL);
6882 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6883 gencjneshort(left, right, lbl);
6885 pic16_emitcode("mov","a,%s",one);
6886 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6887 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6888 pic16_emitcode("clr","a");
6889 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6891 pic16_emitpLabel(lbl->key);
6892 pic16_emitpLabel(tlbl->key);
6898 /*-----------------------------------------------------------------*/
6899 /* is_LitOp - check if operand has to be treated as literal */
6900 /*-----------------------------------------------------------------*/
6901 static bool is_LitOp(operand *op)
6903 return ((AOP_TYPE(op) == AOP_LIT)
6904 || ( (AOP_TYPE(op) == AOP_PCODE)
6905 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6906 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6909 /*-----------------------------------------------------------------*/
6910 /* is_LitAOp - check if operand has to be treated as literal */
6911 /*-----------------------------------------------------------------*/
6912 static bool is_LitAOp(asmop *aop)
6914 return ((aop->type == AOP_LIT)
6915 || ( (aop->type == AOP_PCODE)
6916 && ( (aop->aopu.pcop->type == PO_LITERAL)
6917 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6922 /*-----------------------------------------------------------------*/
6923 /* genCmpEq - generates code for equal to */
6924 /*-----------------------------------------------------------------*/
6925 static void genCmpEq (iCode *ic, iCode *ifx)
6927 operand *left, *right, *result;
6928 symbol *falselbl = newiTempLabel(NULL);
6929 symbol *donelbl = newiTempLabel(NULL);
6931 int preserve_result = 0;
6932 int generate_result = 0;
6934 unsigned long lit = -1;
6938 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6939 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6940 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6942 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6944 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6946 werror(W_POSSBUG2, __FILE__, __LINE__);
6947 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6948 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6952 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6954 operand *tmp = right ;
6959 if (AOP_TYPE(right) == AOP_LIT) {
6960 lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6963 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6964 preserve_result = 1;
6966 if(result && AOP_SIZE(result))
6967 generate_result = 1;
6969 if(generate_result && !preserve_result)
6971 for(i = 0; i < AOP_SIZE(result); i++)
6972 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6975 assert( AOP_SIZE(left) == AOP_SIZE(right) );
6976 for(i=0; i < AOP_SIZE(left); i++)
6978 if(AOP_TYPE(left) != AOP_ACC)
6981 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6983 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6985 if(is_LitOp(right)) {
6986 if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6987 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6990 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
6992 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6997 if(generate_result && preserve_result)
6999 for(i = 0; i < AOP_SIZE(result); i++)
7000 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7004 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
7006 if(generate_result && preserve_result)
7007 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7009 if(ifx && IC_TRUE(ifx))
7010 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7012 if(ifx && IC_FALSE(ifx))
7013 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7015 pic16_emitpLabel(falselbl->key);
7019 if(ifx && IC_FALSE(ifx))
7020 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7022 if(generate_result && preserve_result)
7024 for(i = 0; i < AOP_SIZE(result); i++)
7025 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7028 pic16_emitpLabel(donelbl->key);
7034 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7035 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7036 pic16_freeAsmop(result,NULL,ic,TRUE);
7042 // old version kept for reference
7044 /*-----------------------------------------------------------------*/
7045 /* genCmpEq - generates code for equal to */
7046 /*-----------------------------------------------------------------*/
7047 static void genCmpEq (iCode *ic, iCode *ifx)
7049 operand *left, *right, *result;
7050 unsigned long lit = 0L;
7052 symbol *falselbl = newiTempLabel(NULL);
7055 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7058 DEBUGpic16_emitcode ("; ifx is non-null","");
7060 DEBUGpic16_emitcode ("; ifx is null","");
7062 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7063 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7064 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7066 size = max(AOP_SIZE(left),AOP_SIZE(right));
7068 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7070 /* if literal, literal on the right or
7071 if the right is in a pointer register and left
7073 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
7074 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
7075 operand *tmp = right ;
7081 if(ifx && !AOP_SIZE(result)){
7083 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
7084 /* if they are both bit variables */
7085 if (AOP_TYPE(left) == AOP_CRY &&
7086 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7087 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
7088 if(AOP_TYPE(right) == AOP_LIT){
7089 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7091 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7092 pic16_emitcode("cpl","c");
7093 } else if(lit == 1L) {
7094 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7096 pic16_emitcode("clr","c");
7098 /* AOP_TYPE(right) == AOP_CRY */
7100 symbol *lbl = newiTempLabel(NULL);
7101 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7102 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7103 pic16_emitcode("cpl","c");
7104 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7106 /* if true label then we jump if condition
7108 tlbl = newiTempLabel(NULL);
7109 if ( IC_TRUE(ifx) ) {
7110 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
7111 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
7113 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
7114 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
7116 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7119 /* left and right are both bit variables, result is carry */
7122 resolveIfx(&rIfx,ifx);
7124 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
7125 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
7126 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
7127 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
7132 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
7134 /* They're not both bit variables. Is the right a literal? */
7135 if(AOP_TYPE(right) == AOP_LIT) {
7136 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7141 switch(lit & 0xff) {
7143 if ( IC_TRUE(ifx) ) {
7144 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
7146 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7148 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
7149 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7153 if ( IC_TRUE(ifx) ) {
7154 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
7156 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7158 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
7159 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7163 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7165 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
7170 /* end of size == 1 */
7174 genc16bit2lit(left,lit,offset);
7177 /* end of size == 2 */
7182 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7183 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
7184 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7185 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7188 /* search for patterns that can be optimized */
7190 genc16bit2lit(left,lit,0);
7194 emitSKPZ; // if hi word unequal
7196 emitSKPNZ; // if hi word equal
7198 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
7199 genc16bit2lit(left,lit,2);
7202 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7203 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7207 pic16_emitpLabel(falselbl->key);
7216 } else if(AOP_TYPE(right) == AOP_CRY ) {
7217 /* we know the left is not a bit, but that the right is */
7218 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7219 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
7220 pic16_popGet(AOP(right),offset));
7221 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
7223 /* if the two are equal, then W will be 0 and the Z bit is set
7224 * we could test Z now, or go ahead and check the high order bytes if
7225 * the variable we're comparing is larger than a byte. */
7228 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
7230 if ( IC_TRUE(ifx) ) {
7232 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7233 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7236 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7237 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7241 /* They're both variables that are larger than bits */
7244 tlbl = newiTempLabel(NULL);
7247 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7248 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7250 if ( IC_TRUE(ifx) ) {
7254 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7256 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7257 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7261 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7264 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7265 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7270 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7272 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7273 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7277 if(s>1 && IC_TRUE(ifx)) {
7278 pic16_emitpLabel(tlbl->key);
7279 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7283 /* mark the icode as generated */
7288 /* if they are both bit variables */
7289 if (AOP_TYPE(left) == AOP_CRY &&
7290 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7291 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7292 if(AOP_TYPE(right) == AOP_LIT){
7293 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7295 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7296 pic16_emitcode("cpl","c");
7297 } else if(lit == 1L) {
7298 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7300 pic16_emitcode("clr","c");
7302 /* AOP_TYPE(right) == AOP_CRY */
7304 symbol *lbl = newiTempLabel(NULL);
7305 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7306 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7307 pic16_emitcode("cpl","c");
7308 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7311 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7312 pic16_outBitC(result);
7316 genIfxJump (ifx,"c");
7319 /* if the result is used in an arithmetic operation
7320 then put the result in place */
7321 pic16_outBitC(result);
7324 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7325 gencjne(left,right,result,ifx);
7328 gencjne(left,right,newiTempLabel(NULL));
7330 if(IC_TRUE(ifx)->key)
7331 gencjne(left,right,IC_TRUE(ifx)->key);
7333 gencjne(left,right,IC_FALSE(ifx)->key);
7337 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7338 pic16_aopPut(AOP(result),"a",0);
7343 genIfxJump (ifx,"a");
7347 /* if the result is used in an arithmetic operation
7348 then put the result in place */
7350 if (AOP_TYPE(result) != AOP_CRY)
7351 pic16_outAcc(result);
7353 /* leave the result in acc */
7357 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7358 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7359 pic16_freeAsmop(result,NULL,ic,TRUE);
7363 /*-----------------------------------------------------------------*/
7364 /* ifxForOp - returns the icode containing the ifx for operand */
7365 /*-----------------------------------------------------------------*/
7366 static iCode *ifxForOp ( operand *op, iCode *ic )
7370 /* if true symbol then needs to be assigned */
7371 if (IS_TRUE_SYMOP(op))
7374 /* if this has register type condition and
7375 the next instruction is ifx with the same operand
7376 and live to of the operand is upto the ifx only then */
7378 && ic->next->op == IFX
7379 && IC_COND(ic->next)->key == op->key
7380 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7382 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7388 ic->next->op == IFX &&
7389 IC_COND(ic->next)->key == op->key) {
7390 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7395 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7397 ic->next->op == IFX)
7398 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7401 ic->next->op == IFX &&
7402 IC_COND(ic->next)->key == op->key) {
7403 DEBUGpic16_emitcode ("; "," key is okay");
7404 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7405 OP_SYMBOL(op)->liveTo,
7410 /* the code below is completely untested
7411 * it just allows ulong2fs.c compile -- VR */
7414 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7415 __FILE__, __FUNCTION__, __LINE__);
7417 /* if this has register type condition and
7418 the next instruction is ifx with the same operand
7419 and live to of the operand is upto the ifx only then */
7421 ic->next->op == IFX &&
7422 IC_COND(ic->next)->key == op->key &&
7423 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7427 ic->next->op == IFX &&
7428 IC_COND(ic->next)->key == op->key) {
7429 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7433 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7434 __FILE__, __FUNCTION__, __LINE__);
7436 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7441 /*-----------------------------------------------------------------*/
7442 /* genAndOp - for && operation */
7443 /*-----------------------------------------------------------------*/
7444 static void genAndOp (iCode *ic)
7446 operand *left,*right, *result;
7451 /* note here that && operations that are in an
7452 if statement are taken away by backPatchLabels
7453 only those used in arthmetic operations remain */
7454 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7455 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7456 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7458 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7460 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7461 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7462 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7464 /* if both are bit variables */
7465 /* if (AOP_TYPE(left) == AOP_CRY && */
7466 /* AOP_TYPE(right) == AOP_CRY ) { */
7467 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7468 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7469 /* pic16_outBitC(result); */
7471 /* tlbl = newiTempLabel(NULL); */
7472 /* pic16_toBoolean(left); */
7473 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7474 /* pic16_toBoolean(right); */
7475 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7476 /* pic16_outBitAcc(result); */
7479 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7480 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7481 pic16_freeAsmop(result,NULL,ic,TRUE);
7485 /*-----------------------------------------------------------------*/
7486 /* genOrOp - for || operation */
7487 /*-----------------------------------------------------------------*/
7490 modified this code, but it doesn't appear to ever get called
7493 static void genOrOp (iCode *ic)
7495 operand *left,*right, *result;
7500 /* note here that || operations that are in an
7501 if statement are taken away by backPatchLabels
7502 only those used in arthmetic operations remain */
7503 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7504 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7505 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7507 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7509 /* if both are bit variables */
7510 if (AOP_TYPE(left) == AOP_CRY &&
7511 AOP_TYPE(right) == AOP_CRY ) {
7512 pic16_emitcode("clrc","");
7513 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7514 AOP(left)->aopu.aop_dir,
7515 AOP(left)->aopu.aop_dir);
7516 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7517 AOP(right)->aopu.aop_dir,
7518 AOP(right)->aopu.aop_dir);
7519 pic16_emitcode("setc","");
7522 tlbl = newiTempLabel(NULL);
7523 pic16_toBoolean(left);
7525 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7526 pic16_toBoolean(right);
7527 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7529 pic16_outBitAcc(result);
7532 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7533 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7534 pic16_freeAsmop(result,NULL,ic,TRUE);
7537 /*-----------------------------------------------------------------*/
7538 /* isLiteralBit - test if lit == 2^n */
7539 /*-----------------------------------------------------------------*/
7540 static int isLiteralBit(unsigned long lit)
7542 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7543 0x100L,0x200L,0x400L,0x800L,
7544 0x1000L,0x2000L,0x4000L,0x8000L,
7545 0x10000L,0x20000L,0x40000L,0x80000L,
7546 0x100000L,0x200000L,0x400000L,0x800000L,
7547 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7548 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7551 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7552 for(idx = 0; idx < 32; idx++)
7558 /*-----------------------------------------------------------------*/
7559 /* continueIfTrue - */
7560 /*-----------------------------------------------------------------*/
7561 static void continueIfTrue (iCode *ic)
7565 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7569 /*-----------------------------------------------------------------*/
7571 /*-----------------------------------------------------------------*/
7572 static void jumpIfTrue (iCode *ic)
7576 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7580 /*-----------------------------------------------------------------*/
7581 /* jmpTrueOrFalse - */
7582 /*-----------------------------------------------------------------*/
7583 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7585 // ugly but optimized by peephole
7588 symbol *nlbl = newiTempLabel(NULL);
7589 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7590 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7591 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7592 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7594 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7595 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7600 /*-----------------------------------------------------------------*/
7601 /* genAnd - code for and */
7602 /*-----------------------------------------------------------------*/
7603 static void genAnd (iCode *ic, iCode *ifx)
7605 operand *left, *right, *result;
7607 unsigned long lit = 0L;
7613 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7614 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7615 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7617 resolveIfx(&rIfx,ifx);
7619 /* if left is a literal & right is not then exchange them */
7620 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7621 AOP_NEEDSACC(left)) {
7622 operand *tmp = right ;
7627 /* if result = right then exchange them */
7628 if(pic16_sameRegs(AOP(result),AOP(right))){
7629 operand *tmp = right ;
7634 /* if right is bit then exchange them */
7635 if (AOP_TYPE(right) == AOP_CRY &&
7636 AOP_TYPE(left) != AOP_CRY){
7637 operand *tmp = right ;
7641 if(AOP_TYPE(right) == AOP_LIT)
7642 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7644 size = AOP_SIZE(result);
7646 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7649 // result = bit & yy;
7650 if (AOP_TYPE(left) == AOP_CRY){
7651 // c = bit & literal;
7652 if(AOP_TYPE(right) == AOP_LIT){
7654 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7657 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7660 if(size && (AOP_TYPE(result) == AOP_CRY)){
7661 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7664 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7668 pic16_emitcode("clr","c");
7671 if (AOP_TYPE(right) == AOP_CRY){
7673 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7674 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7677 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7679 pic16_emitcode("rrc","a");
7680 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7686 pic16_outBitC(result);
7688 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7689 genIfxJump(ifx, "c");
7693 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7694 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7695 if((AOP_TYPE(right) == AOP_LIT) &&
7696 (AOP_TYPE(result) == AOP_CRY) &&
7697 (AOP_TYPE(left) != AOP_CRY)){
7698 int posbit = isLiteralBit(lit);
7702 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7705 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7711 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7712 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7714 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7715 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7718 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7719 size = AOP_SIZE(left);
7722 int bp = posbit, ofs=0;
7729 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7730 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7734 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7735 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7737 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7744 symbol *tlbl = newiTempLabel(NULL);
7745 int sizel = AOP_SIZE(left);
7751 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7753 /* patch provided by Aaron Colwell */
7754 if((posbit = isLiteralBit(bytelit)) != 0) {
7755 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7756 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7757 (posbit-1),0, PO_GPR_REGISTER));
7759 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7760 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7762 if (bytelit == 0xff) {
7763 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7764 * a peephole could optimize it out -- VR */
7765 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7767 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7768 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7771 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7772 pic16_popGetLabel(tlbl->key));
7776 /* old code, left here for reference -- VR 09/2004 */
7777 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7779 if((posbit = isLiteralBit(bytelit)) != 0)
7780 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7782 if(bytelit != 0x0FFL)
7783 pic16_emitcode("anl","a,%s",
7784 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7785 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7791 // bit = left & literal
7794 pic16_emitpLabel(tlbl->key);
7796 // if(left & literal)
7799 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7802 pic16_emitpLabel(tlbl->key);
7807 pic16_outBitC(result);
7811 /* if left is same as result */
7812 if(pic16_sameRegs(AOP(result),AOP(left))){
7814 for(;size--; offset++,lit>>=8) {
7815 if(AOP_TYPE(right) == AOP_LIT){
7816 switch(lit & 0xff) {
7818 /* and'ing with 0 has clears the result */
7819 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7820 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7823 /* and'ing with 0xff is a nop when the result and left are the same */
7828 int p = pic16_my_powof2( (~lit) & 0xff );
7830 /* only one bit is set in the literal, so use a bcf instruction */
7831 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7832 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7835 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7836 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7837 if(know_W != (lit&0xff))
7838 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7840 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7845 if (AOP_TYPE(left) == AOP_ACC) {
7846 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7848 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7849 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7856 // left & result in different registers
7857 if(AOP_TYPE(result) == AOP_CRY){
7859 // if(size), result in bit
7860 // if(!size && ifx), conditional oper: if(left & right)
7861 symbol *tlbl = newiTempLabel(NULL);
7862 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7864 pic16_emitcode("setb","c");
7866 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7867 pic16_emitcode("anl","a,%s",
7868 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7869 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7874 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7875 pic16_outBitC(result);
7877 jmpTrueOrFalse(ifx, tlbl);
7879 for(;(size--);offset++) {
7881 // result = left & right
7882 if(AOP_TYPE(right) == AOP_LIT){
7883 int t = (lit >> (offset*8)) & 0x0FFL;
7886 pic16_emitcode("clrf","%s",
7887 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7888 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7891 pic16_emitcode("movf","%s,w",
7892 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7893 pic16_emitcode("movwf","%s",
7894 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7895 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7896 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7899 pic16_emitcode("movlw","0x%x",t);
7900 pic16_emitcode("andwf","%s,w",
7901 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7902 pic16_emitcode("movwf","%s",
7903 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7905 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7906 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7907 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7912 if (AOP_TYPE(left) == AOP_ACC) {
7913 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7914 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7916 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7917 pic16_emitcode("andwf","%s,w",
7918 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7919 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7920 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7922 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7923 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7929 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7930 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7931 pic16_freeAsmop(result,NULL,ic,TRUE);
7934 /*-----------------------------------------------------------------*/
7935 /* genOr - code for or */
7936 /*-----------------------------------------------------------------*/
7937 static void genOr (iCode *ic, iCode *ifx)
7939 operand *left, *right, *result;
7941 unsigned long lit = 0L;
7943 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7946 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7947 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7948 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7950 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7952 /* if left is a literal & right is not then exchange them */
7953 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7954 AOP_NEEDSACC(left)) {
7955 operand *tmp = right ;
7960 /* if result = right then exchange them */
7961 if(pic16_sameRegs(AOP(result),AOP(right))){
7962 operand *tmp = right ;
7967 /* if right is bit then exchange them */
7968 if (AOP_TYPE(right) == AOP_CRY &&
7969 AOP_TYPE(left) != AOP_CRY){
7970 operand *tmp = right ;
7975 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7977 if(AOP_TYPE(right) == AOP_LIT)
7978 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7980 size = AOP_SIZE(result);
7984 if (AOP_TYPE(left) == AOP_CRY){
7985 if(AOP_TYPE(right) == AOP_LIT){
7986 // c = bit & literal;
7988 // lit != 0 => result = 1
7989 if(AOP_TYPE(result) == AOP_CRY){
7991 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7992 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7993 // AOP(result)->aopu.aop_dir,
7994 // AOP(result)->aopu.aop_dir);
7996 continueIfTrue(ifx);
8000 // lit == 0 => result = left
8001 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8003 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
8006 if (AOP_TYPE(right) == AOP_CRY){
8007 if(pic16_sameRegs(AOP(result),AOP(left))){
8009 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8010 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
8011 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8013 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8014 AOP(result)->aopu.aop_dir,
8015 AOP(result)->aopu.aop_dir);
8016 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8017 AOP(right)->aopu.aop_dir,
8018 AOP(right)->aopu.aop_dir);
8019 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8020 AOP(result)->aopu.aop_dir,
8021 AOP(result)->aopu.aop_dir);
8023 if( AOP_TYPE(result) == AOP_ACC) {
8024 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8025 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8026 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8027 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
8031 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8032 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8033 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8034 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8036 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8037 AOP(result)->aopu.aop_dir,
8038 AOP(result)->aopu.aop_dir);
8039 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
8040 AOP(right)->aopu.aop_dir,
8041 AOP(right)->aopu.aop_dir);
8042 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8043 AOP(left)->aopu.aop_dir,
8044 AOP(left)->aopu.aop_dir);
8045 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8046 AOP(result)->aopu.aop_dir,
8047 AOP(result)->aopu.aop_dir);
8052 symbol *tlbl = newiTempLabel(NULL);
8053 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8056 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8057 if( AOP_TYPE(right) == AOP_ACC) {
8058 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
8060 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8061 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8066 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
8067 pic16_emitcode(";XXX setb","c");
8068 pic16_emitcode(";XXX jb","%s,%05d_DS_",
8069 AOP(left)->aopu.aop_dir,tlbl->key+100);
8070 pic16_toBoolean(right);
8071 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8072 if((AOP_TYPE(result) == AOP_CRY) && ifx){
8073 jmpTrueOrFalse(ifx, tlbl);
8077 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8084 pic16_outBitC(result);
8086 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8087 genIfxJump(ifx, "c");
8091 // if(val | 0xZZ) - size = 0, ifx != FALSE -
8092 // bit = val | 0xZZ - size = 1, ifx = FALSE -
8093 if((AOP_TYPE(right) == AOP_LIT) &&
8094 (AOP_TYPE(result) == AOP_CRY) &&
8095 (AOP_TYPE(left) != AOP_CRY)){
8097 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8100 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
8102 continueIfTrue(ifx);
8105 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8106 // lit = 0, result = boolean(left)
8108 pic16_emitcode(";XXX setb","c");
8109 pic16_toBoolean(right);
8111 symbol *tlbl = newiTempLabel(NULL);
8112 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8114 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8116 genIfxJump (ifx,"a");
8120 pic16_outBitC(result);
8124 /* if left is same as result */
8125 if(pic16_sameRegs(AOP(result),AOP(left))){
8127 for(;size--; offset++,lit>>=8) {
8128 if(AOP_TYPE(right) == AOP_LIT){
8129 if((lit & 0xff) == 0)
8130 /* or'ing with 0 has no effect */
8133 int p = pic16_my_powof2(lit & 0xff);
8135 /* only one bit is set in the literal, so use a bsf instruction */
8136 pic16_emitpcode(POC_BSF,
8137 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
8139 if(know_W != (lit & 0xff))
8140 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
8141 know_W = lit & 0xff;
8142 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8147 if (AOP_TYPE(left) == AOP_ACC) {
8148 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
8149 // pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8151 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8152 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8154 // pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8155 // pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8161 // left & result in different registers
8162 if(AOP_TYPE(result) == AOP_CRY){
8164 // if(size), result in bit
8165 // if(!size && ifx), conditional oper: if(left | right)
8166 symbol *tlbl = newiTempLabel(NULL);
8167 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8168 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8172 pic16_emitcode(";XXX setb","c");
8174 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8175 pic16_emitcode(";XXX orl","a,%s",
8176 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8177 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8182 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8183 pic16_outBitC(result);
8185 jmpTrueOrFalse(ifx, tlbl);
8186 } else for(;(size--);offset++){
8188 // result = left & right
8189 if(AOP_TYPE(right) == AOP_LIT){
8190 int t = (lit >> (offset*8)) & 0x0FFL;
8193 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8194 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8196 // pic16_emitcode("movf","%s,w",
8197 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8198 // pic16_emitcode("movwf","%s",
8199 // pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8202 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8203 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
8204 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8206 // pic16_emitcode("movlw","0x%x",t);
8207 // pic16_emitcode("iorwf","%s,w",
8208 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8209 // pic16_emitcode("movwf","%s",
8210 // pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8216 // faster than result <- left, anl result,right
8217 // and better if result is SFR
8218 if (AOP_TYPE(left) == AOP_ACC) {
8219 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
8220 // pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8222 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8223 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
8225 // pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8226 // pic16_emitcode("iorwf","%s,w",
8227 // pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8229 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8230 // pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8235 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8236 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8237 pic16_freeAsmop(result,NULL,ic,TRUE);
8240 /*-----------------------------------------------------------------*/
8241 /* genXor - code for xclusive or */
8242 /*-----------------------------------------------------------------*/
8243 static void genXor (iCode *ic, iCode *ifx)
8245 operand *left, *right, *result;
8247 unsigned long lit = 0L;
8249 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8252 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8253 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8254 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8256 /* if left is a literal & right is not ||
8257 if left needs acc & right does not */
8258 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8259 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8260 operand *tmp = right ;
8265 /* if result = right then exchange them */
8266 if(pic16_sameRegs(AOP(result),AOP(right))){
8267 operand *tmp = right ;
8272 /* if right is bit then exchange them */
8273 if (AOP_TYPE(right) == AOP_CRY &&
8274 AOP_TYPE(left) != AOP_CRY){
8275 operand *tmp = right ;
8279 if(AOP_TYPE(right) == AOP_LIT)
8280 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8282 size = AOP_SIZE(result);
8286 if (AOP_TYPE(left) == AOP_CRY){
8287 if(AOP_TYPE(right) == AOP_LIT){
8288 // c = bit & literal;
8290 // lit>>1 != 0 => result = 1
8291 if(AOP_TYPE(result) == AOP_CRY){
8293 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
8294 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8296 continueIfTrue(ifx);
8299 pic16_emitcode("setb","c");
8303 // lit == 0, result = left
8304 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8306 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8308 // lit == 1, result = not(left)
8309 if(size && pic16_sameRegs(AOP(result),AOP(left))){
8310 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
8311 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
8312 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8315 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8316 pic16_emitcode("cpl","c");
8323 symbol *tlbl = newiTempLabel(NULL);
8324 if (AOP_TYPE(right) == AOP_CRY){
8326 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8329 int sizer = AOP_SIZE(right);
8331 // if val>>1 != 0, result = 1
8332 pic16_emitcode("setb","c");
8334 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8336 // test the msb of the lsb
8337 pic16_emitcode("anl","a,#0xfe");
8338 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8342 pic16_emitcode("rrc","a");
8344 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8345 pic16_emitcode("cpl","c");
8346 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8351 pic16_outBitC(result);
8353 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8354 genIfxJump(ifx, "c");
8358 if(pic16_sameRegs(AOP(result),AOP(left))){
8359 /* if left is same as result */
8360 for(;size--; offset++) {
8361 if(AOP_TYPE(right) == AOP_LIT){
8362 int t = (lit >> (offset*8)) & 0x0FFL;
8366 if (IS_AOP_PREG(left)) {
8367 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8368 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8369 pic16_aopPut(AOP(result),"a",offset);
8371 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8372 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8373 pic16_emitcode("xrl","%s,%s",
8374 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8375 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8378 if (AOP_TYPE(left) == AOP_ACC)
8379 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8381 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8382 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8384 if (IS_AOP_PREG(left)) {
8385 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8386 pic16_aopPut(AOP(result),"a",offset);
8388 pic16_emitcode("xrl","%s,a",
8389 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8395 // left & result in different registers
8396 if(AOP_TYPE(result) == AOP_CRY){
8398 // if(size), result in bit
8399 // if(!size && ifx), conditional oper: if(left ^ right)
8400 symbol *tlbl = newiTempLabel(NULL);
8401 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8403 pic16_emitcode("setb","c");
8405 if((AOP_TYPE(right) == AOP_LIT) &&
8406 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8407 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8409 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8410 pic16_emitcode("xrl","a,%s",
8411 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8413 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8418 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8419 pic16_outBitC(result);
8421 jmpTrueOrFalse(ifx, tlbl);
8422 } else for(;(size--);offset++){
8424 // result = left & right
8425 if(AOP_TYPE(right) == AOP_LIT){
8426 int t = (lit >> (offset*8)) & 0x0FFL;
8429 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8430 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8431 pic16_emitcode("movf","%s,w",
8432 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8433 pic16_emitcode("movwf","%s",
8434 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8437 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8438 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8439 pic16_emitcode("comf","%s,w",
8440 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8441 pic16_emitcode("movwf","%s",
8442 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8445 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8446 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8447 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8448 pic16_emitcode("movlw","0x%x",t);
8449 pic16_emitcode("xorwf","%s,w",
8450 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8451 pic16_emitcode("movwf","%s",
8452 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8458 // faster than result <- left, anl result,right
8459 // and better if result is SFR
8460 if (AOP_TYPE(left) == AOP_ACC) {
8461 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8462 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8464 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8465 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8466 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8467 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8469 if ( AOP_TYPE(result) != AOP_ACC){
8470 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8471 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8477 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8478 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8479 pic16_freeAsmop(result,NULL,ic,TRUE);
8482 /*-----------------------------------------------------------------*/
8483 /* genInline - write the inline code out */
8484 /*-----------------------------------------------------------------*/
8485 static void genInline (iCode *ic)
8487 char *buffer, *bp, *bp1;
8489 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8491 _G.inLine += (!options.asmpeep);
8493 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8494 strcpy(buffer,IC_INLINE(ic));
8496 while((bp1=strstr(bp, "\\n"))) {
8504 /* This is an experimental code for #pragma inline
8505 and is temporarily disabled for 2.5.0 release */
8513 cbuf = Safe_strdup(buffer);
8514 cblen = strlen(buffer)+1;
8515 memset(cbuf, 0, cblen);
8520 if(*bp != '%')*bp1++ = *bp++;
8526 if(i>elementsInSet(asmInlineMap))break;
8529 s = indexSet(asmInlineMap, i);
8530 DEBUGpc("searching symbol s = `%s'", s);
8531 sym = findSym(SymbolTab, NULL, s);
8534 strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8536 strcat(bp1, sym->rname);
8542 if(strlen(bp1) > cblen - 16) {
8543 int i = strlen(cbuf);
8545 cbuf = realloc(cbuf, cblen);
8546 memset(cbuf+i, 0, 50);
8552 buffer = Safe_strdup( cbuf );
8559 /* emit each line as a code */
8565 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8573 /* print label, use this special format with NULL directive
8574 * to denote that the argument should not be indented with tab */
8575 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8578 /* advance to end of line (prevent splitting of comments at ':' */
8579 while (*bp && *bp != '\n') {
8587 if ((bp1 != bp) && *bp1)
8588 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8593 _G.inLine -= (!options.asmpeep);
8596 /*-----------------------------------------------------------------*/
8597 /* genRRC - rotate right with carry */
8598 /*-----------------------------------------------------------------*/
8599 static void genRRC (iCode *ic)
8601 operand *left , *result ;
8602 int size, offset = 0, same;
8604 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8606 /* rotate right with carry */
8608 result=IC_RESULT(ic);
8609 pic16_aopOp (left,ic,FALSE);
8610 pic16_aopOp (result,ic,TRUE);
8612 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8614 same = pic16_sameRegs(AOP(result),AOP(left));
8616 size = AOP_SIZE(result);
8618 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8620 /* get the lsb and put it into the carry */
8621 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8628 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8630 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8631 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8637 pic16_freeAsmop(left,NULL,ic,TRUE);
8638 pic16_freeAsmop(result,NULL,ic,TRUE);
8641 /*-----------------------------------------------------------------*/
8642 /* genRLC - generate code for rotate left with carry */
8643 /*-----------------------------------------------------------------*/
8644 static void genRLC (iCode *ic)
8646 operand *left , *result ;
8647 int size, offset = 0;
8650 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8651 /* rotate right with carry */
8653 result=IC_RESULT(ic);
8654 pic16_aopOp (left,ic,FALSE);
8655 pic16_aopOp (result,ic,TRUE);
8657 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8659 same = pic16_sameRegs(AOP(result),AOP(left));
8661 /* move it to the result */
8662 size = AOP_SIZE(result);
8664 /* get the msb and put it into the carry */
8665 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8672 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8674 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8675 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8682 pic16_freeAsmop(left,NULL,ic,TRUE);
8683 pic16_freeAsmop(result,NULL,ic,TRUE);
8687 /* gpasm can get the highest order bit with HIGH/UPPER
8688 * so the following probably is not needed -- VR */
8690 /*-----------------------------------------------------------------*/
8691 /* genGetHbit - generates code get highest order bit */
8692 /*-----------------------------------------------------------------*/
8693 static void genGetHbit (iCode *ic)
8695 operand *left, *result;
8697 result=IC_RESULT(ic);
8698 pic16_aopOp (left,ic,FALSE);
8699 pic16_aopOp (result,ic,FALSE);
8701 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8702 /* get the highest order byte into a */
8703 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8704 if(AOP_TYPE(result) == AOP_CRY){
8705 pic16_emitcode("rlc","a");
8706 pic16_outBitC(result);
8709 pic16_emitcode("rl","a");
8710 pic16_emitcode("anl","a,#0x01");
8711 pic16_outAcc(result);
8715 pic16_freeAsmop(left,NULL,ic,TRUE);
8716 pic16_freeAsmop(result,NULL,ic,TRUE);
8720 /*-----------------------------------------------------------------*/
8721 /* AccRol - rotate left accumulator by known count */
8722 /*-----------------------------------------------------------------*/
8723 static void AccRol (int shCount)
8725 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8726 shCount &= 0x0007; // shCount : 0..7
8731 pic16_emitcode("rl","a");
8734 pic16_emitcode("rl","a");
8735 pic16_emitcode("rl","a");
8738 pic16_emitcode("swap","a");
8739 pic16_emitcode("rr","a");
8742 pic16_emitcode("swap","a");
8745 pic16_emitcode("swap","a");
8746 pic16_emitcode("rl","a");
8749 pic16_emitcode("rr","a");
8750 pic16_emitcode("rr","a");
8753 pic16_emitcode("rr","a");
8759 /*-----------------------------------------------------------------*/
8760 /* AccLsh - left shift accumulator by known count */
8761 /*-----------------------------------------------------------------*/
8762 static void AccLsh (int shCount, int doMask)
8764 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8770 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8773 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8774 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8777 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8778 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8781 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8784 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8785 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8788 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8789 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8792 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8796 /* no masking is required in genPackBits */
8797 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8801 /*-----------------------------------------------------------------*/
8802 /* AccRsh - right shift accumulator by known count */
8803 /*-----------------------------------------------------------------*/
8804 static void AccRsh (int shCount, int andmask)
8806 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8811 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8814 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8815 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8818 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8819 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8822 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8825 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8826 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8829 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8830 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8833 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8838 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8840 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8844 /*-----------------------------------------------------------------*/
8845 /* AccSRsh - signed right shift accumulator by known count */
8846 /*-----------------------------------------------------------------*/
8847 static void AccSRsh (int shCount)
8850 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8853 pic16_emitcode("mov","c,acc.7");
8854 pic16_emitcode("rrc","a");
8855 } else if(shCount == 2){
8856 pic16_emitcode("mov","c,acc.7");
8857 pic16_emitcode("rrc","a");
8858 pic16_emitcode("mov","c,acc.7");
8859 pic16_emitcode("rrc","a");
8861 tlbl = newiTempLabel(NULL);
8862 /* rotate right accumulator */
8863 AccRol(8 - shCount);
8864 /* and kill the higher order bits */
8865 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8866 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8867 pic16_emitcode("orl","a,#0x%02x",
8868 (unsigned char)~SRMask[shCount]);
8869 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8875 /*-----------------------------------------------------------------*/
8876 /* shiftR1Left2Result - shift right one byte from left to result */
8877 /*-----------------------------------------------------------------*/
8878 static void shiftR1Left2ResultSigned (operand *left, int offl,
8879 operand *result, int offr,
8884 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8886 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8890 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8892 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8894 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8895 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8901 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8903 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8905 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8906 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8908 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8909 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8915 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8917 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8918 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8921 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8922 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8923 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8925 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8926 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8928 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8932 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8933 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8934 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8935 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8936 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8940 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8942 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8943 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8945 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8946 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8947 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8948 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8949 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8954 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8955 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8956 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8957 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8958 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8959 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8961 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8962 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8963 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8964 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8965 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8971 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8972 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8973 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8974 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8976 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8977 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8978 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8986 /*-----------------------------------------------------------------*/
8987 /* shiftR1Left2Result - shift right one byte from left to result */
8988 /*-----------------------------------------------------------------*/
8989 static void shiftR1Left2Result (operand *left, int offl,
8990 operand *result, int offr,
8991 int shCount, int sign)
8995 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8997 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8999 /* Copy the msb into the carry if signed. */
9001 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
9011 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9013 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9014 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9020 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9022 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9023 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9026 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9031 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9033 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9034 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9037 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
9038 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9039 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9040 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9044 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9045 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9046 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9050 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9051 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
9052 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9054 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
9059 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
9060 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
9061 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9062 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9063 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
9068 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9069 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9070 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9079 /*-----------------------------------------------------------------*/
9080 /* shiftL1Left2Result - shift left one byte from left to result */
9081 /*-----------------------------------------------------------------*/
9082 static void shiftL1Left2Result (operand *left, int offl,
9083 operand *result, int offr, int shCount)
9088 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9090 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9091 DEBUGpic16_emitcode ("; ***","same = %d",same);
9092 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9094 /* shift left accumulator */
9095 //AccLsh(shCount, 1); // don't comment out just yet...
9096 // pic16_aopPut(AOP(result),"a",offr);
9100 /* Shift left 1 bit position */
9101 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9103 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9105 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9106 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9110 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9111 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9112 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9113 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9116 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9117 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9118 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9119 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9120 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9123 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9124 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9125 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9128 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9129 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9130 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9131 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9134 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9135 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9136 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9137 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9138 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9141 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9142 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9143 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9147 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9152 /*-----------------------------------------------------------------*/
9153 /* movLeft2Result - move byte from left to result */
9154 /*-----------------------------------------------------------------*/
9155 static void movLeft2Result (operand *left, int offl,
9156 operand *result, int offr)
9159 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9160 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9161 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9163 if (*l == '@' && (IS_AOP_PREG(result))) {
9164 pic16_emitcode("mov","a,%s",l);
9165 pic16_aopPut(AOP(result),"a",offr);
9167 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9168 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9173 /*-----------------------------------------------------------------*/
9174 /* shiftL2Left2Result - shift left two bytes from left to result */
9175 /*-----------------------------------------------------------------*/
9176 static void shiftL2Left2Result (operand *left, int offl,
9177 operand *result, int offr, int shCount)
9179 int same = pic16_sameRegs(AOP(result), AOP(left));
9182 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9184 if (same && (offl != offr)) { // shift bytes
9187 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9188 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9190 } else { // just treat as different later on
9203 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9204 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9205 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9209 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9210 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9216 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9217 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9218 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9219 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9220 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9221 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9222 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9224 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9225 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9229 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9230 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9231 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9232 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9233 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9234 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9235 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9236 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9237 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9238 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9241 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9242 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9243 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9244 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9245 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9255 /* note, use a mov/add for the shift since the mov has a
9256 chance of getting optimized out */
9257 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9258 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9259 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9260 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9261 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9265 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9266 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9272 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9273 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9274 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9275 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9276 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9277 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9278 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9279 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9283 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9284 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9288 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9289 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9290 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9291 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9293 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9294 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9295 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9296 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9297 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9298 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9299 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9300 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9303 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9304 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9305 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9306 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9307 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9312 /*-----------------------------------------------------------------*/
9313 /* shiftR2Left2Result - shift right two bytes from left to result */
9314 /*-----------------------------------------------------------------*/
9315 static void shiftR2Left2Result (operand *left, int offl,
9316 operand *result, int offr,
9317 int shCount, int sign)
9319 int same = pic16_sameRegs(AOP(result), AOP(left));
9321 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9323 if (same && (offl != offr)) { // shift right bytes
9326 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9327 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9329 } else { // just treat as different later on
9340 /* obtain sign from left operand */
9342 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),offr+MSB16));
9347 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9348 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9350 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9351 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9352 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9353 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9358 /* now get sign from already assigned result (avoid BANKSEL) */
9359 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9362 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9363 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9370 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9371 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9372 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9374 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9375 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9376 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9377 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9379 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9380 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9381 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9383 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9384 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9385 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9386 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9387 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9391 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9392 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9396 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9397 pic16_emitpcode(POC_BTFSC,
9398 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9399 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9407 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9408 pic16_emitpcode(POC_RLCF, 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));
9412 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9413 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9415 pic16_emitpcode(POC_BTFSC,
9416 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9417 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9419 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9420 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9421 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9422 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9424 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9425 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9426 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9427 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9428 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9429 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9430 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9431 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9433 pic16_emitpcode(POC_BTFSC,
9434 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9435 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9437 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9438 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9445 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9446 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9447 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9448 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9451 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9453 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9458 /*-----------------------------------------------------------------*/
9459 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9460 /*-----------------------------------------------------------------*/
9461 static void shiftLLeftOrResult (operand *left, int offl,
9462 operand *result, int offr, int shCount)
9464 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9466 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9467 /* shift left accumulator */
9469 /* or with result */
9470 /* back to result */
9471 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9474 /*-----------------------------------------------------------------*/
9475 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9476 /*-----------------------------------------------------------------*/
9477 static void shiftRLeftOrResult (operand *left, int offl,
9478 operand *result, int offr, int shCount)
9480 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9482 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9483 /* shift right accumulator */
9485 /* or with result */
9486 /* back to result */
9487 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9490 /*-----------------------------------------------------------------*/
9491 /* genlshOne - left shift a one byte quantity by known count */
9492 /*-----------------------------------------------------------------*/
9493 static void genlshOne (operand *result, operand *left, int shCount)
9495 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9496 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9499 /*-----------------------------------------------------------------*/
9500 /* genlshTwo - left shift two bytes by known amount != 0 */
9501 /*-----------------------------------------------------------------*/
9502 static void genlshTwo (operand *result,operand *left, int shCount)
9506 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9507 size = pic16_getDataSize(result);
9509 /* if shCount >= 8 */
9515 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9517 movLeft2Result(left, LSB, result, MSB16);
9519 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9522 /* 1 <= shCount <= 7 */
9525 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9527 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9531 /*-----------------------------------------------------------------*/
9532 /* shiftLLong - shift left one long from left to result */
9533 /* offr = LSB or MSB16 */
9534 /*-----------------------------------------------------------------*/
9535 static void shiftLLong (operand *left, operand *result, int offr )
9537 int size = AOP_SIZE(result);
9538 int same = pic16_sameRegs(AOP(left),AOP(result));
9541 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9543 if (same && (offr == MSB16)) { //shift one byte
9544 for(i=size-1;i>=MSB16;i--) {
9545 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9546 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9549 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9552 if (size > LSB+offr ){
9554 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9556 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9557 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9561 if(size > MSB16+offr){
9563 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9565 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9566 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9570 if(size > MSB24+offr){
9572 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9574 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9575 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9579 if(size > MSB32+offr){
9581 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9583 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9584 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9588 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9592 /*-----------------------------------------------------------------*/
9593 /* genlshFour - shift four byte by a known amount != 0 */
9594 /*-----------------------------------------------------------------*/
9595 static void genlshFour (operand *result, operand *left, int shCount)
9599 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9600 size = AOP_SIZE(result);
9602 /* if shifting more that 3 bytes */
9603 if (shCount >= 24 ) {
9606 /* lowest order of left goes to the highest
9607 order of the destination */
9608 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9610 movLeft2Result(left, LSB, result, MSB32);
9612 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9613 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9614 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9619 /* more than two bytes */
9620 else if ( shCount >= 16 ) {
9621 /* lower order two bytes goes to higher order two bytes */
9623 /* if some more remaining */
9625 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9627 movLeft2Result(left, MSB16, result, MSB32);
9628 movLeft2Result(left, LSB, result, MSB24);
9630 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9631 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9635 /* if more than 1 byte */
9636 else if ( shCount >= 8 ) {
9637 /* lower order three bytes goes to higher order three bytes */
9641 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9643 movLeft2Result(left, LSB, result, MSB16);
9645 else{ /* size = 4 */
9647 movLeft2Result(left, MSB24, result, MSB32);
9648 movLeft2Result(left, MSB16, result, MSB24);
9649 movLeft2Result(left, LSB, result, MSB16);
9650 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9652 else if(shCount == 1)
9653 shiftLLong(left, result, MSB16);
9655 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9656 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9657 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9658 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9663 /* 1 <= shCount <= 7 */
9664 else if(shCount <= 3)
9666 shiftLLong(left, result, LSB);
9667 while(--shCount >= 1)
9668 shiftLLong(result, result, LSB);
9670 /* 3 <= shCount <= 7, optimize */
9672 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9673 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9674 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9678 /*-----------------------------------------------------------------*/
9679 /* genLeftShiftLiteral - left shifting by known count */
9680 /*-----------------------------------------------------------------*/
9681 void pic16_genLeftShiftLiteral (operand *left,
9686 int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
9690 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9691 pic16_freeAsmop(right,NULL,ic,TRUE);
9693 pic16_aopOp(left,ic,FALSE);
9694 pic16_aopOp(result,ic,TRUE);
9696 size = getSize(operandType(result));
9699 pic16_emitcode("; shift left ","result %d, left %d",size,
9703 /* I suppose that the left size >= result size */
9706 movLeft2Result(left, size, result, size);
9710 else if(shCount >= (size * 8))
9712 pic16_aopPut(AOP(result),zero,size);
9716 genlshOne (result,left,shCount);
9721 genlshTwo (result,left,shCount);
9725 genlshFour (result,left,shCount);
9729 pic16_freeAsmop(left,NULL,ic,TRUE);
9730 pic16_freeAsmop(result,NULL,ic,TRUE);
9733 /*-----------------------------------------------------------------*
9734 * genMultiAsm - repeat assembly instruction for size of register.
9735 * if endian == 1, then the high byte (i.e base address + size of
9736 * register) is used first else the low byte is used first;
9737 *-----------------------------------------------------------------*/
9738 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9743 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9756 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9762 #if !(USE_GENERIC_SIGNED_SHIFT)
9763 /*-----------------------------------------------------------------*/
9764 /* genLeftShift - generates code for left shifting */
9765 /*-----------------------------------------------------------------*/
9766 static void genLeftShift (iCode *ic)
9768 operand *left,*right, *result;
9771 symbol *tlbl , *tlbl1;
9774 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9776 right = IC_RIGHT(ic);
9778 result = IC_RESULT(ic);
9780 pic16_aopOp(right,ic,FALSE);
9782 /* if the shift count is known then do it
9783 as efficiently as possible */
9784 if (AOP_TYPE(right) == AOP_LIT) {
9785 pic16_genLeftShiftLiteral (left,right,result,ic);
9789 /* shift count is unknown then we have to form
9790 * a loop. Get the loop count in WREG : Note: we take
9791 * only the lower order byte since shifting
9792 * more than 32 bits make no sense anyway, ( the
9793 * largest size of an object can be only 32 bits ) */
9795 pic16_aopOp(left,ic,FALSE);
9796 pic16_aopOp(result,ic,FALSE);
9798 /* now move the left to the result if they are not the
9799 * same, and if size > 1,
9800 * and if right is not same to result (!!!) -- VR */
9801 if (!pic16_sameRegs(AOP(left),AOP(result))
9802 && (AOP_SIZE(result) > 1)) {
9804 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9806 size = AOP_SIZE(result);
9811 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9812 if (*l == '@' && (IS_AOP_PREG(result))) {
9814 pic16_emitcode("mov","a,%s",l);
9815 pic16_aopPut(AOP(result),"a",offset);
9819 /* we don't know if left is a literal or a register, take care -- VR */
9820 pic16_mov2f(AOP(result), AOP(left), offset);
9826 size = AOP_SIZE(result);
9828 /* if it is only one byte then */
9830 if(optimized_for_speed) {
9831 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9832 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9833 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9834 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9835 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9836 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9837 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9838 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9839 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9840 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9841 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9842 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9845 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9847 tlbl = newiTempLabel(NULL);
9850 /* this is already done, why change it? */
9851 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9852 pic16_mov2f(AOP(result), AOP(left), 0);
9856 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9857 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9858 pic16_emitpLabel(tlbl->key);
9859 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9860 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9862 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9867 if (pic16_sameRegs(AOP(left),AOP(result))) {
9869 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9871 tlbl = newiTempLabel(NULL);
9872 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9873 genMultiAsm(POC_RRCF, result, size,1);
9874 pic16_emitpLabel(tlbl->key);
9875 genMultiAsm(POC_RLCF, result, size,0);
9876 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9878 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9882 //tlbl = newiTempLabel(NULL);
9884 //tlbl1 = newiTempLabel(NULL);
9886 //reAdjustPreg(AOP(result));
9888 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9889 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9890 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9892 //pic16_emitcode("add","a,acc");
9893 //pic16_aopPut(AOP(result),"a",offset++);
9895 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9897 // pic16_emitcode("rlc","a");
9898 // pic16_aopPut(AOP(result),"a",offset++);
9900 //reAdjustPreg(AOP(result));
9902 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9903 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9906 tlbl = newiTempLabel(NULL);
9907 tlbl1= newiTempLabel(NULL);
9909 size = AOP_SIZE(result);
9912 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9914 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9916 /* offset should be 0, 1 or 3 */
9918 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9920 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9922 pic16_emitpcode(POC_MOVWF, pctemp);
9925 pic16_emitpLabel(tlbl->key);
9928 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9930 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9932 pic16_emitpcode(POC_DECFSZ, pctemp);
9933 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9934 pic16_emitpLabel(tlbl1->key);
9936 pic16_popReleaseTempReg(pctemp,1);
9940 pic16_freeAsmop (right,NULL,ic,TRUE);
9941 pic16_freeAsmop(left,NULL,ic,TRUE);
9942 pic16_freeAsmop(result,NULL,ic,TRUE);
9948 #error old code (left here for reference)
9949 /*-----------------------------------------------------------------*/
9950 /* genLeftShift - generates code for left shifting */
9951 /*-----------------------------------------------------------------*/
9952 static void genLeftShift (iCode *ic)
9954 operand *left,*right, *result;
9957 symbol *tlbl , *tlbl1;
9960 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9962 right = IC_RIGHT(ic);
9964 result = IC_RESULT(ic);
9966 pic16_aopOp(right,ic,FALSE);
9968 /* if the shift count is known then do it
9969 as efficiently as possible */
9970 if (AOP_TYPE(right) == AOP_LIT) {
9971 pic16_genLeftShiftLiteral (left,right,result,ic);
9975 /* shift count is unknown then we have to form
9976 a loop get the loop count in B : Note: we take
9977 only the lower order byte since shifting
9978 more that 32 bits make no sense anyway, ( the
9979 largest size of an object can be only 32 bits ) */
9982 pic16_aopOp(left,ic,FALSE);
9983 pic16_aopOp(result,ic,FALSE);
9985 /* now move the left to the result if they are not the
9987 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9988 AOP_SIZE(result) > 1) {
9990 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9992 size = AOP_SIZE(result);
9995 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9996 if (*l == '@' && (IS_AOP_PREG(result))) {
9998 pic16_emitcode("mov","a,%s",l);
9999 pic16_aopPut(AOP(result),"a",offset);
10002 /* we don't know if left is a literal or a register, take care -- VR */
10003 pic16_mov2f(AOP(result), AOP(left), offset);
10009 size = AOP_SIZE(result);
10011 /* if it is only one byte then */
10013 if(optimized_for_speed) {
10014 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
10015 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
10016 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
10017 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10018 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10019 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
10020 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
10021 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
10022 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
10023 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
10024 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
10025 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
10028 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10030 tlbl = newiTempLabel(NULL);
10031 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10032 pic16_mov2f(AOP(result), AOP(left), 0);
10034 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10035 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10038 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10039 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10040 pic16_emitpLabel(tlbl->key);
10041 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10042 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10044 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10049 if (pic16_sameRegs(AOP(left),AOP(result))) {
10051 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10053 tlbl = newiTempLabel(NULL);
10054 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10055 genMultiAsm(POC_RRCF, result, size,1);
10056 pic16_emitpLabel(tlbl->key);
10057 genMultiAsm(POC_RLCF, result, size,0);
10058 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10060 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10064 //tlbl = newiTempLabel(NULL);
10066 //tlbl1 = newiTempLabel(NULL);
10068 //reAdjustPreg(AOP(result));
10070 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10071 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10072 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10074 //pic16_emitcode("add","a,acc");
10075 //pic16_aopPut(AOP(result),"a",offset++);
10077 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10079 // pic16_emitcode("rlc","a");
10080 // pic16_aopPut(AOP(result),"a",offset++);
10082 //reAdjustPreg(AOP(result));
10084 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10085 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10088 tlbl = newiTempLabel(NULL);
10089 tlbl1= newiTempLabel(NULL);
10091 size = AOP_SIZE(result);
10094 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10096 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10098 /* offset should be 0, 1 or 3 */
10100 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10102 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10104 pic16_emitpcode(POC_MOVWF, pctemp);
10107 pic16_emitpLabel(tlbl->key);
10110 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10112 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
10114 pic16_emitpcode(POC_DECFSZ, pctemp);
10115 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10116 pic16_emitpLabel(tlbl1->key);
10118 pic16_popReleaseTempReg(pctemp,1);
10122 pic16_freeAsmop (right,NULL,ic,TRUE);
10123 pic16_freeAsmop(left,NULL,ic,TRUE);
10124 pic16_freeAsmop(result,NULL,ic,TRUE);
10128 /*-----------------------------------------------------------------*/
10129 /* genrshOne - right shift a one byte quantity by known count */
10130 /*-----------------------------------------------------------------*/
10131 static void genrshOne (operand *result, operand *left,
10132 int shCount, int sign)
10134 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10135 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10138 /*-----------------------------------------------------------------*/
10139 /* genrshTwo - right shift two bytes by known amount != 0 */
10140 /*-----------------------------------------------------------------*/
10141 static void genrshTwo (operand *result,operand *left,
10142 int shCount, int sign)
10144 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10145 /* if shCount >= 8 */
10146 if (shCount >= 8) {
10149 shiftR1Left2Result(left, MSB16, result, LSB,
10152 movLeft2Result(left, MSB16, result, LSB);
10154 pic16_addSign (result, 1, sign);
10157 /* 1 <= shCount <= 7 */
10159 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
10162 /*-----------------------------------------------------------------*/
10163 /* shiftRLong - shift right one long from left to result */
10164 /* offl = LSB or MSB16 */
10165 /*-----------------------------------------------------------------*/
10166 static void shiftRLong (operand *left, int offl,
10167 operand *result, int sign)
10169 int size = AOP_SIZE(result);
10170 int same = pic16_sameRegs(AOP(left),AOP(result));
10172 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10174 if (same && (offl == MSB16)) { //shift one byte right
10175 for(i=MSB16;i<size;i++) {
10176 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10177 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10182 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10188 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10190 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10191 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10194 if(offl == MSB16) {
10195 /* add sign of "a" */
10196 pic16_addSign(result, MSB32, sign);
10200 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10202 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10203 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10207 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10209 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10210 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10214 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10217 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10218 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10223 /*-----------------------------------------------------------------*/
10224 /* genrshFour - shift four byte by a known amount != 0 */
10225 /*-----------------------------------------------------------------*/
10226 static void genrshFour (operand *result, operand *left,
10227 int shCount, int sign)
10229 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10230 /* if shifting more that 3 bytes */
10231 if(shCount >= 24 ) {
10234 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10236 movLeft2Result(left, MSB32, result, LSB);
10238 pic16_addSign(result, MSB16, sign);
10240 else if(shCount >= 16){
10243 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10245 movLeft2Result(left, MSB24, result, LSB);
10246 movLeft2Result(left, MSB32, result, MSB16);
10248 pic16_addSign(result, MSB24, sign);
10250 else if(shCount >= 8){
10253 shiftRLong(left, MSB16, result, sign);
10254 else if(shCount == 0){
10255 movLeft2Result(left, MSB16, result, LSB);
10256 movLeft2Result(left, MSB24, result, MSB16);
10257 movLeft2Result(left, MSB32, result, MSB24);
10258 pic16_addSign(result, MSB32, sign);
10260 else{ //shcount >= 2
10261 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10262 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10263 /* the last shift is signed */
10264 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10265 pic16_addSign(result, MSB32, sign);
10268 else{ /* 1 <= shCount <= 7 */
10270 shiftRLong(left, LSB, result, sign);
10272 shiftRLong(result, LSB, result, sign);
10275 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10276 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10277 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10282 /*-----------------------------------------------------------------*/
10283 /* genRightShiftLiteral - right shifting by known count */
10284 /*-----------------------------------------------------------------*/
10285 static void genRightShiftLiteral (operand *left,
10291 int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
10292 int lsize,res_size;
10294 pic16_freeAsmop(right,NULL,ic,TRUE);
10296 pic16_aopOp(left,ic,FALSE);
10297 pic16_aopOp(result,ic,TRUE);
10299 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10302 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10306 lsize = pic16_getDataSize(left);
10307 res_size = pic16_getDataSize(result);
10308 /* test the LEFT size !!! */
10310 /* I suppose that the left size >= result size */
10312 assert (res_size <= lsize);
10313 while (res_size--) {
10314 pic16_mov2f (AOP(result), AOP(left), res_size);
10318 else if(shCount >= (lsize * 8)){
10320 if(res_size == 1) {
10321 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10323 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10324 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10329 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10330 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10331 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10333 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10338 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10343 switch (res_size) {
10345 genrshOne (result,left,shCount,sign);
10349 genrshTwo (result,left,shCount,sign);
10353 genrshFour (result,left,shCount,sign);
10361 pic16_freeAsmop(left,NULL,ic,TRUE);
10362 pic16_freeAsmop(result,NULL,ic,TRUE);
10365 #if !(USE_GENERIC_SIGNED_SHIFT)
10366 /*-----------------------------------------------------------------*/
10367 /* genSignedRightShift - right shift of signed number */
10368 /*-----------------------------------------------------------------*/
10369 static void genSignedRightShift (iCode *ic)
10371 operand *right, *left, *result;
10374 symbol *tlbl, *tlbl1 ;
10377 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10379 /* we do it the hard way put the shift count in b
10380 and loop thru preserving the sign */
10381 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10383 right = IC_RIGHT(ic);
10384 left = IC_LEFT(ic);
10385 result = IC_RESULT(ic);
10387 pic16_aopOp(right,ic,FALSE);
10388 pic16_aopOp(left,ic,FALSE);
10389 pic16_aopOp(result,ic,FALSE);
10392 if ( AOP_TYPE(right) == AOP_LIT) {
10393 genRightShiftLiteral (left,right,result,ic,1);
10396 /* shift count is unknown then we have to form
10397 a loop get the loop count in B : Note: we take
10398 only the lower order byte since shifting
10399 more that 32 bits make no sense anyway, ( the
10400 largest size of an object can be only 32 bits ) */
10402 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10403 //pic16_emitcode("inc","b");
10404 //pic16_freeAsmop (right,NULL,ic,TRUE);
10405 //pic16_aopOp(left,ic,FALSE);
10406 //pic16_aopOp(result,ic,FALSE);
10408 /* now move the left to the result if they are not the
10410 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10411 AOP_SIZE(result) > 1) {
10413 size = AOP_SIZE(result);
10417 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10418 if (*l == '@' && IS_AOP_PREG(result)) {
10420 pic16_emitcode("mov","a,%s",l);
10421 pic16_aopPut(AOP(result),"a",offset);
10423 pic16_aopPut(AOP(result),l,offset);
10425 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10426 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10432 /* mov the highest order bit to OVR */
10433 tlbl = newiTempLabel(NULL);
10434 tlbl1= newiTempLabel(NULL);
10436 size = AOP_SIZE(result);
10439 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10441 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10443 /* offset should be 0, 1 or 3 */
10444 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10446 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10448 pic16_emitpcode(POC_MOVWF, pctemp);
10451 pic16_emitpLabel(tlbl->key);
10453 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10454 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10457 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10460 pic16_emitpcode(POC_DECFSZ, pctemp);
10461 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10462 pic16_emitpLabel(tlbl1->key);
10464 pic16_popReleaseTempReg(pctemp,1);
10466 size = AOP_SIZE(result);
10468 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10469 pic16_emitcode("rlc","a");
10470 pic16_emitcode("mov","ov,c");
10471 /* if it is only one byte then */
10473 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10475 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10476 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10477 pic16_emitcode("mov","c,ov");
10478 pic16_emitcode("rrc","a");
10479 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10480 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10481 pic16_aopPut(AOP(result),"a",0);
10485 reAdjustPreg(AOP(result));
10486 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10487 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10488 pic16_emitcode("mov","c,ov");
10490 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10492 pic16_emitcode("rrc","a");
10493 pic16_aopPut(AOP(result),"a",offset--);
10495 reAdjustPreg(AOP(result));
10496 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10497 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10502 pic16_freeAsmop(left,NULL,ic,TRUE);
10503 pic16_freeAsmop(result,NULL,ic,TRUE);
10504 pic16_freeAsmop(right,NULL,ic,TRUE);
10508 #if !(USE_GENERIC_SIGNED_SHIFT)
10509 #warning This implementation of genRightShift() is incomplete!
10510 /*-----------------------------------------------------------------*/
10511 /* genRightShift - generate code for right shifting */
10512 /*-----------------------------------------------------------------*/
10513 static void genRightShift (iCode *ic)
10515 operand *right, *left, *result;
10519 symbol *tlbl, *tlbl1 ;
10521 /* if signed then we do it the hard way preserve the
10522 sign bit moving it inwards */
10523 letype = getSpec(operandType(IC_LEFT(ic)));
10524 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10526 if (!SPEC_USIGN(letype)) {
10527 genSignedRightShift (ic);
10531 /* signed & unsigned types are treated the same : i.e. the
10532 signed is NOT propagated inwards : quoting from the
10533 ANSI - standard : "for E1 >> E2, is equivalent to division
10534 by 2**E2 if unsigned or if it has a non-negative value,
10535 otherwise the result is implementation defined ", MY definition
10536 is that the sign does not get propagated */
10538 right = IC_RIGHT(ic);
10539 left = IC_LEFT(ic);
10540 result = IC_RESULT(ic);
10542 pic16_aopOp(right,ic,FALSE);
10544 /* if the shift count is known then do it
10545 as efficiently as possible */
10546 if (AOP_TYPE(right) == AOP_LIT) {
10547 genRightShiftLiteral (left,right,result,ic, 0);
10551 /* shift count is unknown then we have to form
10552 a loop get the loop count in B : Note: we take
10553 only the lower order byte since shifting
10554 more that 32 bits make no sense anyway, ( the
10555 largest size of an object can be only 32 bits ) */
10557 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10558 pic16_emitcode("inc","b");
10559 pic16_aopOp(left,ic,FALSE);
10560 pic16_aopOp(result,ic,FALSE);
10562 /* now move the left to the result if they are not the
10564 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10565 AOP_SIZE(result) > 1) {
10567 size = AOP_SIZE(result);
10570 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10571 if (*l == '@' && IS_AOP_PREG(result)) {
10573 pic16_emitcode("mov","a,%s",l);
10574 pic16_aopPut(AOP(result),"a",offset);
10576 pic16_aopPut(AOP(result),l,offset);
10581 tlbl = newiTempLabel(NULL);
10582 tlbl1= newiTempLabel(NULL);
10583 size = AOP_SIZE(result);
10586 /* if it is only one byte then */
10589 tlbl = newiTempLabel(NULL);
10590 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10591 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10592 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10595 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10596 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10597 pic16_emitpLabel(tlbl->key);
10598 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10599 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10601 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10606 reAdjustPreg(AOP(result));
10607 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10608 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10611 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10613 pic16_emitcode("rrc","a");
10614 pic16_aopPut(AOP(result),"a",offset--);
10616 reAdjustPreg(AOP(result));
10618 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10619 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10622 pic16_freeAsmop(left,NULL,ic,TRUE);
10623 pic16_freeAsmop (right,NULL,ic,TRUE);
10624 pic16_freeAsmop(result,NULL,ic,TRUE);
10628 #if (USE_GENERIC_SIGNED_SHIFT)
10629 /*-----------------------------------------------------------------*/
10630 /* genGenericShift - generates code for left or right shifting */
10631 /*-----------------------------------------------------------------*/
10632 static void genGenericShift (iCode *ic, int isShiftLeft) {
10633 operand *left,*right, *result;
10635 int sign, signedCount;
10636 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10637 PIC_OPCODE pos_shift, neg_shift;
10641 right = IC_RIGHT(ic);
10642 left = IC_LEFT(ic);
10643 result = IC_RESULT(ic);
10645 pic16_aopOp(right,ic,FALSE);
10646 pic16_aopOp(left,ic,FALSE);
10647 pic16_aopOp(result,ic,TRUE);
10649 sign = !SPEC_USIGN(operandType (left));
10650 signedCount = !SPEC_USIGN(operandType (right));
10652 /* if the shift count is known then do it
10653 as efficiently as possible */
10654 if (AOP_TYPE(right) == AOP_LIT) {
10655 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10656 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10657 // we should modify right->aopu.aop_lit here!
10658 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10659 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10661 pic16_genLeftShiftLiteral (left,right,result,ic);
10663 genRightShiftLiteral (left,right,result,ic, sign);
10666 } // if (right is literal)
10668 /* shift count is unknown then we have to form a loop.
10669 * Note: we take only the lower order byte since shifting
10670 * more than 32 bits make no sense anyway, ( the
10671 * largest size of an object can be only 32 bits )
10672 * Note: we perform arithmetic shifts if the left operand is
10673 * signed and we do an (effective) right shift, i. e. we
10674 * shift in the sign bit from the left. */
10676 label_complete = newiTempLabel ( NULL );
10677 label_loop_pos = newiTempLabel ( NULL );
10678 label_loop_neg = NULL;
10679 label_negative = NULL;
10680 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10681 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10684 // additional labels needed
10685 label_loop_neg = newiTempLabel ( NULL );
10686 label_negative = newiTempLabel ( NULL );
10689 // copy source to result -- this will effectively truncate the left operand to the size of result!
10690 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10691 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10692 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10693 pic16_mov2f (AOP(result),AOP(left), offset);
10696 // if result is longer than left, fill with zeros (or sign)
10697 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10698 if (sign && AOP_SIZE(left) > 0) {
10699 // shift signed operand -- fill with sign
10700 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10701 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10702 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10703 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10704 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10707 // shift unsigned operand -- fill result with zeros
10708 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10709 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10712 } // if (size mismatch)
10714 pic16_mov2w (AOP(right), 0);
10715 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10716 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10719 // perform a shift by one (shift count is positive)
10720 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10721 // 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])
10722 pic16_emitpLabel (label_loop_pos->key);
10724 if (sign && (pos_shift == POC_RRCF)) {
10725 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10728 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10729 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10730 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10732 // perform a shift by one (shift count is positive)
10733 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10734 // 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])
10735 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10736 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10738 pic16_emitpLabel (label_loop_pos->key);
10739 if (sign && (pos_shift == POC_RRCF)) {
10740 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10743 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10744 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10745 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10746 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10750 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10752 pic16_emitpLabel (label_negative->key);
10753 // perform a shift by -1 (shift count is negative)
10754 // 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)
10756 pic16_emitpLabel (label_loop_neg->key);
10757 if (sign && (neg_shift == POC_RRCF)) {
10758 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10761 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10762 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10763 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10764 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10765 } // if (signedCount)
10767 pic16_emitpLabel (label_complete->key);
10770 pic16_freeAsmop (right,NULL,ic,TRUE);
10771 pic16_freeAsmop(left,NULL,ic,TRUE);
10772 pic16_freeAsmop(result,NULL,ic,TRUE);
10775 static void genLeftShift (iCode *ic) {
10776 genGenericShift (ic, 1);
10779 static void genRightShift (iCode *ic) {
10780 genGenericShift (ic, 0);
10785 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10786 void pic16_loadFSR0(operand *op, int lit)
10788 if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) {
10789 if (AOP_TYPE(op) == AOP_LIT) {
10790 /* handle 12 bit integers correctly */
10791 unsigned int val = (unsigned int)floatFromVal(AOP(op)->aopu.aop_lit);
10792 if ((val & 0x0fff) != val) {
10793 fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
10794 val, (val & 0x0fff) );
10797 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
10799 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10802 assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
10803 // set up FSR0 with address of result
10804 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10805 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10809 /*----------------------------------------------------------------*/
10810 /* pic16_derefPtr - move one byte from the location ptr points to */
10811 /* to WREG (doWrite == 0) or one byte from WREG */
10812 /* to the location ptr points to (doWrite != 0) */
10813 /*----------------------------------------------------------------*/
10814 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10816 if (!IS_PTR(operandType(ptr)))
10818 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10819 else pic16_mov2w (AOP(ptr), 0);
10823 //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10824 /* We might determine pointer type right here: */
10825 p_type = DCL_TYPE(operandType(ptr));
10830 if (!fsr0_setup || !*fsr0_setup)
10832 pic16_loadFSR0( ptr, 0 );
10833 if (fsr0_setup) *fsr0_setup = 1;
10836 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10838 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10842 if (AOP(ptr)->aopu.aop_reg[2]) {
10843 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10844 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10845 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10846 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10847 pic16_mov2w(AOP(ptr), 2);
10848 pic16_callGenericPointerRW(doWrite, 1);
10850 // data pointer (just 2 byte given)
10851 if (!fsr0_setup || !*fsr0_setup)
10853 pic16_loadFSR0( ptr, 0 );
10854 if (fsr0_setup) *fsr0_setup = 1;
10857 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10859 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10864 assert (0 && "invalid pointer type specified");
10869 /*-----------------------------------------------------------------*/
10870 /* genUnpackBits - generates code for unpacking bits */
10871 /*-----------------------------------------------------------------*/
10872 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10875 sym_link *etype, *letype;
10876 int blen=0, bstr=0;
10881 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10882 etype = getSpec(operandType(result));
10883 letype = getSpec(operandType(left));
10885 // if(IS_BITFIELD(etype)) {
10886 blen = SPEC_BLEN(etype);
10887 bstr = SPEC_BSTR(etype);
10890 lbstr = SPEC_BSTR( letype );
10892 DEBUGpic16_emitcode ("; ***","%s %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10893 SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10896 if((blen == 1) && (bstr < 8)
10897 && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10898 /* it is a single bit, so use the appropriate bit instructions */
10899 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10901 same = pic16_sameRegs(AOP(left),AOP(result));
10902 op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10903 pic16_emitpcode(POC_CLRF, op);
10905 if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10906 /* workaround to reduce the extra lfsr instruction */
10907 pic16_emitpcode(POC_BTFSC,
10908 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10910 assert (PIC_IS_DATA_PTR (operandType(left)));
10911 pic16_loadFSR0 (left, 0);
10912 pic16_emitpcode(POC_BTFSC,
10913 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10916 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10917 /* unsigned bitfields result in either 0 or 1 */
10918 pic16_emitpcode(POC_INCF, op);
10920 /* signed bitfields result in either 0 or -1 */
10921 pic16_emitpcode(POC_DECF, op);
10924 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10927 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10933 if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10934 // access symbol directly
10935 pic16_mov2w (AOP(left), 0);
10937 pic16_derefPtr (left, ptype, 0, NULL);
10940 /* if we have bitdisplacement then it fits */
10941 /* into this byte completely or if length is */
10942 /* less than a byte */
10943 if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8)) {
10945 /* shift right acc */
10948 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10949 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10951 /* VR -- normally I would use the following, but since we use the hack,
10952 * to avoid the masking from AccRsh, why not mask it right now? */
10955 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10958 /* extend signed bitfields to 8 bits */
10959 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10961 assert (blen + bstr > 0);
10962 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10963 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10966 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10968 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10972 fprintf(stderr, "SDCC pic16 port error: the port currently does not support *reading*\n");
10973 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10974 exit(EXIT_FAILURE);
10980 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
10982 int size, offset = 0, leoffset=0 ;
10984 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10985 pic16_aopOp(result, ic, TRUE);
10989 size = AOP_SIZE(result);
10990 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10994 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10995 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10996 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
11001 if(AOP(left)->aopu.pcop->type == PO_DIR)
11002 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
11004 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11007 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
11009 // pic16_DumpOp("(result)",result);
11010 if(is_LitAOp(AOP(result))) {
11011 pic16_mov2w(AOP(left), offset); // patch 8
11012 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
11014 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11015 pic16_popGet(AOP(left), offset), //patch 8
11016 pic16_popGet(AOP(result), offset)));
11024 pic16_freeAsmop(result,NULL,ic,TRUE);
11029 /*-----------------------------------------------------------------*/
11030 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
11031 /*-----------------------------------------------------------------*/
11032 static void genNearPointerGet (operand *left,
11036 // asmop *aop = NULL;
11037 //regs *preg = NULL ;
11038 sym_link *rtype, *retype;
11039 sym_link *ltype, *letype;
11043 rtype = operandType(result);
11044 retype= getSpec(rtype);
11045 ltype = operandType(left);
11046 letype= getSpec(ltype);
11048 pic16_aopOp(left,ic,FALSE);
11050 // pic16_DumpOp("(left)",left);
11051 // pic16_DumpOp("(result)",result);
11053 /* if left is rematerialisable and
11054 * result is not bit variable type and
11055 * the left is pointer to data space i.e
11056 * lower 128 bytes of space */
11058 if (AOP_TYPE(left) == AOP_PCODE
11059 && !IS_BITFIELD(retype)
11060 && DCL_TYPE(ltype) == POINTER) {
11062 genDataPointerGet (left,result,ic);
11063 pic16_freeAsmop(left, NULL, ic, TRUE);
11067 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11068 pic16_aopOp (result,ic,TRUE);
11070 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11073 if(IS_BITFIELD( retype )
11074 && (SPEC_BLEN(operandType(result))==1)
11078 int bitstrt, bytestrt;
11080 /* if this is bitfield of size 1, see if we are checking the value
11081 * of a single bit in an if-statement,
11082 * if yes, then don't generate usual code, but execute the
11083 * genIfx directly -- VR */
11087 /* CHECK: if next iCode is IFX
11088 * and current result operand is nextic's conditional operand
11089 * and current result operand live ranges ends at nextic's key number
11091 if((nextic->op == IFX)
11092 && (result == IC_COND(nextic))
11093 && (OP_LIVETO(result) == nextic->seq)
11094 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
11096 /* everything is ok then */
11097 /* find a way to optimize the genIfx iCode */
11099 bytestrt = SPEC_BSTR(operandType(result))/8;
11100 bitstrt = SPEC_BSTR(operandType(result))%8;
11102 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
11104 genIfxpCOpJump(nextic, jop);
11106 pic16_freeAsmop(left, NULL, ic, TRUE);
11107 pic16_freeAsmop(result, NULL, ic, TRUE);
11113 /* if bitfield then unpack the bits */
11114 if (IS_BITFIELD(letype))
11115 genUnpackBits (result, left, NULL, POINTER);
11117 /* we have can just get the values */
11118 int size = AOP_SIZE(result);
11121 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11123 pic16_loadFSR0( left, 0 );
11127 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11128 pic16_popGet(AOP(result), offset++)));
11130 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11131 pic16_popGet(AOP(result), offset++)));
11137 /* now some housekeeping stuff */
11139 /* we had to allocate for this iCode */
11140 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11141 pic16_freeAsmop(NULL,aop,ic,TRUE);
11143 /* we did not allocate which means left
11144 * already in a pointer register, then
11145 * if size > 0 && this could be used again
11146 * we have to point it back to where it
11148 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11149 if (AOP_SIZE(result) > 1
11150 && !OP_SYMBOL(left)->remat
11151 && ( OP_SYMBOL(left)->liveTo > ic->seq
11153 // int size = AOP_SIZE(result) - 1;
11155 // pic16_emitcode("dec","%s",rname);
11161 pic16_freeAsmop(left,NULL,ic,TRUE);
11162 pic16_freeAsmop(result,NULL,ic,TRUE);
11165 /*-----------------------------------------------------------------*/
11166 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
11167 /*-----------------------------------------------------------------*/
11168 static void genPagedPointerGet (operand *left,
11173 regs *preg = NULL ;
11175 sym_link *rtype, *retype;
11177 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11179 rtype = operandType(result);
11180 retype= getSpec(rtype);
11182 pic16_aopOp(left,ic,FALSE);
11184 /* if the value is already in a pointer register
11185 then don't need anything more */
11186 if (!AOP_INPREG(AOP(left))) {
11187 /* otherwise get a free pointer register */
11189 preg = getFreePtr(ic,&aop,FALSE);
11190 pic16_emitcode("mov","%s,%s",
11192 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11193 rname = preg->name ;
11195 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11197 pic16_freeAsmop(left,NULL,ic,TRUE);
11198 pic16_aopOp (result,ic,TRUE);
11200 /* if bitfield then unpack the bits */
11201 if (IS_BITFIELD(retype))
11202 genUnpackBits (result,left,rname,PPOINTER);
11204 /* we have can just get the values */
11205 int size = AOP_SIZE(result);
11210 pic16_emitcode("movx","a,@%s",rname);
11211 pic16_aopPut(AOP(result),"a",offset);
11216 pic16_emitcode("inc","%s",rname);
11220 /* now some housekeeping stuff */
11222 /* we had to allocate for this iCode */
11223 pic16_freeAsmop(NULL,aop,ic,TRUE);
11225 /* we did not allocate which means left
11226 already in a pointer register, then
11227 if size > 0 && this could be used again
11228 we have to point it back to where it
11230 if (AOP_SIZE(result) > 1 &&
11231 !OP_SYMBOL(left)->remat &&
11232 ( OP_SYMBOL(left)->liveTo > ic->seq ||
11234 int size = AOP_SIZE(result) - 1;
11236 pic16_emitcode("dec","%s",rname);
11241 pic16_freeAsmop(result,NULL,ic,TRUE);
11247 /* This code is not adjusted to PIC16 and fails utterly.
11248 * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
11250 /*-----------------------------------------------------------------*/
11251 /* genFarPointerGet - gget value from far space */
11252 /*-----------------------------------------------------------------*/
11253 static void genFarPointerGet (operand *left,
11254 operand *result, iCode *ic)
11257 sym_link *retype = getSpec(operandType(result));
11259 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11261 pic16_aopOp(left,ic,FALSE);
11263 /* if the operand is already in dptr
11264 then we do nothing else we move the value to dptr */
11265 if (AOP_TYPE(left) != AOP_STR) {
11266 /* if this is remateriazable */
11267 if (AOP_TYPE(left) == AOP_IMMD)
11268 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11269 else { /* we need to get it byte by byte */
11270 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11271 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11272 if (options.model == MODEL_FLAT24)
11274 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11278 /* so dptr know contains the address */
11279 pic16_freeAsmop(left,NULL,ic,TRUE);
11280 pic16_aopOp(result,ic,TRUE);
11282 /* if bit then unpack */
11283 if (IS_BITFIELD(retype))
11284 genUnpackBits(result,left,"dptr",FPOINTER);
11286 size = AOP_SIZE(result);
11290 pic16_emitcode("movx","a,@dptr");
11291 pic16_aopPut(AOP(result),"a",offset++);
11293 pic16_emitcode("inc","dptr");
11297 pic16_freeAsmop(result,NULL,ic,TRUE);
11302 /*-----------------------------------------------------------------*/
11303 /* genCodePointerGet - get value from code space */
11304 /*-----------------------------------------------------------------*/
11305 static void genCodePointerGet (operand *left,
11306 operand *result, iCode *ic)
11309 sym_link *retype = getSpec(operandType(result));
11311 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11313 pic16_aopOp(left,ic,FALSE);
11315 /* if the operand is already in dptr
11316 then we do nothing else we move the value to dptr */
11317 if (AOP_TYPE(left) != AOP_STR) {
11318 /* if this is remateriazable */
11319 if (AOP_TYPE(left) == AOP_IMMD)
11320 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11321 else { /* we need to get it byte by byte */
11322 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11323 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11324 if (options.model == MODEL_FLAT24)
11326 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11330 /* so dptr know contains the address */
11331 pic16_freeAsmop(left,NULL,ic,TRUE);
11332 pic16_aopOp(result,ic,FALSE);
11334 /* if bit then unpack */
11335 if (IS_BITFIELD(retype))
11336 genUnpackBits(result,left,"dptr",CPOINTER);
11338 size = AOP_SIZE(result);
11342 pic16_emitcode("clr","a");
11343 pic16_emitcode("movc","a,@a+dptr");
11344 pic16_aopPut(AOP(result),"a",offset++);
11346 pic16_emitcode("inc","dptr");
11350 pic16_freeAsmop(result,NULL,ic,TRUE);
11355 /*-----------------------------------------------------------------*/
11356 /* genGenPointerGet - gget value from generic pointer space */
11357 /*-----------------------------------------------------------------*/
11358 static void genGenPointerGet (operand *left,
11359 operand *result, iCode *ic)
11361 int size, offset, lit;
11362 sym_link *retype = getSpec(operandType(result));
11364 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11365 pic16_aopOp(left,ic,FALSE);
11366 pic16_aopOp(result,ic,FALSE);
11367 size = AOP_SIZE(result);
11369 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11371 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11373 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11374 // load FSR0 from immediate
11375 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11377 // pic16_loadFSR0( left );
11382 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11384 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11391 else { /* we need to get it byte by byte */
11392 // set up FSR0 with address from left
11393 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11394 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11400 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11402 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11409 /* if bit then unpack */
11410 if (IS_BITFIELD(retype))
11411 genUnpackBits(result,left,"BAD",GPOINTER);
11414 pic16_freeAsmop(left,NULL,ic,TRUE);
11415 pic16_freeAsmop(result,NULL,ic,TRUE);
11421 /*-----------------------------------------------------------------*/
11422 /* genGenPointerGet - gget value from generic pointer space */
11423 /*-----------------------------------------------------------------*/
11424 static void genGenPointerGet (operand *left,
11425 operand *result, iCode *ic)
11427 int size, offset, lit;
11428 sym_link *letype = getSpec(operandType(left));
11430 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11431 pic16_aopOp(left,ic,FALSE);
11432 pic16_aopOp(result,ic,TRUE);
11433 size = AOP_SIZE(result);
11435 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11437 /* if bit then unpack */
11438 if (IS_BITFIELD(letype)) {
11439 genUnpackBits(result,left,"BAD",GPOINTER);
11443 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11445 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11446 // load FSR0 from immediate
11447 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11449 werror(W_POSSBUG2, __FILE__, __LINE__);
11454 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11456 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11463 } else { /* we need to get it byte by byte */
11465 /* set up WREG:PRODL:FSR0L with address from left */
11466 mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11467 mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11468 pic16_mov2w(AOP(left), 2);
11469 pic16_callGenericPointerRW(0, size);
11471 assignResultValue(result, size, 1);
11477 pic16_freeAsmop(left,NULL,ic,TRUE);
11478 pic16_freeAsmop(result,NULL,ic,TRUE);
11481 /*-----------------------------------------------------------------*/
11482 /* genConstPointerGet - get value from const generic pointer space */
11483 /*-----------------------------------------------------------------*/
11484 static void genConstPointerGet (operand *left,
11485 operand *result, iCode *ic)
11487 //sym_link *retype = getSpec(operandType(result));
11488 // symbol *albl = newiTempLabel(NULL); // patch 15
11489 // symbol *blbl = newiTempLabel(NULL); //
11490 // PIC_OPCODE poc; // patch 15
11494 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11495 pic16_aopOp(left,ic,FALSE);
11496 pic16_aopOp(result,ic,TRUE);
11497 size = AOP_SIZE(result);
11499 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11501 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11503 // set up table pointer
11504 if( (AOP_TYPE(left) == AOP_PCODE)
11505 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11506 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11508 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11509 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11510 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11511 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11512 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11513 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11515 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11516 mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11517 mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11521 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11522 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11526 pic16_freeAsmop(left,NULL,ic,TRUE);
11527 pic16_freeAsmop(result,NULL,ic,TRUE);
11531 /*-----------------------------------------------------------------*/
11532 /* genPointerGet - generate code for pointer get */
11533 /*-----------------------------------------------------------------*/
11534 static void genPointerGet (iCode *ic)
11536 operand *left, *result ;
11537 sym_link *type, *etype;
11542 left = IC_LEFT(ic);
11543 result = IC_RESULT(ic) ;
11545 /* depending on the type of pointer we need to
11546 move it to the correct pointer register */
11547 type = operandType(left);
11548 etype = getSpec(type);
11551 if (IS_PTR_CONST(type))
11553 if (IS_CODEPTR(type))
11555 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11557 /* if left is of type of pointer then it is simple */
11558 if (IS_PTR(type) && !IS_FUNC(type->next))
11559 p_type = DCL_TYPE(type);
11561 /* we have to go by the storage class */
11562 p_type = PTR_TYPE(SPEC_OCLS(etype));
11564 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11566 if (SPEC_OCLS(etype)->codesp ) {
11567 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11568 //p_type = CPOINTER ;
11570 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11571 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11572 /*p_type = FPOINTER ;*/
11574 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11575 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11576 /* p_type = PPOINTER; */
11578 if (SPEC_OCLS(etype) == idata ) {
11579 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11580 /* p_type = IPOINTER; */
11582 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11583 /* p_type = POINTER ; */
11587 /* now that we have the pointer type we assign
11588 the pointer values */
11593 genNearPointerGet (left,result,ic);
11597 genPagedPointerGet(left,result,ic);
11601 /* PICs do not support FAR pointers... */
11602 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11604 genFarPointerGet (left,result,ic);
11609 genConstPointerGet (left,result,ic);
11610 //pic16_emitcodePointerGet (left,result,ic);
11615 if (IS_PTR_CONST(type))
11616 genConstPointerGet (left,result,ic);
11619 genGenPointerGet (left,result,ic);
11623 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11624 "genPointerGet: illegal pointer type");
11629 /*-----------------------------------------------------------------*/
11630 /* genPackBits - generates code for packed bit storage */
11631 /*-----------------------------------------------------------------*/
11632 static void genPackBits (sym_link *etype , operand *result,
11634 char *rname, int p_type)
11640 int shifted_and_masked = 0;
11641 unsigned long lit = (unsigned long)-1;
11644 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11645 blen = SPEC_BLEN(etype);
11646 bstr = SPEC_BSTR(etype);
11648 retype = getSpec(operandType(right));
11650 if(AOP_TYPE(right) == AOP_LIT) {
11651 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11653 if((blen == 1) && (bstr < 8)) {
11654 /* it is a single bit, so use the appropriate bit instructions */
11656 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11658 if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11659 /* workaround to reduce the extra lfsr instruction */
11661 pic16_emitpcode(POC_BSF,
11662 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11664 pic16_emitpcode(POC_BCF,
11665 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11668 if (PIC_IS_DATA_PTR(operandType(result))) {
11669 pic16_loadFSR0(result, 0);
11670 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11671 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11673 /* get old value */
11674 pic16_derefPtr (result, p_type, 0, NULL);
11675 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11676 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11677 /* write back new value */
11678 pic16_derefPtr (result, p_type, 1, NULL);
11684 /* IORLW below is more efficient */
11685 //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11686 lit = (lit & ((1UL << blen) - 1)) << bstr;
11687 shifted_and_masked = 1;
11690 if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11691 && IS_BITFIELD(retype)
11692 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11696 rblen = SPEC_BLEN( retype );
11697 rbstr = SPEC_BSTR( retype );
11699 if(IS_BITFIELD(etype)) {
11700 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11701 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11703 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11706 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11708 if(IS_BITFIELD(etype)) {
11709 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11711 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11714 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11718 /* move right to W */
11719 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11722 /* if the bit length is less than or */
11723 /* it exactly fits a byte then */
11724 if((shCnt=SPEC_BSTR(etype))
11725 || SPEC_BLEN(etype) <= 8 ) {
11726 int fsr0_setup = 0;
11728 if (blen != 8 || (bstr % 8) != 0) {
11729 // we need to combine the value with the old value
11730 if(!shifted_and_masked)
11732 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11734 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11735 SPEC_BSTR(etype), SPEC_BLEN(etype));
11737 /* shift left acc, do NOT mask the result again */
11740 /* using PRODH as a temporary register here */
11741 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11744 if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11745 || IS_DIRECT(result)) {
11746 /* access symbol directly */
11747 pic16_mov2w (AOP(result), 0);
11749 /* get old value */
11750 pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11753 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11754 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11755 (unsigned char)(0xff >> (8-bstr))) ));
11756 if (!shifted_and_masked) {
11757 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11759 /* We have the shifted and masked (literal) right value in `lit' */
11761 pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11763 } else { // if (blen == 8 && (bstr % 8) == 0)
11764 if (shifted_and_masked) {
11765 // move right (literal) to WREG (only case where right is not yet in WREG)
11766 pic16_mov2w(AOP(right), (bstr / 8));
11770 /* write new value back */
11771 if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11772 || IS_DIRECT(result)) {
11773 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11775 pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11784 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11785 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11786 exit(EXIT_FAILURE);
11790 pic16_loadFSR0(result, 0); // load FSR0 with address of result
11791 rLen = SPEC_BLEN(etype)-8;
11793 /* now generate for lengths greater than one byte */
11797 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11803 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11809 pic16_emitcode("movx","@dptr,a");
11814 DEBUGpic16_emitcode(";lcall","__gptrput");
11822 pic16_mov2w(AOP(right), offset++);
11825 /* last last was not complete */
11827 /* save the byte & read byte */
11830 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11831 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11836 pic16_emitcode ("mov","b,a");
11837 pic16_emitcode("movx","a,@dptr");
11841 pic16_emitcode ("push","b");
11842 pic16_emitcode ("push","acc");
11843 pic16_emitcode ("lcall","__gptrget");
11844 pic16_emitcode ("pop","b");
11850 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11851 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11852 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11853 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11854 // pic16_emitcode ("orl","a,b");
11857 // if (p_type == GPOINTER)
11858 // pic16_emitcode("pop","b");
11863 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11864 // pic16_emitcode("mov","@%s,a",rname);
11868 pic16_emitcode("movx","@dptr,a");
11872 DEBUGpic16_emitcode(";lcall","__gptrput");
11879 // pic16_freeAsmop(right, NULL, ic, TRUE);
11882 /*-----------------------------------------------------------------*/
11883 /* genDataPointerSet - remat pointer to data space */
11884 /*-----------------------------------------------------------------*/
11885 static void genDataPointerSet(operand *right,
11889 int size, offset = 0, resoffset=0 ;
11891 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11892 pic16_aopOp(right,ic,FALSE);
11894 size = AOP_SIZE(right);
11896 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11899 if ( AOP_TYPE(result) == AOP_PCODE) {
11900 fprintf(stderr,"genDataPointerSet %s, %d\n",
11901 AOP(result)->aopu.pcop->name,
11902 (AOP(result)->aopu.pcop->type == PO_DIR)?
11903 PCOR(AOP(result)->aopu.pcop)->instance:
11904 PCOI(AOP(result)->aopu.pcop)->offset);
11908 if(AOP(result)->aopu.pcop->type == PO_DIR)
11909 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11912 if (AOP_TYPE(right) == AOP_LIT) {
11913 unsigned int lit = pic16aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
11914 pic16_movLit2f(pic16_popGet(AOP(result), offset), lit);
11916 pic16_mov2w(AOP(right), offset);
11917 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); // patch 8
11923 pic16_freeAsmop(right,NULL,ic,TRUE);
11928 /*-----------------------------------------------------------------*/
11929 /* genNearPointerSet - pic16_emitcode for near pointer put */
11930 /*-----------------------------------------------------------------*/
11931 static void genNearPointerSet (operand *right,
11937 sym_link *ptype = operandType(result);
11938 sym_link *resetype;
11940 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11941 retype= getSpec(operandType(right));
11942 resetype = getSpec(operandType(result));
11944 pic16_aopOp(result,ic,FALSE);
11946 /* if the result is rematerializable &
11947 * in data space & not a bit variable */
11949 /* and result is not a bit variable */
11950 if (AOP_TYPE(result) == AOP_PCODE
11951 // && AOP_TYPE(result) == AOP_IMMD
11952 && DCL_TYPE(ptype) == POINTER
11953 && !IS_BITFIELD(retype)
11954 && !IS_BITFIELD(resetype)) {
11956 genDataPointerSet (right,result,ic);
11957 pic16_freeAsmop(result,NULL,ic,TRUE);
11961 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11962 pic16_aopOp(right,ic,FALSE);
11963 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11965 /* if bitfield then unpack the bits */
11966 if (IS_BITFIELD(resetype)) {
11967 genPackBits (resetype, result, right, NULL, POINTER);
11969 /* we have can just get the values */
11970 int size = AOP_SIZE(right);
11973 pic16_loadFSR0(result, 0);
11975 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11977 if (AOP_TYPE(right) == AOP_LIT) {
11978 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11980 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11982 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11984 } else { // no literal
11986 pic16_emitpcode(POC_MOVFF,
11987 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11988 pic16_popCopyReg(&pic16_pc_postinc0)));
11990 pic16_emitpcode(POC_MOVFF,
11991 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11992 pic16_popCopyReg(&pic16_pc_indf0)));
12000 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12001 /* now some housekeeping stuff */
12003 /* we had to allocate for this iCode */
12004 pic16_freeAsmop(NULL,aop,ic,TRUE);
12006 /* we did not allocate which means left
12007 * already in a pointer register, then
12008 * if size > 0 && this could be used again
12009 * we have to point it back to where it
12011 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12012 if (AOP_SIZE(right) > 1
12013 && !OP_SYMBOL(result)->remat
12014 && ( OP_SYMBOL(result)->liveTo > ic->seq
12017 int size = AOP_SIZE(right) - 1;
12020 pic16_emitcode("decf","fsr0,f");
12021 //pic16_emitcode("dec","%s",rname);
12025 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12028 pic16_freeAsmop(right,NULL,ic,TRUE);
12029 pic16_freeAsmop(result,NULL,ic,TRUE);
12032 /*-----------------------------------------------------------------*/
12033 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
12034 /*-----------------------------------------------------------------*/
12035 static void genPagedPointerSet (operand *right,
12040 regs *preg = NULL ;
12044 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12046 retype= getSpec(operandType(right));
12048 pic16_aopOp(result,ic,FALSE);
12050 /* if the value is already in a pointer register
12051 then don't need anything more */
12052 if (!AOP_INPREG(AOP(result))) {
12053 /* otherwise get a free pointer register */
12055 preg = getFreePtr(ic,&aop,FALSE);
12056 pic16_emitcode("mov","%s,%s",
12058 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12059 rname = preg->name ;
12061 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12063 pic16_freeAsmop(result,NULL,ic,TRUE);
12064 pic16_aopOp (right,ic,FALSE);
12066 /* if bitfield then unpack the bits */
12067 if (IS_BITFIELD(retype))
12068 genPackBits (retype,result,right,rname,PPOINTER);
12070 /* we have can just get the values */
12071 int size = AOP_SIZE(right);
12075 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12078 pic16_emitcode("movx","@%s,a",rname);
12081 pic16_emitcode("inc","%s",rname);
12087 /* now some housekeeping stuff */
12089 /* we had to allocate for this iCode */
12090 pic16_freeAsmop(NULL,aop,ic,TRUE);
12092 /* we did not allocate which means left
12093 already in a pointer register, then
12094 if size > 0 && this could be used again
12095 we have to point it back to where it
12097 if (AOP_SIZE(right) > 1 &&
12098 !OP_SYMBOL(result)->remat &&
12099 ( OP_SYMBOL(result)->liveTo > ic->seq ||
12101 int size = AOP_SIZE(right) - 1;
12103 pic16_emitcode("dec","%s",rname);
12108 pic16_freeAsmop(right,NULL,ic,TRUE);
12114 /* This code is not adjusted to PIC16 and fails utterly...
12115 * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
12117 /*-----------------------------------------------------------------*/
12118 /* genFarPointerSet - set value from far space */
12119 /*-----------------------------------------------------------------*/
12120 static void genFarPointerSet (operand *right,
12121 operand *result, iCode *ic)
12124 sym_link *retype = getSpec(operandType(right));
12126 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12127 pic16_aopOp(result,ic,FALSE);
12129 /* if the operand is already in dptr
12130 then we do nothing else we move the value to dptr */
12131 if (AOP_TYPE(result) != AOP_STR) {
12132 /* if this is remateriazable */
12133 if (AOP_TYPE(result) == AOP_IMMD)
12134 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12135 else { /* we need to get it byte by byte */
12136 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12137 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12138 if (options.model == MODEL_FLAT24)
12140 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12144 /* so dptr know contains the address */
12145 pic16_freeAsmop(result,NULL,ic,TRUE);
12146 pic16_aopOp(right,ic,FALSE);
12148 /* if bit then unpack */
12149 if (IS_BITFIELD(retype))
12150 genPackBits(retype,result,right,"dptr",FPOINTER);
12152 size = AOP_SIZE(right);
12156 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12158 pic16_emitcode("movx","@dptr,a");
12160 pic16_emitcode("inc","dptr");
12164 pic16_freeAsmop(right,NULL,ic,TRUE);
12168 /*-----------------------------------------------------------------*/
12169 /* genGenPointerSet - set value from generic pointer space */
12170 /*-----------------------------------------------------------------*/
12172 static void genGenPointerSet (operand *right,
12173 operand *result, iCode *ic)
12175 int i, size, offset, lit;
12176 sym_link *retype = getSpec(operandType(right));
12178 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12180 pic16_aopOp(result,ic,FALSE);
12181 pic16_aopOp(right,ic,FALSE);
12182 size = AOP_SIZE(right);
12185 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12187 /* if the operand is already in dptr
12188 then we do nothing else we move the value to dptr */
12189 if (AOP_TYPE(result) != AOP_STR) {
12190 /* if this is remateriazable */
12191 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12192 // WARNING: anythig until "else" is untested!
12193 if (AOP_TYPE(result) == AOP_IMMD) {
12194 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12195 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12196 // load FSR0 from immediate
12197 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12201 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12203 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12209 else { /* we need to get it byte by byte */
12210 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12211 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12213 // set up FSR0 with address of result
12214 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12215 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12217 /* hack hack! see if this the FSR. If so don't load W */
12218 if(AOP_TYPE(right) != AOP_ACC) {
12220 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12222 if(AOP_TYPE(right) == AOP_LIT)
12225 // note: pic16_popGet handles sign extension
12226 for(i=0;i<size;i++) {
12227 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12229 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12231 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12236 for(i=0;i<size;i++) {
12238 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12239 pic16_popCopyReg(&pic16_pc_postinc0)));
12241 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12242 pic16_popCopyReg(&pic16_pc_indf0)));
12248 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12249 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12251 } // if (AOP_TYPE(result) != AOP_IMMD)
12253 } // if (AOP_TYPE(result) != AOP_STR)
12254 /* so dptr know contains the address */
12257 /* if bit then unpack */
12258 if (IS_BITFIELD(retype))
12259 genPackBits(retype,result,right,"dptr",GPOINTER);
12261 size = AOP_SIZE(right);
12264 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12266 // set up FSR0 with address of result
12267 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12268 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12271 if (AOP_TYPE(right) == AOP_LIT) {
12272 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12274 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12276 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12278 } else { // no literal
12280 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12282 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12290 pic16_freeAsmop(right,NULL,ic,TRUE);
12291 pic16_freeAsmop(result,NULL,ic,TRUE);
12295 static void genGenPointerSet (operand *right,
12296 operand *result, iCode *ic)
12299 sym_link *retype = getSpec(operandType(result));
12301 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12303 pic16_aopOp(result,ic,FALSE);
12304 pic16_aopOp(right,ic,FALSE);
12305 size = AOP_SIZE(right);
12307 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12310 /* if bit then unpack */
12311 if (IS_BITFIELD(retype)) {
12312 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12313 genPackBits(retype,result,right,"dptr",GPOINTER);
12317 size = AOP_SIZE(right);
12319 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12322 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12324 /* value of right+0 is placed on stack, which will be retrieved
12325 * by the support function thus restoring the stack. The important
12326 * thing is that there is no need to manually restore stack pointer
12328 pushaop(AOP(right), 0);
12329 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12330 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12331 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12332 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12334 /* load address to write to in WREG:FSR0H:FSR0L */
12335 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12336 pic16_popCopyReg(&pic16_pc_fsr0l)));
12337 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12338 pic16_popCopyReg(&pic16_pc_prodl)));
12339 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12341 pic16_callGenericPointerRW(1, size);
12344 pic16_freeAsmop(right,NULL,ic,TRUE);
12345 pic16_freeAsmop(result,NULL,ic,TRUE);
12348 /*-----------------------------------------------------------------*/
12349 /* genPointerSet - stores the value into a pointer location */
12350 /*-----------------------------------------------------------------*/
12351 static void genPointerSet (iCode *ic)
12353 operand *right, *result ;
12354 sym_link *type, *etype;
12359 right = IC_RIGHT(ic);
12360 result = IC_RESULT(ic) ;
12362 /* depending on the type of pointer we need to
12363 move it to the correct pointer register */
12364 type = operandType(result);
12365 etype = getSpec(type);
12367 /* if left is of type of pointer then it is simple */
12368 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12369 p_type = DCL_TYPE(type);
12372 /* we have to go by the storage class */
12373 p_type = PTR_TYPE(SPEC_OCLS(etype));
12375 /* if (SPEC_OCLS(etype)->codesp ) { */
12376 /* p_type = CPOINTER ; */
12379 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12380 /* p_type = FPOINTER ; */
12382 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12383 /* p_type = PPOINTER ; */
12385 /* if (SPEC_OCLS(etype) == idata ) */
12386 /* p_type = IPOINTER ; */
12388 /* p_type = POINTER ; */
12391 /* now that we have the pointer type we assign
12392 the pointer values */
12397 genNearPointerSet (right,result,ic);
12401 genPagedPointerSet (right,result,ic);
12405 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12407 genFarPointerSet (right,result,ic);
12412 genGenPointerSet (right,result,ic);
12416 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12417 "genPointerSet: illegal pointer type");
12421 /*-----------------------------------------------------------------*/
12422 /* genIfx - generate code for Ifx statement */
12423 /*-----------------------------------------------------------------*/
12424 static void genIfx (iCode *ic, iCode *popIc)
12426 operand *cond = IC_COND(ic);
12431 pic16_aopOp(cond,ic,FALSE);
12433 /* get the value into acc */
12434 if (AOP_TYPE(cond) != AOP_CRY)
12435 pic16_toBoolean(cond);
12438 /* the result is now in the accumulator */
12439 pic16_freeAsmop(cond,NULL,ic,TRUE);
12441 /* if there was something to be popped then do it */
12445 /* if the condition is a bit variable */
12446 if (isbit && IS_ITEMP(cond) &&
12448 genIfxJump(ic,"c");
12449 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12451 if (isbit && !IS_ITEMP(cond))
12452 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12454 genIfxJump(ic,"a");
12459 /*-----------------------------------------------------------------*/
12460 /* genAddrOf - generates code for address of */
12461 /*-----------------------------------------------------------------*/
12462 static void genAddrOf (iCode *ic)
12464 operand *result, *left;
12466 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12467 pCodeOp *pcop0, *pcop1, *pcop2;
12471 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12473 sym = OP_SYMBOL( IC_LEFT(ic) );
12476 /* get address of symbol on stack */
12477 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12479 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12480 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12483 // operands on stack are accessible via "FSR2 + index" with index
12484 // starting at 2 for arguments and growing from 0 downwards for
12485 // local variables (index == 0 is not assigned so we add one here)
12487 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12490 assert (soffs < 0);
12494 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12495 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12496 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12497 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12498 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12499 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12500 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12506 // if(pic16_debug_verbose) {
12507 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12508 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12511 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12512 size = AOP_SIZE(IC_RESULT(ic));
12514 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12515 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12516 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12519 pic16_emitpcode(POC_MOVLW, pcop0);
12520 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12521 pic16_emitpcode(POC_MOVLW, pcop1);
12522 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12523 pic16_emitpcode(POC_MOVLW, pcop2);
12524 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12527 pic16_emitpcode(POC_MOVLW, pcop0);
12528 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12529 pic16_emitpcode(POC_MOVLW, pcop1);
12530 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12532 pic16_emitpcode(POC_MOVLW, pcop0);
12533 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12536 pic16_freeAsmop(left, NULL, ic, FALSE);
12538 pic16_freeAsmop(result,NULL,ic,TRUE);
12543 /*-----------------------------------------------------------------*/
12544 /* genFarFarAssign - assignment when both are in far space */
12545 /*-----------------------------------------------------------------*/
12546 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12548 int size = AOP_SIZE(right);
12551 /* first push the right side on to the stack */
12553 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12555 pic16_emitcode ("push","acc");
12558 pic16_freeAsmop(right,NULL,ic,FALSE);
12559 /* now assign DPTR to result */
12560 pic16_aopOp(result,ic,FALSE);
12561 size = AOP_SIZE(result);
12563 pic16_emitcode ("pop","acc");
12564 pic16_aopPut(AOP(result),"a",--offset);
12566 pic16_freeAsmop(result,NULL,ic,FALSE);
12571 /*-----------------------------------------------------------------*/
12572 /* genAssign - generate code for assignment */
12573 /*-----------------------------------------------------------------*/
12574 static void genAssign (iCode *ic)
12576 operand *result, *right;
12577 sym_link *restype, *rtype;
12578 int size, offset,know_W;
12579 unsigned long lit = 0L;
12581 result = IC_RESULT(ic);
12582 right = IC_RIGHT(ic) ;
12586 /* if they are the same */
12587 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12590 /* reversed order operands are aopOp'ed so that result operand
12591 * is effective in case right is a stack symbol. This maneauver
12592 * allows to use the _G.resDirect flag later */
12593 pic16_aopOp(result,ic,TRUE);
12594 pic16_aopOp(right,ic,FALSE);
12596 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12598 /* if they are the same registers */
12599 if (pic16_sameRegs(AOP(right),AOP(result)))
12602 /* if the result is a bit */
12603 if (AOP_TYPE(result) == AOP_CRY) {
12604 /* if the right size is a literal then
12605 we know what the value is */
12606 if (AOP_TYPE(right) == AOP_LIT) {
12608 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12609 pic16_popGet(AOP(result),0));
12611 if (((int) operandLitValue(right)))
12612 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12613 AOP(result)->aopu.aop_dir,
12614 AOP(result)->aopu.aop_dir);
12616 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12617 AOP(result)->aopu.aop_dir,
12618 AOP(result)->aopu.aop_dir);
12623 /* the right is also a bit variable */
12624 if (AOP_TYPE(right) == AOP_CRY) {
12625 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12626 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12627 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12632 /* we need to or */
12633 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12634 pic16_toBoolean(right);
12636 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12637 //pic16_aopPut(AOP(result),"a",0);
12641 /* bit variables done */
12643 size = AOP_SIZE(result);
12646 /* bit variables done */
12648 size = AOP_SIZE(result);
12649 restype = operandType(result);
12650 rtype = operandType(right);
12653 if(AOP_TYPE(right) == AOP_LIT) {
12654 if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12656 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12658 /* patch tag for literals that are cast to pointers */
12659 if (IS_CODEPTR(restype)) {
12660 //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12661 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12663 if (IS_GENPTR(restype))
12665 if (IS_CODEPTR(rtype)) {
12666 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12667 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12668 } else if (PIC_IS_DATA_PTR(rtype)) {
12669 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12670 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12671 } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12672 //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12673 } else if (IS_PTR(rtype)) {
12674 fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12675 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12681 unsigned long lit_int;
12686 if(IS_FIXED16X16(operandType(right))) {
12687 lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12689 /* take care if literal is a float */
12690 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12691 lit = info.lit_int;
12696 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12697 // sizeof(unsigned long int), sizeof(float));
12700 if (AOP_TYPE(right) == AOP_REG) {
12701 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12703 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12708 /* when do we have to read the program memory?
12709 * - if right itself is a symbol in code space
12710 * (we don't care what it points to if it's a pointer)
12711 * - AND right is not a function (we would want its address)
12713 if(AOP_TYPE(right) != AOP_LIT
12714 && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12715 && !IS_FUNC(OP_SYM_TYPE(right))
12716 && !IS_ITEMP(right)) {
12718 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12719 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12721 // set up table pointer
12722 if(is_LitOp(right)) {
12723 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12724 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12725 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12726 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12727 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12728 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12729 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12731 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12732 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12733 pic16_popCopyReg(&pic16_pc_tblptrl)));
12734 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12735 pic16_popCopyReg(&pic16_pc_tblptrh)));
12736 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12737 pic16_popCopyReg(&pic16_pc_tblptru)));
12740 /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12741 size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12743 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12744 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12745 pic16_popGet(AOP(result),offset)));
12749 /* FIXME: for pointers we need to extend differently (according
12750 * to pointer type DATA/CODE/EEPROM/... :*/
12751 size = getSize(OP_SYM_TYPE(right));
12752 if(AOP_SIZE(result) > size) {
12753 size = AOP_SIZE(result) - size;
12755 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12763 /* VR - What is this?! */
12764 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12765 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12767 if(aopIdx(AOP(result),0) == 4) {
12768 /* this is a workaround to save value of right into wreg too,
12769 * value of wreg is going to be used later */
12770 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12771 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12772 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12776 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12780 size = AOP_SIZE(right);
12781 if (size > AOP_SIZE(result)) size = AOP_SIZE(result);
12784 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12785 if(AOP_TYPE(right) == AOP_LIT) {
12787 if(know_W != (lit&0xff))
12788 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12790 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12792 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12796 } else if (AOP_TYPE(right) == AOP_CRY) {
12797 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12799 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12800 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12801 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12803 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12804 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12805 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12807 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12809 if(!_G.resDirect) { /* use this aopForSym feature */
12810 if(AOP_TYPE(result) == AOP_ACC) {
12811 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
12813 if(AOP_TYPE(right) == AOP_ACC) {
12814 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
12816 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12823 pic16_addSign(result, AOP_SIZE(right), !IS_UNSIGNED(operandType(right)));
12826 pic16_freeAsmop (right,NULL,ic,FALSE);
12827 pic16_freeAsmop (result,NULL,ic,TRUE);
12830 /*-----------------------------------------------------------------*/
12831 /* genJumpTab - generates code for jump table */
12832 /*-----------------------------------------------------------------*/
12833 static void genJumpTab (iCode *ic)
12838 pCodeOp *jt_offs_hi;
12843 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12844 /* get the condition into accumulator */
12845 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12847 /* multiply by three */
12848 pic16_emitcode("add","a,acc");
12849 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12851 jtab = newiTempLabel(NULL);
12852 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12853 pic16_emitcode("jmp","@a+dptr");
12854 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12857 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12858 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12860 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12861 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12862 pic16_emitpLabel(jtab->key);
12866 jt_offs = pic16_popGetTempReg(0);
12867 jt_offs_hi = pic16_popGetTempReg(1);
12868 jt_label = pic16_popGetLabel (jtab->key);
12869 //fprintf (stderr, "Creating jump table...\n");
12871 // calculate offset into jump table (idx * sizeof (GOTO))
12872 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12873 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12874 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12875 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12876 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12877 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12878 pic16_emitpcode(POC_MOVWF , jt_offs);
12880 // prepare PCLATx (set to first entry in jump table)
12881 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12882 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12883 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12884 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12885 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12887 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12888 pic16_emitpcode(POC_ADDWF , jt_offs);
12889 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12890 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12892 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12894 // release temporaries and prepare jump into table (new PCL --> WREG)
12895 pic16_emitpcode(POC_MOVFW , jt_offs);
12896 pic16_popReleaseTempReg (jt_offs_hi, 1);
12897 pic16_popReleaseTempReg (jt_offs, 0);
12899 // jump into the table
12900 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12902 pic16_emitpLabelFORCE(jtab->key);
12905 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12906 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12908 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12909 /* now generate the jump labels */
12910 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12911 jtab = setNextItem(IC_JTLABELS(ic))) {
12912 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12913 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12916 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12920 /*-----------------------------------------------------------------*/
12921 /* genMixedOperation - gen code for operators between mixed types */
12922 /*-----------------------------------------------------------------*/
12924 TSD - Written for the PIC port - but this unfortunately is buggy.
12925 This routine is good in that it is able to efficiently promote
12926 types to different (larger) sizes. Unfortunately, the temporary
12927 variables that are optimized out by this routine are sometimes
12928 used in other places. So until I know how to really parse the
12929 iCode tree, I'm going to not be using this routine :(.
12931 static int genMixedOperation (iCode *ic)
12934 operand *result = IC_RESULT(ic);
12935 sym_link *ctype = operandType(IC_LEFT(ic));
12936 operand *right = IC_RIGHT(ic);
12942 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12944 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12950 nextright = IC_RIGHT(nextic);
12951 nextleft = IC_LEFT(nextic);
12952 nextresult = IC_RESULT(nextic);
12954 pic16_aopOp(right,ic,FALSE);
12955 pic16_aopOp(result,ic,FALSE);
12956 pic16_aopOp(nextright, nextic, FALSE);
12957 pic16_aopOp(nextleft, nextic, FALSE);
12958 pic16_aopOp(nextresult, nextic, FALSE);
12960 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12962 operand *t = right;
12966 pic16_emitcode(";remove right +","");
12968 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12970 operand *t = right;
12974 pic16_emitcode(";remove left +","");
12978 big = AOP_SIZE(nextleft);
12979 small = AOP_SIZE(nextright);
12981 switch(nextic->op) {
12984 pic16_emitcode(";optimize a +","");
12985 /* if unsigned or not an integral type */
12986 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12987 pic16_emitcode(";add a bit to something","");
12990 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12992 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12993 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12994 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12996 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
13004 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13005 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13006 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13009 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13011 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13012 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
13013 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
13014 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13015 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
13018 pic16_emitcode("rlf","known_zero,w");
13025 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13026 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13027 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13029 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13039 pic16_freeAsmop(right,NULL,ic,TRUE);
13040 pic16_freeAsmop(result,NULL,ic,TRUE);
13041 pic16_freeAsmop(nextright,NULL,ic,TRUE);
13042 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
13044 nextic->generated = 1;
13051 /*-----------------------------------------------------------------*/
13052 /* genCast - gen code for casting */
13053 /*-----------------------------------------------------------------*/
13054 static void genCast (iCode *ic)
13056 operand *result = IC_RESULT(ic);
13057 sym_link *ctype = operandType(IC_LEFT(ic));
13058 sym_link *rtype = operandType(IC_RIGHT(ic));
13059 sym_link *restype = operandType(IC_RESULT(ic));
13060 operand *right = IC_RIGHT(ic);
13066 /* if they are equivalent then do nothing */
13067 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13070 pic16_aopOp(result,ic,FALSE);
13071 pic16_aopOp(right,ic,FALSE) ;
13073 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13076 /* if the result is a bit */
13077 if (AOP_TYPE(result) == AOP_CRY) {
13079 /* if the right size is a literal then
13080 * we know what the value is */
13081 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13083 if (AOP_TYPE(right) == AOP_LIT) {
13084 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13085 pic16_popGet(AOP(result),0));
13087 if (((int) operandLitValue(right)))
13088 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13089 AOP(result)->aopu.aop_dir,
13090 AOP(result)->aopu.aop_dir);
13092 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13093 AOP(result)->aopu.aop_dir,
13094 AOP(result)->aopu.aop_dir);
13098 /* the right is also a bit variable */
13099 if (AOP_TYPE(right) == AOP_CRY) {
13101 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13103 pic16_emitcode("clrc","");
13104 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13105 AOP(right)->aopu.aop_dir,
13106 AOP(right)->aopu.aop_dir);
13107 pic16_aopPut(AOP(result),"c",0);
13111 /* we need to or */
13112 if (AOP_TYPE(right) == AOP_REG) {
13113 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
13114 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13115 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
13117 pic16_toBoolean(right);
13118 pic16_aopPut(AOP(result),"a",0);
13122 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13125 size = AOP_SIZE(result);
13127 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13129 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
13130 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13131 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
13134 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13139 if(IS_BITFIELD(getSpec(restype))
13140 && IS_BITFIELD(getSpec(rtype))) {
13141 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13144 /* port from pic14 to cope with generic pointers */
13145 if (PIC_IS_TAGGED(restype))
13147 operand *result = IC_RESULT(ic);
13148 //operand *left = IC_LEFT(ic);
13149 operand *right = IC_RIGHT(ic);
13152 /* copy common part */
13153 int max, size = AOP_SIZE(result);
13154 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
13155 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13160 pic16_mov2w (AOP(right), size);
13161 pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
13164 /* upcast into generic pointer type? */
13165 if (IS_GENPTR(restype)
13166 && !PIC_IS_TAGGED(rtype)
13167 && (AOP_SIZE(result) > max))
13169 /* determine appropriate tag for right */
13170 if (PIC_IS_DATA_PTR(rtype))
13171 tag = GPTR_TAG_DATA;
13172 else if (IS_CODEPTR(rtype))
13173 tag = GPTR_TAG_CODE;
13174 else if (PIC_IS_DATA_PTR(ctype)) {
13175 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
13176 tag = GPTR_TAG_DATA;
13177 } else if (IS_CODEPTR(ctype)) {
13178 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
13179 tag = GPTR_TAG_CODE;
13180 } else if (IS_PTR(rtype)) {
13181 PERFORM_ONCE(weirdcast,
13182 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno);
13184 tag = GPTR_TAG_DATA;
13186 PERFORM_ONCE(weirdcast,
13187 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno);
13189 tag = GPTR_TAG_DATA;
13192 assert (AOP_SIZE(result) == 3);
13193 /* zero-extend address... */
13194 for (size = max; size < AOP_SIZE(result)-1; size++)
13195 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
13196 /* ...and add tag */
13197 pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
13198 } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
13199 //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
13200 for (size = max; size < AOP_SIZE(result)-1; size++)
13201 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
13202 /* add __code tag */
13203 pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
13204 } else if (AOP_SIZE(result) > max) {
13205 /* extend non-pointers */
13206 //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
13207 pic16_addSign(result, max, 0);
13212 /* if they are the same size : or less */
13213 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13215 /* if they are in the same place */
13216 if (pic16_sameRegs(AOP(right),AOP(result)))
13219 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13221 if (IS_PTR_CONST(rtype))
13223 if (IS_CODEPTR(rtype))
13225 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13228 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13230 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13232 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13235 if(AOP_TYPE(right) == AOP_IMMD) {
13236 pCodeOp *pcop0, *pcop1, *pcop2;
13237 symbol *sym = OP_SYMBOL( right );
13239 size = AOP_SIZE(result);
13241 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13243 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13245 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13248 pic16_emitpcode(POC_MOVLW, pcop0);
13249 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13250 pic16_emitpcode(POC_MOVLW, pcop1);
13251 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13252 pic16_emitpcode(POC_MOVLW, pcop2);
13253 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13256 pic16_emitpcode(POC_MOVLW, pcop0);
13257 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13258 pic16_emitpcode(POC_MOVLW, pcop1);
13259 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13261 pic16_emitpcode(POC_MOVLW, pcop0);
13262 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13266 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13267 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13268 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13270 if(AOP_SIZE(result) < 2) {
13271 fprintf(stderr,"%d -- casting a ptr to a char\n",__LINE__);
13273 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13274 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13277 /* if they in different places then copy */
13278 size = AOP_SIZE(result);
13281 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13282 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13289 /* if the result is of type pointer */
13290 if (IS_PTR(ctype)) {
13292 sym_link *type = operandType(right);
13293 sym_link *etype = getSpec(type);
13295 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
13297 /* pointer to generic pointer */
13298 if (IS_GENPTR(ctype)) {
13302 p_type = DCL_TYPE(type);
13304 /* we have to go by the storage class */
13305 p_type = PTR_TYPE(SPEC_OCLS(etype));
13307 /* if (SPEC_OCLS(etype)->codesp ) */
13308 /* p_type = CPOINTER ; */
13310 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13311 /* p_type = FPOINTER ; */
13313 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13314 /* p_type = PPOINTER; */
13316 /* if (SPEC_OCLS(etype) == idata ) */
13317 /* p_type = IPOINTER ; */
13319 /* p_type = POINTER ; */
13322 /* the first two bytes are known */
13323 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
13324 size = GPTRSIZE - 1;
13327 if(offset < AOP_SIZE(right)) {
13328 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13329 pic16_mov2f(AOP(result), AOP(right), offset);
13331 if ((AOP_TYPE(right) == AOP_PCODE) &&
13332 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13333 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13334 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13337 pic16_aopPut(AOP(result),
13338 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13343 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13346 /* the last byte depending on type */
13351 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13355 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13359 pic16_emitcode(";BUG!? ","%d",__LINE__);
13364 if (GPTRSIZE > AOP_SIZE(right)) {
13365 // assume __data pointer... THIS MIGHT BE WRONG!
13366 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13368 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13373 /* this should never happen */
13374 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13375 "got unknown pointer type");
13378 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13384 /* just copy the pointers */
13385 size = AOP_SIZE(result);
13388 pic16_aopPut(AOP(result),
13389 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13398 /* so we now know that the size of destination is greater
13399 than the size of the source.
13400 Now, if the next iCode is an operator then we might be
13401 able to optimize the operation without performing a cast.
13403 if(genMixedOperation(ic))
13406 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13408 /* we move to result for the size of source */
13409 size = AOP_SIZE(right);
13414 pic16_mov2f(AOP(result), AOP(right), offset);
13418 /* now depending on the sign of the destination */
13419 size = AOP_SIZE(result) - AOP_SIZE(right);
13420 /* if unsigned or not an integral type */
13421 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13423 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13425 /* we need to extend the sign :( */
13428 /* Save one instruction of casting char to int */
13429 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13430 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13431 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
13433 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13436 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13438 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13440 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13443 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13448 pic16_freeAsmop(right,NULL,ic,TRUE);
13449 pic16_freeAsmop(result,NULL,ic,TRUE);
13453 /*-----------------------------------------------------------------*/
13454 /* genDjnz - generate decrement & jump if not zero instrucion */
13455 /*-----------------------------------------------------------------*/
13456 static int genDjnz (iCode *ic, iCode *ifx)
13458 symbol *lbl, *lbl1;
13459 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13464 /* if the if condition has a false label
13465 then we cannot save */
13469 /* if the minus is not of the form
13471 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13472 !IS_OP_LITERAL(IC_RIGHT(ic)))
13475 if (operandLitValue(IC_RIGHT(ic)) != 1)
13478 /* if the size of this greater than one then no
13480 if (getSize(operandType(IC_RESULT(ic))) > 1)
13483 /* otherwise we can save BIG */
13484 lbl = newiTempLabel(NULL);
13485 lbl1= newiTempLabel(NULL);
13487 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13489 if (IS_AOP_PREG(IC_RESULT(ic))) {
13490 pic16_emitcode("dec","%s",
13491 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13492 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13493 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13497 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13498 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13500 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13501 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13505 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13506 ifx->generated = 1;
13510 /*-----------------------------------------------------------------*/
13511 /* genReceive - generate code for a receive iCode */
13512 /*-----------------------------------------------------------------*/
13513 static void genReceive (iCode *ic)
13519 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13520 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13522 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13524 if (isOperandInFarSpace(IC_RESULT(ic))
13525 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13526 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13528 int size = getSize(operandType(IC_RESULT(ic)));
13529 int offset = pic16_fReturnSizePic - size;
13533 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13534 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13538 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13540 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13541 size = AOP_SIZE(IC_RESULT(ic));
13544 pic16_emitcode ("pop","acc");
13545 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13548 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13550 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13553 /* set pseudo stack pointer to where it should be - dw*/
13554 GpsuedoStkPtr = ic->parmBytes;
13556 /* setting GpsuedoStkPtr has side effects here: */
13557 /* FIXME: What's the correct size of the return(ed) value?
13558 * For now, assuming '4' as before... */
13559 assignResultValue(IC_RESULT(ic), 4, 0);
13562 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13565 /*-----------------------------------------------------------------*/
13566 /* genDummyRead - generate code for dummy read of volatiles */
13567 /*-----------------------------------------------------------------*/
13569 genDummyRead (iCode * ic)
13575 if (op && IS_SYMOP(op)) {
13576 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13577 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13580 pic16_aopOp (op, ic, FALSE);
13581 for (i=0; i < AOP_SIZE(op); i++) {
13582 // may need to protect this from the peepholer -- this is not nice but works...
13583 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13584 pic16_mov2w (AOP(op),i);
13585 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13587 pic16_freeAsmop (op, NULL, ic, TRUE);
13589 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13593 /*-----------------------------------------------------------------*/
13594 /* genpic16Code - generate code for pic16 based controllers */
13595 /*-----------------------------------------------------------------*/
13597 * At this point, ralloc.c has gone through the iCode and attempted
13598 * to optimize in a way suitable for a PIC. Now we've got to generate
13599 * PIC instructions that correspond to the iCode.
13601 * Once the instructions are generated, we'll pass through both the
13602 * peep hole optimizer and the pCode optimizer.
13603 *-----------------------------------------------------------------*/
13605 void genpic16Code (iCode *lic)
13610 lineHead = lineCurr = NULL;
13612 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13613 pic16_addpBlock(pb);
13616 /* if debug information required */
13617 if (options.debug && currFunc) {
13619 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13624 for (ic = lic ; ic ; ic = ic->next ) {
13626 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13627 if ( cln != ic->lineno ) {
13628 if ( options.debug ) {
13629 debugFile->writeCLine (ic);
13632 if(!options.noCcodeInAsm) {
13633 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13634 printCLine(ic->filename, ic->lineno)));
13640 if(options.iCodeInAsm) {
13643 /* insert here code to print iCode as comment */
13644 l = Safe_strdup(printILine(ic));
13645 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13648 /* if the result is marked as
13649 * spilt and rematerializable or code for
13650 * this has already been generated then
13652 if (resultRemat(ic) || ic->generated )
13655 /* depending on the operation */
13674 /* IPOP happens only when trying to restore a
13675 * spilt live range, if there is an ifx statement
13676 * following this pop then the if statement might
13677 * be using some of the registers being popped which
13678 * would destroy the contents of the register so
13679 * we need to check for this condition and handle it */
13681 && ic->next->op == IFX
13682 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13683 genIfx (ic->next,ic);
13701 genEndFunction (ic);
13717 pic16_genPlus (ic) ;
13721 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13722 pic16_genMinus (ic);
13738 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13742 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13748 /* note these two are xlated by algebraic equivalence
13749 * during parsing SDCC.y */
13750 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13751 "got '>=' or '<=' shouldn't have come here");
13755 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13767 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13771 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13775 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13799 genRightShift (ic);
13802 case GET_VALUE_AT_ADDRESS:
13807 if (POINTER_SET(ic))
13834 addSet(&_G.sendSet,ic);
13837 case DUMMY_READ_VOLATILE:
13847 /* now we are ready to call the
13848 peep hole optimizer */
13849 if (!options.nopeep)
13850 peepHole (&lineHead);
13852 /* now do the actual printing */
13853 printLine (lineHead, codeOutFile);
13856 DFPRINTF((stderr,"printing pBlock\n\n"));
13857 pic16_printpBlock(stdout,pb);