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@otenet.gr (2003,2004,2005)
11 This program is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2, or (at your option) any
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 In other words, you are welcome to use, share and improve this program.
26 You are forbidden to forbid anyone else to use, share and improve
27 what you give them. Help stamp out software-hoarding!
30 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
31 Made everything static
32 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
42 #include "SDCCpeeph.h"
50 /* Set the following to 1 to enable the slower/bigger
51 * but more robust generic shifting routine (which also
52 * operates correctly with negative shift values). */
53 #define USE_GENERIC_SIGNED_SHIFT 1
55 /* Set the following to 1 to enable the new
56 * stripped down genCmp version.
57 * This version should be easier to understand,
58 * more reliable and (sigh) slighly slower. */
59 #define USE_SIMPLE_GENCMP 1
61 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
62 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
63 void pic16_genMult8X8_8 (operand *, operand *,operand *);
64 void pic16_genMult16X16_16(operand *, operand *, operand *);
65 void pic16_genMult32X32_32(operand *, operand *, operand *);
66 pCode *pic16_AssembleLine(char *line, int peeps);
67 extern void pic16_printpBlock(FILE *of, pBlock *pb);
68 static asmop *newAsmop (short type);
69 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
70 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
71 static void mov2f(asmop *dst, asmop *src, int offset);
72 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
73 static pCodeOp *pic16_popRegFromIdx(int rIdx);
75 //static int aopIdx (asmop *aop, int offset);
77 int pic16_labelOffset=0;
78 extern int pic16_debug_verbose;
79 #if !(USE_GENERIC_SIGNED_SHIFT)
80 static int optimized_for_speed = 0;
89 /* max_key keeps track of the largest label number used in
90 a function. This is then used to adjust the label offset
91 for the next function.
94 static int GpsuedoStkPtr=0;
96 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
98 unsigned int pic16aopLiteral (value *val, int offset);
99 const char *pic16_AopType(short type);
100 static iCode *ifxForOp ( operand *op, iCode *ic );
102 void pic16_pushpCodeOp(pCodeOp *pcop);
103 void pic16_poppCodeOp(pCodeOp *pcop);
105 static bool is_LitOp(operand *op);
106 static bool is_LitAOp(asmop *aop);
109 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
111 /* set the following macro to 1 to enable passing the
112 * first byte of functions parameters via WREG */
113 #define USE_WREG_IN_FUNC_PARAMS 0
116 /* this is the down and dirty file with all kinds of
117 kludgy & hacky stuff. This is what it is all about
118 CODE GENERATION for a specific MCU . some of the
119 routines may be reusable, will have to see */
121 static char *zero = "#0x00";
122 static char *one = "#0x01";
123 //static char *spname = "sp";
127 * Function return value policy (MSB-->LSB):
129 * 16 bits -> PRODL:WREG
130 * 24 bits -> PRODH:PRODL:WREG
131 * 32 bits -> FSR0L:PRODH:PRODL:WREG
132 * >32 bits -> on stack, and FSR0 points to the beginning
137 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
138 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
139 static char **fReturn = fReturnpic16;
141 static char *accUse[] = {"WREG"};
143 //static short rbank = -1;
158 int stack_lat; /* stack offset latency */
160 int useWreg; /* flag when WREG is used to pass function parameter */
163 /* Resolved ifx structure. This structure stores information
164 about an iCode ifx that makes it easier to generate code.
166 typedef struct resolvedIfx {
167 symbol *lbl; /* pointer to a label */
168 int condition; /* true or false ifx */
169 int generated; /* set true when the code associated with the ifx
173 extern int pic16_ptrRegReq ;
174 extern int pic16_nRegs;
175 extern FILE *codeOutFile;
176 //static void saverbank (int, iCode *,bool);
178 static lineNode *lineHead = NULL;
179 static lineNode *lineCurr = NULL;
181 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
182 0xE0, 0xC0, 0x80, 0x00};
183 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
184 0x07, 0x03, 0x01, 0x00};
188 /*-----------------------------------------------------------------*/
189 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
190 /* exponent of 2 is returned, otherwise -1 is */
192 /* note that this is similar to the function `powof2' in SDCCsymt */
196 /*-----------------------------------------------------------------*/
197 int pic16_my_powof2 (unsigned long num)
200 if( (num & (num-1)) == 0) {
213 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
215 DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
217 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
218 ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
219 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
220 ((left) ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
221 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
222 ((right) ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
223 ((result) ? AOP_SIZE(result) : 0));
226 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
229 DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
231 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
232 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
233 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
234 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
235 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
236 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
240 void pic16_emitpcomment (char *fmt, ...)
243 char lb[INITIAL_INLINEASM];
249 vsprintf(lb+1,fmt,ap);
251 while (isspace(*lbp)) lbp++;
254 lineCurr = (lineCurr ?
255 connectLine(lineCurr,newLineNode(lb)) :
256 (lineHead = newLineNode(lb)));
257 lineCurr->isInline = _G.inLine;
258 lineCurr->isDebug = _G.debugLine;
260 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
263 // fprintf(stderr, "%s\n", lb);
266 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
269 char lb[INITIAL_INLINEASM];
272 if(!pic16_debug_verbose)
279 sprintf(lb,"%s\t",inst);
281 sprintf(lb,"%s",inst);
282 vsprintf(lb+(strlen(lb)),fmt,ap);
286 while (isspace(*lbp)) lbp++;
289 lineCurr = (lineCurr ?
290 connectLine(lineCurr,newLineNode(lb)) :
291 (lineHead = newLineNode(lb)));
292 lineCurr->isInline = _G.inLine;
293 lineCurr->isDebug = _G.debugLine;
295 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
298 // fprintf(stderr, "%s\n", lb);
303 void pic16_emitpLabel(int key)
305 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
308 void pic16_emitpLabelFORCE(int key)
310 pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
313 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
317 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
319 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
322 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
325 pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
327 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
330 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
333 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
339 #define pic16_emitcode DEBUGpic16_emitcode
341 /*-----------------------------------------------------------------*/
342 /* pic16_emitcode - writes the code into a file : for now it is simple */
343 /*-----------------------------------------------------------------*/
344 void pic16_emitcode (char *inst,char *fmt, ...)
347 char lb[INITIAL_INLINEASM];
354 sprintf(lb,"%s\t",inst);
356 sprintf(lb,"%s",inst);
357 vsprintf(lb+(strlen(lb)),fmt,ap);
361 while (isspace(*lbp)) lbp++;
364 lineCurr = (lineCurr ?
365 connectLine(lineCurr,newLineNode(lb)) :
366 (lineHead = newLineNode(lb)));
367 lineCurr->isInline = _G.inLine;
368 lineCurr->isDebug = _G.debugLine;
370 // VR fprintf(stderr, "lb = <%s>\n", lbp);
372 // if(pic16_debug_verbose)
373 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
380 /*-----------------------------------------------------------------*/
381 /* pic16_emitDebuggerSymbol - associate the current code location */
382 /* with a debugger symbol */
383 /*-----------------------------------------------------------------*/
385 pic16_emitDebuggerSymbol (char * debugSym)
388 pic16_emitcode (";", "%s ==.", debugSym);
393 /*-----------------------------------------------------------------*/
394 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
395 /*-----------------------------------------------------------------*/
396 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
398 // bool r0iu = FALSE , r1iu = FALSE;
399 // bool r0ou = FALSE , r1ou = FALSE;
400 bool fsr0iu = FALSE, fsr0ou;
401 bool fsr2iu = FALSE, fsr2ou;
403 fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
406 fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
407 fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
409 fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
410 fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
412 if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
413 fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
414 DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
417 if(!fsr0iu && !fsr0ou) {
418 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
419 (*aopp)->type = AOP_FSR0;
421 fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
423 return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
427 /* no usage of FSR2 */
428 if(!fsr2iu && !fsr2ou) {
429 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
430 (*aopp)->type = AOP_FSR2;
432 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
436 /* now we know they both have usage */
437 /* if fsr0 not used in this instruction */
439 if (!_G.fsr0Pushed) {
440 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
441 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
445 ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
446 (*aopp)->type = AOP_FSR0;
448 // fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
450 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
454 fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
459 /* the logic: if r0 & r1 used in the instruction
460 then we are in trouble otherwise */
462 /* first check if r0 & r1 are used by this
463 instruction, in which case we are in trouble */
464 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
465 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
470 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
471 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
473 /* if no usage of r0 then return it */
474 if (!r0iu && !r0ou) {
475 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
476 (*aopp)->type = AOP_R0;
478 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
481 /* if no usage of r1 then return it */
482 if (!r1iu && !r1ou) {
483 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
484 (*aopp)->type = AOP_R1;
486 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
489 /* now we know they both have usage */
490 /* if r0 not used in this instruction */
492 /* push it if not already pushed */
494 //pic16_emitcode ("push","%s",
495 // pic16_regWithIdx(R0_IDX)->dname);
499 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
500 (*aopp)->type = AOP_R0;
502 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
505 /* if r1 not used then */
508 /* push it if not already pushed */
510 //pic16_emitcode ("push","%s",
511 // pic16_regWithIdx(R1_IDX)->dname);
515 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
516 (*aopp)->type = AOP_R1;
517 return pic16_regWithIdx(R1_IDX);
521 /* I said end of world but not quite end of world yet */
522 /* if this is a result then we can push it on the stack*/
524 (*aopp)->type = AOP_STK;
528 /* other wise this is true end of the world */
529 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
530 "getFreePtr should never reach here");
535 /*-----------------------------------------------------------------*/
536 /* newAsmop - creates a new asmOp */
537 /*-----------------------------------------------------------------*/
538 static asmop *newAsmop (short type)
542 aop = Safe_calloc(1,sizeof(asmop));
547 static void genSetDPTR(int n)
551 pic16_emitcode(";", "Select standard DPTR");
552 pic16_emitcode("mov", "dps, #0x00");
556 pic16_emitcode(";", "Select alternate DPTR");
557 pic16_emitcode("mov", "dps, #0x01");
561 /*-----------------------------------------------------------------*/
562 /* resolveIfx - converts an iCode ifx into a form more useful for */
563 /* generating code */
564 /*-----------------------------------------------------------------*/
565 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
569 // DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
575 resIfx->condition = 1; /* assume that the ifx is true */
576 resIfx->generated = 0; /* indicate that the ifx has not been used */
579 resIfx->lbl = newiTempLabel(NULL); /* oops, there is no ifx. so create a label */
582 DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
583 __FUNCTION__,__LINE__,resIfx->lbl->key);
588 resIfx->lbl = IC_TRUE(ifx);
590 resIfx->lbl = IC_FALSE(ifx);
591 resIfx->condition = 0;
596 DEBUGpic16_emitcode("; +++","ifx true is non-null");
598 DEBUGpic16_emitcode("; +++","ifx true is null");
600 DEBUGpic16_emitcode("; +++","ifx false is non-null");
602 DEBUGpic16_emitcode("; +++","ifx false is null");
606 DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
610 /*-----------------------------------------------------------------*/
611 /* pointerCode - returns the code for a pointer type */
612 /*-----------------------------------------------------------------*/
613 static int pointerCode (sym_link *etype)
616 return PTR_TYPE(SPEC_OCLS(etype));
621 /*-----------------------------------------------------------------*/
622 /* aopForSym - for a true symbol */
623 /*-----------------------------------------------------------------*/
624 static asmop *aopForSym (iCode *ic, operand *op, bool result)
626 symbol *sym=OP_SYMBOL(op);
628 memmap *space= SPEC_OCLS(sym->etype);
632 _G.resDirect = 0; /* clear flag that instructs the result is loaded directly from aopForSym */
634 // sym = OP_SYMBOL(op);
636 /* if already has one */
638 DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
643 /* if symbol was initially placed onStack then we must re-place it
644 * to direct memory, since pic16 does not have a specific stack */
646 fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
654 fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
656 sym->aop = aop = newAsmop (AOP_PAGED);
657 aop->aopu.aop_dir = sym->rname ;
658 aop->size = getSize(sym->type);
659 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
660 pic16_allocDirReg( IC_LEFT(ic) );
668 /* assign depending on the storage class */
669 /* if it is on the stack or indirectly addressable */
670 /* space we need to assign either r0 or r1 to it */
671 if (sym->onStack) // || sym->iaccess)
676 DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
677 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
679 /* acquire a temporary register -- it is saved in function */
681 sym->aop = aop = newAsmop(AOP_STA);
682 aop->aopu.stk.stk = sym->stack;
683 aop->size = getSize(sym->type);
686 DEBUGpic16_emitcode("; +++", "%s:%d", __FILE__, __LINE__);
687 if((ic->op == '=') && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
688 && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG) ) {
689 pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
691 for(i=0;i<aop->size;i++)
692 aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
693 _G.resDirect = 1; /* notify that result will be loaded directly from aopForSym */
695 for(i=0;i<aop->size;i++) {
696 aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond( _G.fregsUsed, 0 );
697 _G.fregsUsed = bitVectSetBit(_G.fregsUsed, PCOR(pcop[i])->r->rIdx);
701 // fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
704 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
706 // we do not need to load the value if it is to be defined...
707 if (result) return aop;
710 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
713 for(i=0;i<aop->size;i++) {
715 /* initialise for stack access via frame pointer */
716 // operands on stack are accessible via "FSR2 + index" with index
717 // starting at 2 for arguments and growing from 0 downwards for
718 // local variables (index == 0 is not assigned so we add one here)
720 int soffs = sym->stack;
725 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
726 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
727 pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
732 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
739 /* now assign the address of the variable to
740 the pointer register */
741 if (aop->type != AOP_STK) {
745 pic16_emitcode("push","acc");
747 pic16_emitcode("mov","a,_bp");
748 pic16_emitcode("add","a,#0x%02x",
750 ((char)(sym->stack - _G.nRegsSaved )) :
751 ((char)sym->stack)) & 0xff);
752 pic16_emitcode("mov","%s,a",
753 aop->aopu.aop_ptr->name);
756 pic16_emitcode("pop","acc");
758 pic16_emitcode("mov","%s,#%s",
759 aop->aopu.aop_ptr->name,
761 aop->paged = space->paged;
763 aop->aopu.aop_stk = sym->stack;
771 if (sym->onStack && options.stack10bit)
773 /* It's on the 10 bit stack, which is located in
777 //DEBUGpic16_emitcode(";","%d",__LINE__);
780 pic16_emitcode("push","acc");
782 pic16_emitcode("mov","a,_bp");
783 pic16_emitcode("add","a,#0x%02x",
785 ((char)(sym->stack - _G.nRegsSaved )) :
786 ((char)sym->stack)) & 0xff);
789 pic16_emitcode ("mov","dpx1,#0x40");
790 pic16_emitcode ("mov","dph1,#0x00");
791 pic16_emitcode ("mov","dpl1, a");
795 pic16_emitcode("pop","acc");
797 sym->aop = aop = newAsmop(AOP_DPTR2);
798 aop->size = getSize(sym->type);
804 /* special case for a function */
805 if (IS_FUNC(sym->type)) {
806 sym->aop = aop = newAsmop(AOP_PCODE);
807 //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
808 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
809 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
810 PCOI(aop->aopu.pcop)->index = 0;
811 aop->size = FPTRSIZE;
812 DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
819 //DEBUGpic16_emitcode(";","%d",__LINE__);
820 /* if in bit space */
821 if (IN_BITSPACE(space)) {
822 sym->aop = aop = newAsmop (AOP_CRY);
823 aop->aopu.aop_dir = sym->rname ;
824 aop->size = getSize(sym->type);
825 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
828 /* if it is in direct space */
829 if (IN_DIRSPACE(space)) {
830 sym->aop = aop = newAsmop (AOP_DIR);
831 aop->aopu.aop_dir = sym->rname ;
832 aop->size = getSize(sym->type);
833 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
834 pic16_allocDirReg( IC_LEFT(ic) );
839 if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
840 sym->aop = aop = newAsmop (AOP_DIR);
841 aop->aopu.aop_dir = sym->rname ;
842 aop->size = getSize(sym->type);
843 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
844 pic16_allocDirReg( IC_LEFT(ic) );
849 /* only remaining is far space */
850 sym->aop = aop = newAsmop(AOP_PCODE);
852 /* change the next if to 1 to revert to good old immediate code */
853 if(IN_CODESPACE(space)) {
854 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
855 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
856 PCOI(aop->aopu.pcop)->index = 0;
858 /* try to allocate via direct register */
859 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
860 // aop->size = getSize( sym->type );
863 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
864 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
867 if(!pic16_allocDirReg (IC_LEFT(ic)))
871 if(IN_DIRSPACE( space ))
873 else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
874 aop->size = FPTRSIZE;
875 else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
876 else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
877 else if(sym->onStack) {
880 if(SPEC_SCLS(sym->etype) == S_PDATA) {
881 fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
882 aop->size = FPTRSIZE;
887 DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
889 /* if it is in code space */
890 if (IN_CODESPACE(space))
896 /*-----------------------------------------------------------------*/
897 /* aopForRemat - rematerialzes an object */
898 /*-----------------------------------------------------------------*/
899 static asmop *aopForRemat (operand *op) // x symbol *sym)
901 symbol *sym = OP_SYMBOL(op);
903 iCode *ic = NULL, *oldic;
904 asmop *aop = newAsmop(AOP_PCODE);
911 ic = sym->rematiCode;
913 if(IS_OP_POINTER(op)) {
914 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
920 // pic16_emitpcomment("ic: %s\n", printILine(ic));
923 val += (int) operandLitValue(IC_RIGHT(ic));
924 } else if (ic->op == '-') {
925 val -= (int) operandLitValue(IC_RIGHT(ic));
929 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
932 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
935 if(!op->isaddr)viaimmd++; else viaimmd=0;
937 /* set the following if to 1 to revert to good old immediate code */
938 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
941 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
943 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
946 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
948 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
951 PCOI(aop->aopu.pcop)->index = val;
953 aop->size = getSize( sym->type );
955 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__, getSize( OP_SYMBOL( IC_LEFT(ic))->type));
957 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
958 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
960 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
964 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
965 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
967 val, IS_PTR_CONST(operandType(op)));
969 val, IS_CODEPTR(operandType(op)));
972 // DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
974 pic16_allocDirReg (IC_LEFT(ic));
976 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
983 static int aopIdx (asmop *aop, int offset)
988 if(aop->type != AOP_REG)
991 return aop->aopu.aop_reg[offset]->rIdx;
996 /*-----------------------------------------------------------------*/
997 /* regsInCommon - two operands have some registers in common */
998 /*-----------------------------------------------------------------*/
999 static bool regsInCommon (operand *op1, operand *op2)
1001 symbol *sym1, *sym2;
1004 /* if they have registers in common */
1005 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1008 sym1 = OP_SYMBOL(op1);
1009 sym2 = OP_SYMBOL(op2);
1011 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1014 for (i = 0 ; i < sym1->nRegs ; i++) {
1019 for (j = 0 ; j < sym2->nRegs ;j++ ) {
1023 if (sym2->regs[j] == sym1->regs[i])
1031 /*-----------------------------------------------------------------*/
1032 /* operandsEqu - equivalent */
1033 /*-----------------------------------------------------------------*/
1034 static bool operandsEqu ( operand *op1, operand *op2)
1036 symbol *sym1, *sym2;
1038 /* if they not symbols */
1039 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1042 sym1 = OP_SYMBOL(op1);
1043 sym2 = OP_SYMBOL(op2);
1045 /* if both are itemps & one is spilt
1046 and the other is not then false */
1047 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1048 sym1->isspilt != sym2->isspilt )
1051 /* if they are the same */
1055 if (sym1->rname[0] && sym2->rname[0]
1056 && strcmp (sym1->rname, sym2->rname) == 0)
1060 /* if left is a tmp & right is not */
1061 if (IS_ITEMP(op1) &&
1064 (sym1->usl.spillLoc == sym2))
1067 if (IS_ITEMP(op2) &&
1071 (sym2->usl.spillLoc == sym1))
1077 /*-----------------------------------------------------------------*/
1078 /* pic16_sameRegs - two asmops have the same registers */
1079 /*-----------------------------------------------------------------*/
1080 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1087 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1088 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1090 if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1092 if (aop1->type != AOP_REG ||
1093 aop2->type != AOP_REG )
1096 /* This is a bit too restrictive if one is a subset of the other...
1097 if (aop1->size != aop2->size )
1101 for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1102 // if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1104 // if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1105 if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1112 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1114 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1115 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1117 if(aop1 == aop2)return TRUE;
1118 if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1120 if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1126 /*-----------------------------------------------------------------*/
1127 /* pic16_aopOp - allocates an asmop for an operand : */
1128 /*-----------------------------------------------------------------*/
1129 void pic16_aopOp (operand *op, iCode *ic, bool result)
1138 DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1140 /* if this a literal */
1141 if (IS_OP_LITERAL(op)) {
1142 op->aop = aop = newAsmop(AOP_LIT);
1143 aop->aopu.aop_lit = op->operand.valOperand;
1144 aop->size = getSize(operandType(op));
1149 sym_link *type = operandType(op);
1151 if(IS_PTR_CONST(type))
1153 if(IS_CODEPTR(type))
1155 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1158 /* if already has a asmop then continue */
1162 /* if the underlying symbol has a aop */
1163 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1164 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1165 op->aop = OP_SYMBOL(op)->aop;
1169 /* if this is a true symbol */
1170 if (IS_TRUE_SYMOP(op)) {
1171 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1172 op->aop = aopForSym(ic, op, result);
1176 /* this is a temporary : this has
1182 e) can be a return use only */
1184 sym = OP_SYMBOL(op);
1186 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1187 /* if the type is a conditional */
1188 if (sym->regType == REG_CND) {
1189 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1194 /* if it is spilt then two situations
1196 b) has a spill location */
1197 if (sym->isspilt || sym->nRegs == 0) {
1199 // debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1200 DEBUGpic16_emitcode(";","%d",__LINE__);
1201 /* rematerialize it NOW */
1204 sym->aop = op->aop = aop = aopForRemat (op);
1205 // aop->size = getSize(sym->type);
1206 // DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1213 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1214 aop->size = getSize(sym->type);
1215 for ( i = 0 ; i < 1 ; i++ ) {
1216 aop->aopu.aop_str[i] = accUse[i];
1217 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1219 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1220 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1228 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1229 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1230 //pic16_allocDirReg (IC_LEFT(ic));
1231 aop->size = getSize(sym->type);
1236 aop = op->aop = sym->aop = newAsmop(AOP_STR);
1237 aop->size = getSize(sym->type);
1238 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1239 aop->aopu.aop_str[i] = fReturn[i];
1241 DEBUGpic16_emitcode(";","%d",__LINE__);
1245 /* else spill location */
1246 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1247 /* force a new aop if sizes differ */
1248 sym->usl.spillLoc->aop = NULL;
1252 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1253 __FUNCTION__,__LINE__,
1254 sym->usl.spillLoc->rname,
1255 sym->rname, sym->usl.spillLoc->offset);
1258 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1259 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1260 if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1261 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1263 sym->usl.spillLoc->offset, op);
1265 fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__);
1266 DEBUGpic16_emitcode (";","%s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1267 assert (getSize(sym->type) <= 1);
1268 aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);//pic16_popRegFromString("_WREG", getSize(sym->type), 0, op);
1270 aop->size = getSize(sym->type);
1276 sym_link *type = operandType(op);
1278 if(IS_PTR_CONST(type))
1280 if(IS_CODEPTR(type))
1282 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1285 /* must be in a register */
1286 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1287 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1288 aop->size = sym->nRegs;
1289 for ( i = 0 ; i < sym->nRegs ;i++)
1290 aop->aopu.aop_reg[i] = sym->regs[i];
1293 /*-----------------------------------------------------------------*/
1294 /* pic16_freeAsmop - free up the asmop given to an operand */
1295 /*----------------------------------------------------------------*/
1296 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1313 /* depending on the asmop type only three cases need work AOP_RO
1314 , AOP_R1 && AOP_STK */
1316 switch (aop->type) {
1318 if (_G.fsr0Pushed ) {
1320 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1321 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1322 // pic16_emitcode ("pop","ar0");
1326 bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1330 bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1336 pic16_emitcode ("pop","ar0");
1340 bitVectUnSetBit(ic->rUsed,R0_IDX);
1346 pic16_emitcode ("pop","ar1");
1350 bitVectUnSetBit(ic->rUsed,R1_IDX);
1357 /* we must store the result on stack */
1358 if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1359 // operands on stack are accessible via "FSR2 + index" with index
1360 // starting at 2 for arguments and growing from 0 downwards for
1361 // local variables (index == 0 is not assigned so we add one here)
1362 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1367 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1368 for(i=0;i<aop->size;i++) {
1369 /* initialise for stack access via frame pointer */
1370 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1371 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1372 aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1375 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1379 for(i=0;i<aop->size;i++)
1380 PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1389 int stk = aop->aopu.aop_stk + aop->size;
1390 bitVectUnSetBit(ic->rUsed,R0_IDX);
1391 bitVectUnSetBit(ic->rUsed,R1_IDX);
1393 getFreePtr(ic,&aop,FALSE);
1395 if (options.stack10bit)
1397 /* I'm not sure what to do here yet... */
1400 "*** Warning: probably generating bad code for "
1401 "10 bit stack mode.\n");
1405 pic16_emitcode ("mov","a,_bp");
1406 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1407 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1409 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1413 pic16_emitcode("pop","acc");
1414 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1416 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1419 pic16_freeAsmop(op,NULL,ic,TRUE);
1421 pic16_emitcode("pop","ar0");
1426 pic16_emitcode("pop","ar1");
1436 /* all other cases just dealloc */
1440 OP_SYMBOL(op)->aop = NULL;
1441 /* if the symbol has a spill */
1443 SPIL_LOC(op)->aop = NULL;
1448 /*-----------------------------------------------------------------*/
1449 /* pic16_aopGet - for fetching value of the aop */
1450 /*-----------------------------------------------------------------*/
1451 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1456 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1458 /* offset is greater than size then zero */
1459 if (offset > (aop->size - 1) &&
1460 aop->type != AOP_LIT)
1463 /* depending on type */
1464 switch (aop->type) {
1468 sprintf(s, "%s", aop->aopu.aop_ptr->name);
1469 rs = Safe_calloc(1, strlen(s)+1);
1474 /* if we need to increment it */
1475 while (offset > aop->coff)
1477 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1481 while (offset < aop->coff)
1483 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1489 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1490 return (dname ? "acc" : "a");
1492 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1493 rs = Safe_calloc (1, strlen (s) + 1);
1501 sprintf (s,"%s",aop->aopu.aop_immd);
1504 sprintf(s,"(%s >> %d)",
1509 aop->aopu.aop_immd);
1510 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1511 rs = Safe_calloc(1,strlen(s)+1);
1517 sprintf(s,"(%s + %d)",
1520 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1522 sprintf(s,"%s",aop->aopu.aop_dir);
1523 rs = Safe_calloc(1,strlen(s)+1);
1529 // return aop->aopu.aop_reg[offset]->dname;
1531 return aop->aopu.aop_reg[offset]->name;
1534 //pic16_emitcode(";","%d",__LINE__);
1535 return aop->aopu.aop_dir;
1538 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1539 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1541 // return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1542 rs = Safe_strdup("WREG");
1546 sprintf(s,"0X%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1547 rs = Safe_calloc(1,strlen(s)+1);
1552 aop->coff = offset ;
1553 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1556 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1558 return aop->aopu.aop_str[offset];
1562 pCodeOp *pcop = aop->aopu.pcop;
1563 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1565 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1566 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1568 sprintf(s,"(%s + %d)", pcop->name, offset);
1570 sprintf(s,"%s", pcop->name);
1573 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1576 rs = Safe_calloc(1,strlen(s)+1);
1582 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1584 sprintf(s,"(%s + %d)",
1588 sprintf(s,"%s",aop->aopu.aop_dir);
1589 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1590 rs = Safe_calloc(1,strlen(s)+1);
1596 rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1600 // pCodeOp *pcop = aop->aop
1605 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1606 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1607 "aopget got unsupported aop->type");
1613 /* lock has the following meaning: When allocating temporary registers
1614 * for stack variables storage, the value of the temporary register is
1615 * saved on stack. Its value is restored at the end. This procedure is
1616 * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1617 * a possibility that before a call to pic16_aopOp, a temporary register
1618 * is allocated for a while and it is freed after some time, this will
1619 * mess the stack and values will not be restored properly. So use lock=1
1620 * to allocate temporary registers used internally by the programmer, and
1621 * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1622 * to inform the compiler developer about a possible bug. This is an internal
1623 * feature for developing the compiler -- VR */
1625 int _TempReg_lock = 0;
1626 /*-----------------------------------------------------------------*/
1627 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1628 /*-----------------------------------------------------------------*/
1629 pCodeOp *pic16_popGetTempReg(int lock)
1634 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1636 // werror(W_POSSBUG2, __FILE__, __LINE__);
1639 _TempReg_lock += lock;
1644 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1645 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1646 PCOR(pcop)->r->wasUsed=1;
1647 PCOR(pcop)->r->isFree=0;
1649 /* push value on stack */
1650 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1658 /*-----------------------------------------------------------------*/
1659 /* pic16_popGetTempRegCond - create a new temporary pCodeOp, but */
1660 /* don't save if inside v */
1661 /*-----------------------------------------------------------------*/
1662 pCodeOp *pic16_popGetTempRegCond(bitVect *v, int lock)
1667 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1670 // werror(W_POSSBUG2, __FILE__, __LINE__);
1673 _TempReg_lock += lock;
1678 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1679 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1680 PCOR(pcop)->r->wasUsed=1;
1681 PCOR(pcop)->r->isFree=0;
1683 if(!bitVectBitValue(v, PCOR(pcop)->r->rIdx)) {
1684 /* push value on stack */
1685 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1695 /*-----------------------------------------------------------------*/
1696 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1697 /*-----------------------------------------------------------------*/
1698 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1700 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1702 _TempReg_lock -= lock;
1704 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1705 PCOR(pcop)->r->isFree = 1;
1706 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1709 /*-----------------------------------------------------------------*/
1710 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1711 /*-----------------------------------------------------------------*/
1712 pCodeOp *pic16_popGetLabel(unsigned int key)
1715 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1720 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1723 /*-----------------------------------------------------------------*/
1724 /* pic16_popCopyReg - copy a pcode operator */
1725 /*-----------------------------------------------------------------*/
1726 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1730 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1731 pcor->pcop.type = pc->pcop.type;
1733 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1734 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1736 pcor->pcop.name = NULL;
1739 pcor->rIdx = pc->rIdx;
1741 pcor->instance = pc->instance;
1743 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1748 /*-----------------------------------------------------------------*/
1749 /* pic16_popGetLit - asm operator to pcode operator conversion */
1750 /*-----------------------------------------------------------------*/
1751 pCodeOp *pic16_popGetLit(int lit)
1753 return pic16_newpCodeOpLit(lit);
1756 /*-----------------------------------------------------------------*/
1757 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1758 /*-----------------------------------------------------------------*/
1759 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1761 return pic16_newpCodeOpLit2(lit, arg2);
1765 /*-----------------------------------------------------------------*/
1766 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1767 /*-----------------------------------------------------------------*/
1768 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1770 return pic16_newpCodeOpImmd(name, offset,index, 0);
1774 /*-----------------------------------------------------------------*/
1775 /* pic16_popGet - asm operator to pcode operator conversion */
1776 /*-----------------------------------------------------------------*/
1777 pCodeOp *pic16_popGetWithString(char *str)
1783 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1787 pcop = pic16_newpCodeOp(str,PO_STR);
1792 /*-----------------------------------------------------------------*/
1793 /* pic16_popRegFromString - */
1794 /*-----------------------------------------------------------------*/
1795 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1798 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1799 pcop->type = PO_DIR;
1801 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1802 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1807 pcop->name = Safe_calloc(1,strlen(str)+1);
1808 strcpy(pcop->name,str);
1810 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1812 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1814 /* make sure that register doesn't exist,
1815 * and operand isn't NULL
1816 * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1817 if((PCOR(pcop)->r == NULL)
1819 && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1820 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1821 // __FUNCTION__, __LINE__, str, size, offset);
1823 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1824 fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1827 PCOR(pcop)->instance = offset;
1832 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1836 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1838 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1839 PCOR(pcop)->rIdx = rIdx;
1840 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1842 PCOR(pcop)->r->isFree = 0;
1843 PCOR(pcop)->r->wasUsed = 1;
1845 pcop->type = PCOR(pcop)->r->pc_type;
1850 /*---------------------------------------------------------------------------------*/
1851 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1853 /*---------------------------------------------------------------------------------*/
1854 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1859 pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1861 /* comment the following check, so errors to throw up */
1862 // if(!pcop2)return NULL;
1864 temp = pic16_popGet(aop_dst, offset);
1865 pcop2->pcop2 = temp;
1872 /*--------------------------------------------------------------------------------.-*/
1873 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1874 /* VR 030601 , adapted by Hans Dorn */
1875 /*--------------------------------------------------------------------------------.-*/
1876 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1880 pcop2 = (pCodeOpReg2 *)src;
1888 /*---------------------------------------------------------------------------------*/
1889 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
1890 /* movff instruction */
1891 /*---------------------------------------------------------------------------------*/
1892 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1897 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1898 pcop2->pcop2 = pic16_popCopyReg(dst);
1900 /* the pCodeOp may be already allocated */
1901 pcop2 = (pCodeOpReg2 *)(src);
1902 pcop2->pcop2 = (pCodeOp *)(dst);
1909 /*-----------------------------------------------------------------*/
1910 /* pic16_popGet - asm operator to pcode operator conversion */
1911 /*-----------------------------------------------------------------*/
1912 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1914 //char *s = buffer ;
1919 /* offset is greater than
1922 // if (offset > (aop->size - 1) &&
1923 // aop->type != AOP_LIT)
1924 // return NULL; //zero;
1926 /* depending on type */
1927 switch (aop->type) {
1933 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1934 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1941 pcop = Safe_calloc(1, sizeof(pCodeOpReg));
1942 PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */
1943 PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
1944 PCOR(pcop)->r->wasUsed = 1;
1945 PCOR(pcop)->r->isFree = 0;
1947 PCOR(pcop)->instance = offset;
1948 pcop->type = PCOR(pcop)->r->pc_type;
1952 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1953 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1956 /* pCodeOp is already allocated from aopForSym */
1957 DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
1958 pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
1964 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
1966 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1968 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1970 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1971 PCOR(pcop)->rIdx = rIdx;
1972 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1973 PCOR(pcop)->r->wasUsed=1;
1974 PCOR(pcop)->r->isFree=0;
1976 PCOR(pcop)->instance = offset;
1977 pcop->type = PCOR(pcop)->r->pc_type;
1978 // rs = aop->aopu.aop_reg[offset]->name;
1979 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1983 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1984 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1990 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1991 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1995 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1996 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2002 assert (aop && aop->aopu.aop_reg[offset] != NULL);
2003 rIdx = aop->aopu.aop_reg[offset]->rIdx;
2005 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2007 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2008 // pcop->type = PO_GPR_REGISTER;
2009 PCOR(pcop)->rIdx = rIdx;
2010 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
2011 PCOR(pcop)->r->wasUsed=1;
2012 PCOR(pcop)->r->isFree=0;
2014 PCOR(pcop)->instance = offset;
2015 pcop->type = PCOR(pcop)->r->pc_type;
2017 DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2018 rs = aop->aopu.aop_reg[offset]->name;
2019 DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2024 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2026 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2027 PCOR(pcop)->instance = offset;
2028 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2029 //if(PCOR(pcop)->r == NULL)
2030 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2034 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2035 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2038 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2039 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2042 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2043 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2044 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2045 pcop->type = PCOR(pcop)->r->pc_type;
2046 pcop->name = PCOR(pcop)->r->name;
2052 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2054 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2055 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2056 switch( aop->aopu.pcop->type ) {
2057 case PO_DIR: PCOR(pcop)->instance += offset; break;
2058 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2063 fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2064 assert( 0 ); /* should never reach here */;
2069 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2070 "pic16_popGet got unsupported aop->type");
2073 /*-----------------------------------------------------------------*/
2074 /* pic16_aopPut - puts a string for a aop */
2075 /*-----------------------------------------------------------------*/
2076 void pic16_aopPut (asmop *aop, char *s, int offset)
2083 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2085 if (aop->size && offset > ( aop->size - 1)) {
2086 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2087 "pic16_aopPut got offset > aop->size");
2091 /* will assign value to value */
2092 /* depending on where it is ofcourse */
2093 switch (aop->type) {
2096 sprintf(d,"(%s + %d)",
2097 aop->aopu.aop_dir,offset);
2098 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2101 sprintf(d,"%s",aop->aopu.aop_dir);
2104 DEBUGpic16_emitcode(";","%d",__LINE__);
2106 pic16_emitcode("movf","%s,w",s);
2107 pic16_emitcode("movwf","%s",d);
2110 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
2111 if(offset >= aop->size) {
2112 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2115 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2118 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2125 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2126 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2129 strcmp(s,"r0") == 0 ||
2130 strcmp(s,"r1") == 0 ||
2131 strcmp(s,"r2") == 0 ||
2132 strcmp(s,"r3") == 0 ||
2133 strcmp(s,"r4") == 0 ||
2134 strcmp(s,"r5") == 0 ||
2135 strcmp(s,"r6") == 0 ||
2136 strcmp(s,"r7") == 0 )
2137 pic16_emitcode("mov","%s,%s ; %d",
2138 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2142 if(strcmp(s,"W")==0 )
2143 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
2145 pic16_emitcode("movwf","%s",
2146 aop->aopu.aop_reg[offset]->name);
2148 if(strcmp(s,zero)==0) {
2149 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2151 } else if(strcmp(s,"W")==0) {
2152 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2153 pcop->type = PO_GPR_REGISTER;
2155 PCOR(pcop)->rIdx = -1;
2156 PCOR(pcop)->r = NULL;
2158 DEBUGpic16_emitcode(";","%d",__LINE__);
2159 pcop->name = Safe_strdup(s);
2160 pic16_emitpcode(POC_MOVFW,pcop);
2161 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2162 } else if(strcmp(s,one)==0) {
2163 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2164 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2166 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2174 if (aop->type == AOP_DPTR2)
2180 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2181 "pic16_aopPut writting to code space");
2185 while (offset > aop->coff) {
2187 pic16_emitcode ("inc","dptr");
2190 while (offset < aop->coff) {
2192 pic16_emitcode("lcall","__decdptr");
2197 /* if not in accumulater */
2200 pic16_emitcode ("movx","@dptr,a");
2202 if (aop->type == AOP_DPTR2)
2210 while (offset > aop->coff) {
2212 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2214 while (offset < aop->coff) {
2216 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2222 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2227 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2229 if (strcmp(s,"r0") == 0 ||
2230 strcmp(s,"r1") == 0 ||
2231 strcmp(s,"r2") == 0 ||
2232 strcmp(s,"r3") == 0 ||
2233 strcmp(s,"r4") == 0 ||
2234 strcmp(s,"r5") == 0 ||
2235 strcmp(s,"r6") == 0 ||
2236 strcmp(s,"r7") == 0 ) {
2238 sprintf(buffer,"a%s",s);
2239 pic16_emitcode("mov","@%s,%s",
2240 aop->aopu.aop_ptr->name,buffer);
2242 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2247 if (strcmp(s,"a") == 0)
2248 pic16_emitcode("push","acc");
2250 pic16_emitcode("push","%s",s);
2255 /* if bit variable */
2256 if (!aop->aopu.aop_dir) {
2257 pic16_emitcode("clr","a");
2258 pic16_emitcode("rlc","a");
2261 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2264 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2267 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2269 lbl = newiTempLabel(NULL);
2271 if (strcmp(s,"a")) {
2274 pic16_emitcode("clr","c");
2275 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2276 pic16_emitcode("cpl","c");
2277 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2278 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2285 if (strcmp(aop->aopu.aop_str[offset],s))
2286 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2291 if (!offset && (strcmp(s,"acc") == 0))
2294 if (strcmp(aop->aopu.aop_str[offset],s))
2295 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2299 fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2300 // werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2301 // "pic16_aopPut got unsupported aop->type");
2307 /*-----------------------------------------------------------------*/
2308 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type */
2309 /*-----------------------------------------------------------------*/
2310 void pic16_mov2w (asmop *aop, int offset)
2312 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2315 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2317 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2320 static void mov2f(asmop *dst, asmop *src, int offset)
2322 if(is_LitAOp(src)) {
2323 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2324 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2326 if(pic16_sameRegsOfs(src, dst, offset))return;
2327 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2328 pic16_popGet(dst, offset)));
2332 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2334 if(is_LitAOp(src)) {
2335 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2336 pic16_emitpcode(POC_MOVWF, dst);
2338 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2342 void pic16_testStackOverflow(void)
2344 #define GSTACK_TEST_NAME "__gstack_test"
2346 pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2351 sym = newSymbol( GSTACK_TEST_NAME , 0 );
2352 strcpy(sym->rname, GSTACK_TEST_NAME);
2353 checkAddSym(&externs, sym);
2358 /* push pcop into stack */
2359 void pic16_pushpCodeOp(pCodeOp *pcop)
2361 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2362 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec ))); //&pic16_pc_postdec1)));
2363 if(pic16_options.gstack)
2364 pic16_testStackOverflow();
2368 /* pop pcop from stack */
2369 void pic16_poppCodeOp(pCodeOp *pcop)
2371 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2372 if(pic16_options.gstack)
2373 pic16_testStackOverflow();
2377 /*-----------------------------------------------------------------*/
2378 /* pushw - pushes wreg to stack */
2379 /*-----------------------------------------------------------------*/
2382 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2383 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec )); //&pic16_pc_postdec1));
2384 if(pic16_options.gstack)
2385 pic16_testStackOverflow();
2389 /*-----------------------------------------------------------------*/
2390 /* pushaop - pushes aop to stack */
2391 /*-----------------------------------------------------------------*/
2392 void pushaop(asmop *aop, int offset)
2394 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2396 if(is_LitAOp(aop)) {
2397 pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2398 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec )); //&pic16_pc_postdec1));
2400 pic16_emitpcode(POC_MOVFF,
2401 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec ))); //&pic16_pc_postdec1)));
2404 if(pic16_options.gstack)
2405 pic16_testStackOverflow();
2408 /*-----------------------------------------------------------------*/
2409 /* popaop - pops aop from stack */
2410 /*-----------------------------------------------------------------*/
2411 void popaop(asmop *aop, int offset)
2413 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2414 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2415 if(pic16_options.gstack)
2416 pic16_testStackOverflow();
2419 void popaopidx(asmop *aop, int offset, int index)
2423 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2425 if(STACK_MODEL_LARGE)ofs++;
2427 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2428 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2429 if(pic16_options.gstack)
2430 pic16_testStackOverflow();
2433 #if !(USE_GENERIC_SIGNED_SHIFT)
2434 /*-----------------------------------------------------------------*/
2435 /* reAdjustPreg - points a register back to where it should */
2436 /*-----------------------------------------------------------------*/
2437 static void reAdjustPreg (asmop *aop)
2441 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2443 if ((size = aop->size) <= 1)
2446 switch (aop->type) {
2450 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2454 if (aop->type == AOP_DPTR2)
2460 pic16_emitcode("lcall","__decdptr");
2463 if (aop->type == AOP_DPTR2)
2475 /*-----------------------------------------------------------------*/
2476 /* opIsGptr: returns non-zero if the passed operand is */
2477 /* a generic pointer type. */
2478 /*-----------------------------------------------------------------*/
2479 static int opIsGptr(operand *op)
2481 sym_link *type = operandType(op);
2483 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2484 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2492 /*-----------------------------------------------------------------*/
2493 /* pic16_getDataSize - get the operand data size */
2494 /*-----------------------------------------------------------------*/
2495 int pic16_getDataSize(operand *op)
2497 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2500 return AOP_SIZE(op);
2502 // tsd- in the pic port, the genptr size is 1, so this code here
2503 // fails. ( in the 8051 port, the size was 4).
2506 size = AOP_SIZE(op);
2507 if (size == GPTRSIZE)
2509 sym_link *type = operandType(op);
2510 if (IS_GENPTR(type))
2512 /* generic pointer; arithmetic operations
2513 * should ignore the high byte (pointer type).
2516 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2523 /*-----------------------------------------------------------------*/
2524 /* pic16_outAcc - output Acc */
2525 /*-----------------------------------------------------------------*/
2526 void pic16_outAcc(operand *result)
2529 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2530 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2533 size = pic16_getDataSize(result);
2535 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2538 /* unsigned or positive */
2540 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2545 /*-----------------------------------------------------------------*/
2546 /* pic16_outBitC - output a bit C */
2547 /* Move to result the value of Carry flag -- VR */
2548 /*-----------------------------------------------------------------*/
2549 void pic16_outBitC(operand *result)
2553 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2555 /* if the result is bit */
2556 if (AOP_TYPE(result) == AOP_CRY) {
2557 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2558 pic16_aopPut(AOP(result),"c",0);
2561 i = AOP_SIZE(result);
2563 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2565 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2569 /*-----------------------------------------------------------------*/
2570 /* pic16_outBitOp - output a bit from Op */
2571 /* Move to result the value of set/clr op -- VR */
2572 /*-----------------------------------------------------------------*/
2573 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2577 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2579 /* if the result is bit */
2580 if (AOP_TYPE(result) == AOP_CRY) {
2581 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2582 pic16_aopPut(AOP(result),"c",0);
2585 i = AOP_SIZE(result);
2587 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2589 pic16_emitpcode(POC_RRCF, pcop);
2590 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2594 /*-----------------------------------------------------------------*/
2595 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2596 /*-----------------------------------------------------------------*/
2597 void pic16_toBoolean(operand *oper)
2599 int size = AOP_SIZE(oper) - 1;
2602 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2604 if ( AOP_TYPE(oper) != AOP_ACC) {
2605 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2608 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2613 #if !defined(GEN_Not)
2614 /*-----------------------------------------------------------------*/
2615 /* genNot - generate code for ! operation */
2616 /*-----------------------------------------------------------------*/
2617 static void pic16_genNot (iCode *ic)
2623 /* assign asmOps to operand & result */
2624 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2625 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2627 DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2628 /* if in bit space then a special case */
2629 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2630 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2631 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2632 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2634 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2635 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2636 pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2641 size = AOP_SIZE(IC_LEFT(ic));
2643 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2644 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2645 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2648 pic16_toBoolean(IC_LEFT(ic));
2650 tlbl = newiTempLabel(NULL);
2651 pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2652 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2653 pic16_outBitC(IC_RESULT(ic));
2656 /* release the aops */
2657 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2658 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2663 #if !defined(GEN_Cpl)
2664 /*-----------------------------------------------------------------*/
2665 /* genCpl - generate code for complement */
2666 /*-----------------------------------------------------------------*/
2667 static void pic16_genCpl (iCode *ic)
2673 /* assign asmOps to operand & result */
2674 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2675 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2677 /* if both are in bit space then
2679 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2680 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2682 pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
2683 pic16_emitcode("cpl","c");
2684 pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
2688 size = AOP_SIZE(IC_RESULT(ic));
2691 char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2693 pic16_emitcode("cpl","a");
2694 pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2696 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2697 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)), offset));
2699 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2700 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2708 /* release the aops */
2709 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2710 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2714 /*-----------------------------------------------------------------*/
2715 /* genUminusFloat - unary minus for floating points */
2716 /*-----------------------------------------------------------------*/
2717 static void genUminusFloat(operand *op,operand *result)
2719 int size ,offset =0 ;
2722 /* for this we just need to flip the
2723 first it then copy the rest in place */
2724 size = AOP_SIZE(op);
2727 mov2f(AOP(result), AOP(op), offset);
2731 /* toggle the MSB's highest bit */
2732 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2735 /*-----------------------------------------------------------------*/
2736 /* genUminus - unary minus code generation */
2737 /*-----------------------------------------------------------------*/
2738 static void genUminus (iCode *ic)
2741 sym_link *optype, *rtype;
2748 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2749 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2751 /* if both in bit space then special case */
2752 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2753 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2755 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2756 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2757 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2761 optype = operandType(IC_LEFT(ic));
2762 rtype = operandType(IC_RESULT(ic));
2764 /* if float then do float stuff */
2765 if (IS_FLOAT(optype)) {
2766 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2770 /* otherwise subtract from zero by taking the 2's complement */
2771 size = AOP_SIZE(IC_LEFT(ic));
2772 label = newiTempLabel ( NULL );
2774 if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2775 for (i=size-1; i > 0; i--) {
2776 pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2778 pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2779 for (i=1; i < size; i++) {
2780 if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2781 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2784 for (i=size-1; i >= 0; i--) {
2785 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2786 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2789 for (i=0; i < size-2; i++) {
2790 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2791 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2793 pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2795 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2798 pic16_emitpLabel (label->key);
2801 /* release the aops */
2802 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2803 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2807 /*-----------------------------------------------------------------*/
2808 /* saveRegisters - will look for a call and save the registers */
2809 /*-----------------------------------------------------------------*/
2810 static void saveRegisters(iCode *lic)
2817 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2819 for (ic = lic ; ic ; ic = ic->next)
2820 if (ic->op == CALL || ic->op == PCALL)
2824 fprintf(stderr,"found parameter push with no function call\n");
2828 /* if the registers have been saved already then
2830 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2833 /* find the registers in use at this time
2834 and push them away to safety */
2835 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2839 if (options.useXstack) {
2840 if (bitVectBitValue(rsave,R0_IDX))
2841 pic16_emitcode("mov","b,r0");
2842 pic16_emitcode("mov","r0,%s",spname);
2843 for (i = 0 ; i < pic16_nRegs ; i++) {
2844 if (bitVectBitValue(rsave,i)) {
2846 pic16_emitcode("mov","a,b");
2848 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2849 pic16_emitcode("movx","@r0,a");
2850 pic16_emitcode("inc","r0");
2853 pic16_emitcode("mov","%s,r0",spname);
2854 if (bitVectBitValue(rsave,R0_IDX))
2855 pic16_emitcode("mov","r0,b");
2857 //for (i = 0 ; i < pic16_nRegs ; i++) {
2858 // if (bitVectBitValue(rsave,i))
2859 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2862 dtype = operandType(IC_LEFT(ic));
2863 if (currFunc && dtype &&
2864 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2865 IFFUNC_ISISR(currFunc->type) &&
2868 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2871 /*-----------------------------------------------------------------*/
2872 /* unsaveRegisters - pop the pushed registers */
2873 /*-----------------------------------------------------------------*/
2874 static void unsaveRegisters (iCode *ic)
2879 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2880 /* find the registers in use at this time
2881 and push them away to safety */
2882 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2885 if (options.useXstack) {
2886 pic16_emitcode("mov","r0,%s",spname);
2887 for (i = pic16_nRegs ; i >= 0 ; i--) {
2888 if (bitVectBitValue(rsave,i)) {
2889 pic16_emitcode("dec","r0");
2890 pic16_emitcode("movx","a,@r0");
2892 pic16_emitcode("mov","b,a");
2894 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2898 pic16_emitcode("mov","%s,r0",spname);
2899 if (bitVectBitValue(rsave,R0_IDX))
2900 pic16_emitcode("mov","r0,b");
2902 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2903 // if (bitVectBitValue(rsave,i))
2904 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2911 /*-----------------------------------------------------------------*/
2913 /*-----------------------------------------------------------------*/
2914 static void pushSide(operand * oper, int size)
2917 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2919 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2920 if (AOP_TYPE(oper) != AOP_REG &&
2921 AOP_TYPE(oper) != AOP_DIR &&
2923 pic16_emitcode("mov","a,%s",l);
2924 pic16_emitcode("push","acc");
2926 pic16_emitcode("push","%s",l);
2931 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2933 if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2934 pic16_emitpcode(POC_MOVFW, src);
2935 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2937 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2938 src, pic16_popGet(AOP(op), offset)));
2943 /*-----------------------------------------------------------------*/
2944 /* assignResultValue - assign results to oper, rescall==1 is */
2945 /* called from genCall() or genPcall() */
2946 /*-----------------------------------------------------------------*/
2947 static void assignResultValue(operand * oper, int rescall)
2949 int size = AOP_SIZE(oper);
2953 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2954 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2957 /* assign result from a call/pcall function() */
2959 /* function results are stored in a special order,
2960 * see top of file with Function return policy, or manual */
2963 /* 8-bits, result in WREG */
2964 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2967 /* 16-bits, result in PRODL:WREG */
2968 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2972 /* 24-bits, result in PRODH:PRODL:WREG */
2973 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2977 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2978 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2982 /* >32-bits, result on stack, and FSR0 points to beginning.
2983 * Fix stack when done */
2985 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2987 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2988 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2990 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2995 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2996 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
2997 if(STACK_MODEL_LARGE) {
2999 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3003 int areg = 0; /* matching argument register */
3005 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3006 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3009 /* its called from genReceive (probably) -- VR */
3010 /* I hope this code will not be called from somewhere else in the future!
3011 * We manually set the pseudo stack pointer in genReceive. - dw
3013 if(!GpsuedoStkPtr && _G.useWreg) {
3014 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3016 /* The last byte in the assignment is in W */
3017 if(areg <= GpsuedoStkPtr) {
3019 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3021 // debugf("receive from WREG\n", 0);
3023 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3026 _G.stack_lat = AOP_SIZE(oper)-1;
3031 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3032 // debugf("receive from STACK\n", 0);
3039 /*-----------------------------------------------------------------*/
3040 /* genIpush - generate code for pushing this gets a little complex */
3041 /*-----------------------------------------------------------------*/
3042 static void genIpush (iCode *ic)
3044 // int size, offset=0;
3047 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3050 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3052 /* send to stack as normal */
3053 addSet(&_G.sendSet,ic);
3054 // addSetHead(&_G.sendSet,ic);
3055 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3060 int size, offset = 0 ;
3064 /* if this is not a parm push : ie. it is spill push
3065 and spill push is always done on the local stack */
3066 if (!ic->parmPush) {
3068 /* and the item is spilt then do nothing */
3069 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3072 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3073 size = AOP_SIZE(IC_LEFT(ic));
3074 /* push it on the stack */
3076 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3081 pic16_emitcode("push","%s",l);
3086 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3090 /*-----------------------------------------------------------------*/
3091 /* genIpop - recover the registers: can happen only for spilling */
3092 /*-----------------------------------------------------------------*/
3093 static void genIpop (iCode *ic)
3096 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3101 /* if the temp was not pushed then */
3102 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3105 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3106 size = AOP_SIZE(IC_LEFT(ic));
3109 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3112 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3117 /*-----------------------------------------------------------------*/
3118 /* unsaverbank - restores the resgister bank from stack */
3119 /*-----------------------------------------------------------------*/
3120 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3122 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3128 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3130 if (options.useXstack) {
3132 r = getFreePtr(ic,&aop,FALSE);
3135 pic16_emitcode("mov","%s,_spx",r->name);
3136 pic16_emitcode("movx","a,@%s",r->name);
3137 pic16_emitcode("mov","psw,a");
3138 pic16_emitcode("dec","%s",r->name);
3141 pic16_emitcode ("pop","psw");
3144 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3145 if (options.useXstack) {
3146 pic16_emitcode("movx","a,@%s",r->name);
3147 //pic16_emitcode("mov","(%s+%d),a",
3148 // regspic16[i].base,8*bank+regspic16[i].offset);
3149 pic16_emitcode("dec","%s",r->name);
3152 pic16_emitcode("pop",""); //"(%s+%d)",
3153 //regspic16[i].base,8*bank); //+regspic16[i].offset);
3156 if (options.useXstack) {
3158 pic16_emitcode("mov","_spx,%s",r->name);
3159 pic16_freeAsmop(NULL,aop,ic,TRUE);
3165 /*-----------------------------------------------------------------*/
3166 /* saverbank - saves an entire register bank on the stack */
3167 /*-----------------------------------------------------------------*/
3168 static void saverbank (int bank, iCode *ic, bool pushPsw)
3170 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3176 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3177 if (options.useXstack) {
3180 r = getFreePtr(ic,&aop,FALSE);
3181 pic16_emitcode("mov","%s,_spx",r->name);
3185 for (i = 0 ; i < pic16_nRegs ;i++) {
3186 if (options.useXstack) {
3187 pic16_emitcode("inc","%s",r->name);
3188 //pic16_emitcode("mov","a,(%s+%d)",
3189 // regspic16[i].base,8*bank+regspic16[i].offset);
3190 pic16_emitcode("movx","@%s,a",r->name);
3192 pic16_emitcode("push","");// "(%s+%d)",
3193 //regspic16[i].base,8*bank+regspic16[i].offset);
3197 if (options.useXstack) {
3198 pic16_emitcode("mov","a,psw");
3199 pic16_emitcode("movx","@%s,a",r->name);
3200 pic16_emitcode("inc","%s",r->name);
3201 pic16_emitcode("mov","_spx,%s",r->name);
3202 pic16_freeAsmop (NULL,aop,ic,TRUE);
3205 pic16_emitcode("push","psw");
3207 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3215 static int wparamCmp(void *p1, void *p2)
3217 return (!strcmp((char *)p1, (char *)p2));
3220 int inWparamList(char *s)
3222 return isinSetWith(wparamList, s, wparamCmp);
3226 /*-----------------------------------------------------------------*/
3227 /* genCall - generates a call statement */
3228 /*-----------------------------------------------------------------*/
3229 static void genCall (iCode *ic)
3239 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3240 /* if caller saves & we have not saved then */
3241 // if (!ic->regsSaved)
3242 // saveRegisters(ic);
3244 /* initialise stackParms for IPUSH pushes */
3245 // stackParms = psuedoStkPtr;
3246 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3247 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3248 inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3251 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3254 /* if send set is not empty the assign */
3257 int psuedoStkPtr=-1;
3258 int firstTimeThruLoop = 1;
3261 /* reverse sendSet if function is not reentrant */
3262 if(!IFFUNC_ISREENT(ftype))
3263 _G.sendSet = reverseSet(_G.sendSet);
3265 /* First figure how many parameters are getting passed */
3269 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3273 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3274 size = AOP_SIZE(IC_LEFT(sic));
3278 /* pass the last byte through WREG */
3282 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3283 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3284 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3286 if(!firstTimeThruLoop) {
3287 /* If this is not the first time we've been through the loop
3288 * then we need to save the parameter in a temporary
3289 * register. The last byte of the last parameter is
3293 // --psuedoStkPtr; // sanity check
3297 firstTimeThruLoop=0;
3299 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3304 /* all arguments are passed via stack */
3308 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3309 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3310 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3312 // pushaop(AOP(IC_LEFT(sic)), size);
3313 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3318 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3322 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3323 pushw(); /* save last parameter to stack if functions has varargs */
3327 } else use_wreg = 0;
3329 _G.stackRegSet = _G.sendSet;
3334 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3338 /* if we need to assign a result value */
3339 if ((IS_ITEMP(IC_RESULT(ic))
3340 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3341 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3342 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3345 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3348 assignResultValue(IC_RESULT(ic), 1);
3350 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3351 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3353 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3356 if(!stackParms && ic->parmBytes) {
3357 stackParms = ic->parmBytes;
3360 stackParms -= use_wreg;
3363 if(stackParms == 1) {
3364 pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3366 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3367 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3369 if(STACK_MODEL_LARGE) {
3371 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3376 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3379 /* adjust the stack for parameters if required */
3380 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3383 /* if register bank was saved then pop them */
3385 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3387 /* if we hade saved some registers then unsave them */
3388 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3389 unsaveRegisters (ic);
3395 /*-----------------------------------------------------------------*/
3396 /* genPcall - generates a call by pointer statement */
3397 /* new version, created from genCall - HJD */
3398 /*-----------------------------------------------------------------*/
3399 static void genPcall (iCode *ic)
3401 sym_link *ftype, *fntype;
3403 symbol *retlbl = newiTempLabel(NULL);
3404 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3408 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3409 fntype = operandType( IC_LEFT(ic) )->next;
3411 /* if send set is not empty the assign */
3414 int psuedoStkPtr=-1;
3416 /* reverse sendSet if function is not reentrant */
3417 if(!IFFUNC_ISREENT(fntype))
3418 _G.sendSet = reverseSet(_G.sendSet);
3422 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3425 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3426 size = AOP_SIZE(IC_LEFT(sic));
3429 /* all parameters are passed via stack, since WREG is clobbered
3430 * by the calling sequence */
3432 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3433 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3434 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3436 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3440 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3443 _G.stackRegSet = _G.sendSet;
3447 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3449 // push return address
3450 // push $ on return stack, then replace with retlbl
3452 /* Thanks to Thorsten Klose for pointing out that the following
3453 * snippet should be interrupt safe */
3454 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3455 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3457 pic16_emitpcodeNULLop(POC_PUSH);
3459 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3460 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3461 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3462 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3463 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3464 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3467 /* restore interrupt control register */
3468 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3469 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3471 /* make the call by writing the pointer into pc */
3472 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3473 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3475 // note: MOVFF to PCL not allowed
3476 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3477 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3480 /* return address is here: (X) */
3481 pic16_emitpLabelFORCE(retlbl->key);
3483 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3486 /* if we need assign a result value */
3487 if ((IS_ITEMP(IC_RESULT(ic))
3488 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3489 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3490 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3493 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3496 assignResultValue(IC_RESULT(ic), 1);
3498 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3499 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3501 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3504 // stackParms -= use_wreg;
3507 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3508 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3509 if(STACK_MODEL_LARGE) {
3511 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3516 /*-----------------------------------------------------------------*/
3517 /* resultRemat - result is rematerializable */
3518 /*-----------------------------------------------------------------*/
3519 static int resultRemat (iCode *ic)
3521 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3522 if (SKIP_IC(ic) || ic->op == IFX)
3525 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3526 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3527 if (sym->remat && !POINTER_SET(ic))
3534 #if defined(__BORLANDC__) || defined(_MSC_VER)
3535 #define STRCASECMP stricmp
3537 #define STRCASECMP strcasecmp
3541 /*-----------------------------------------------------------------*/
3542 /* inExcludeList - return 1 if the string is in exclude Reg list */
3543 /*-----------------------------------------------------------------*/
3544 static bool inExcludeList(char *s)
3546 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3549 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3550 if (options.excludeRegs[i] &&
3551 STRCASECMP(options.excludeRegs[i],"none") == 0)
3554 for ( i = 0 ; options.excludeRegs[i]; i++) {
3555 if (options.excludeRegs[i] &&
3556 STRCASECMP(s,options.excludeRegs[i]) == 0)
3563 /*-----------------------------------------------------------------*/
3564 /* genFunction - generated code for function entry */
3565 /*-----------------------------------------------------------------*/
3566 static void genFunction (iCode *ic)
3572 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3574 pic16_labelOffset += (max_key+4);
3579 ftype = operandType(IC_LEFT(ic));
3580 sym = OP_SYMBOL(IC_LEFT(ic));
3582 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3583 /* create an absolute section at the interrupt vector:
3584 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3589 // debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3595 sym = OP_SYMBOL( IC_LEFT(ic));
3597 if(interrupts[i]->name
3598 && !STRCASECMP(interrupts[i]->name, sym->name)) {
3605 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3606 __FILE__, __LINE__, sym->name);
3609 _G.interruptvector = found;
3613 if(FUNC_INTNO(sym->type) == 256)
3614 sprintf(asymname, "ivec_%s", sym->name);
3616 sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3617 asym = newSymbol(asymname, 0);
3619 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3620 pic16_addpBlock( apb );
3622 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3623 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3624 pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3626 /* mark the end of this tiny function */
3627 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3632 abSym = Safe_calloc(1, sizeof(absSym));
3633 strcpy(abSym->name, asymname);
3635 switch( FUNC_INTNO(sym->type) ) {
3636 case 0: abSym->address = 0x000000; break;
3637 case 1: abSym->address = 0x000008; break;
3638 case 2: abSym->address = 0x000018; break;
3641 abSym->address = -1; break;
3644 /* relocate interrupt vectors if needed */
3645 if(abSym->address != -1)
3646 abSym->address += pic16_options.ivt_loc;
3648 addSet(&absSymSet, abSym);
3652 /* create the function header */
3653 pic16_emitcode(";","-----------------------------------------");
3654 pic16_emitcode(";"," function %s",sym->name);
3655 pic16_emitcode(";","-----------------------------------------");
3657 pic16_emitcode("","%s:",sym->rname);
3658 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3664 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3665 if(!strcmp(ab->name, sym->rname)) {
3666 pic16_pBlockConvert2Absolute(pb);
3673 if(IFFUNC_ISNAKED(ftype)) {
3674 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3678 /* if critical function then turn interrupts off */
3679 if (IFFUNC_ISCRITICAL(ftype)) {
3680 //pic16_emitcode("clr","ea");
3683 _G.fregsUsed = sym->regsUsed;
3685 /* if this is an interrupt service routine then
3686 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3687 if (IFFUNC_ISISR(sym->type)) {
3688 _G.usefastretfie = 1; /* use shadow registers by default */
3690 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3691 if(!FUNC_ISSHADOWREGS(sym->type)) {
3692 /* do not save WREG,STATUS,BSR for high priority interrupts
3693 * because they are stored in the hardware shadow registers already */
3694 _G.usefastretfie = 0;
3695 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3696 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3697 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3700 /* these should really be optimized somehow, because not all
3701 * interrupt handlers modify them */
3702 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3703 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3704 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3705 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3707 // pic16_pBlockConvert2ISR(pb);
3711 /* emit code to setup stack frame if user enabled,
3712 * and function is not main() */
3714 //fprintf(stderr, "function name: %s\n", sym->name);
3715 if(strcmp(sym->name, "main")) {
3716 if(0 || !options.ommitFramePtr || sym->regsUsed) {
3717 /* setup the stack frame */
3718 if(STACK_MODEL_LARGE)
3719 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3720 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3722 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3723 if(STACK_MODEL_LARGE)
3724 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3728 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3731 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3733 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3734 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3736 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3739 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3740 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3747 /* if callee-save to be used for this function
3748 * then save the registers being used in this function */
3749 // if (IFFUNC_CALLEESAVES(sym->type))
3753 /* if any registers used */
3754 if (sym->regsUsed) {
3755 /* save the registers used */
3756 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3757 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3758 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3759 if (bitVectBitValue(sym->regsUsed,i)) {
3760 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3763 if(!pic16_regWithIdx(i)->wasUsed) {
3764 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3765 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3766 pic16_regWithIdx(i)->wasUsed = 1;
3770 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3774 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3775 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3778 /*-----------------------------------------------------------------*/
3779 /* genEndFunction - generates epilogue for functions */
3780 /*-----------------------------------------------------------------*/
3781 static void genEndFunction (iCode *ic)
3783 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3787 if(IFFUNC_ISNAKED(sym->type)) {
3788 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3794 /* add code for ISCRITICAL */
3795 if(IFFUNC_ISCRITICAL(sym->type)) {
3796 /* if critical function, turn on interrupts */
3798 /* TODO: add code here -- VR */
3801 // sym->regsUsed = _G.fregsUsed;
3803 /* now we need to restore the registers */
3804 /* if any registers used */
3805 if (sym->regsUsed) {
3808 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3809 /* restore registers used */
3810 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3811 for ( i = sym->regsUsed->size; i >= 0; i--) {
3812 if (bitVectBitValue(sym->regsUsed,i)) {
3813 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3817 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3821 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3823 if (sym->stack == 1) {
3824 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3825 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3827 // we have to add more than one...
3828 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3829 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3830 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3832 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3833 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3834 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3838 if(strcmp(sym->name, "main")) {
3839 if(0 || !options.ommitFramePtr || sym->regsUsed) {
3840 /* restore stack frame */
3841 if(STACK_MODEL_LARGE)
3842 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3843 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3849 if (IFFUNC_ISISR(sym->type)) {
3850 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3851 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3852 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3853 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3855 if(!FUNC_ISSHADOWREGS(sym->type)) {
3856 /* do not restore interrupt vector for WREG,STATUS,BSR
3857 * for high priority interrupt, see genFunction */
3858 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3859 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3860 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3862 // _G.interruptvector = 0; /* sanity check */
3865 /* if debug then send end of function */
3866 /* if (options.debug && currFunc) */
3868 debugFile->writeEndFunction (currFunc, ic, 1);
3871 if(_G.usefastretfie)
3872 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3874 pic16_emitpcodeNULLop(POC_RETFIE);
3876 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3878 _G.usefastretfie = 0;
3882 if (IFFUNC_ISCRITICAL(sym->type)) {
3883 pic16_emitcode("setb","ea");
3886 /* if debug then send end of function */
3888 debugFile->writeEndFunction (currFunc, ic, 1);
3891 /* insert code to restore stack frame, if user enabled it
3892 * and function is not main() */
3895 pic16_emitpcodeNULLop(POC_RETURN);
3897 /* Mark the end of a function */
3898 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3902 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3904 unsigned long lit=1;
3906 // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3907 if(AOP_TYPE(op) == AOP_LIT) {
3908 if(!IS_FLOAT(operandType( op ))) {
3909 lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3912 unsigned long lit_int;
3916 /* take care if literal is a float */
3917 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3924 pic16_emitpcode(POC_CLRF, dest);
3926 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
3927 if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
3930 if(dest->type == PO_WREG && (offset == 0)) {
3931 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3934 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3938 /*-----------------------------------------------------------------*/
3939 /* genRet - generate code for return statement */
3940 /*-----------------------------------------------------------------*/
3941 static void genRet (iCode *ic)
3947 /* if we have no return value then
3948 * just generate the "ret" */
3953 /* we have something to return then
3954 * move the return value into place */
3955 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3956 size = AOP_SIZE(IC_LEFT(ic));
3960 pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3961 // pic16_emitpcode(POC_MOVFF,
3962 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3965 pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3966 // pic16_emitpcode(POC_MOVFF,
3967 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3970 pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3971 // pic16_emitpcode(POC_MOVFF,
3972 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3975 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0)); // patch 12
3977 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg)); // patch 12
3978 // pic16_emitpcode(POC_MOVFF,
3979 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3982 /* >32-bits, setup stack and FSR0 */
3984 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3985 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3987 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3989 // popaopidx(AOP(oper), size, GpseudoStkPtr);
3994 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3995 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3997 if(STACK_MODEL_LARGE) {
3998 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3999 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4001 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4006 /* old code, left here for reference -- VR */
4010 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4012 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4013 pic16_emitpcomment("push %s",l);
4016 DEBUGpic16_emitcode(";", "%d", __LINE__);
4017 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4018 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
4020 if (strcmp(fReturn[offset],l)) {
4021 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4022 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4023 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4025 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4029 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4039 if (strcmp(fReturn[pushed],"a"))
4040 pic16_emitcode("pop",fReturn[pushed]);
4042 pic16_emitcode("pop","acc");
4048 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4051 /* generate a jump to the return label
4052 * if the next is not the return statement */
4053 if (!(ic->next && ic->next->op == LABEL
4054 && IC_LABEL(ic->next) == returnLabel)) {
4056 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4057 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4061 /*-----------------------------------------------------------------*/
4062 /* genLabel - generates a label */
4063 /*-----------------------------------------------------------------*/
4064 static void genLabel (iCode *ic)
4068 /* special case never generate */
4069 if (IC_LABEL(ic) == entryLabel)
4072 pic16_emitpLabel(IC_LABEL(ic)->key);
4073 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4076 /*-----------------------------------------------------------------*/
4077 /* genGoto - generates a goto */
4078 /*-----------------------------------------------------------------*/
4080 static void genGoto (iCode *ic)
4083 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4084 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4088 /*-----------------------------------------------------------------*/
4089 /* genMultbits :- multiplication of bits */
4090 /*-----------------------------------------------------------------*/
4091 static void genMultbits (operand *left,
4097 if(!pic16_sameRegs(AOP(result),AOP(right)))
4098 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
4100 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4101 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4102 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4107 /*-----------------------------------------------------------------*/
4108 /* genMultOneByte : 8 bit multiplication & division */
4109 /*-----------------------------------------------------------------*/
4110 static void genMultOneByte (operand *left,
4116 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4117 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4119 /* (if two literals, the value is computed before) */
4120 /* if one literal, literal on the right */
4121 if (AOP_TYPE(left) == AOP_LIT){
4127 /* size is already checked in genMult == 1 */
4128 // size = AOP_SIZE(result);
4130 if (AOP_TYPE(right) == AOP_LIT){
4131 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4132 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4133 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4134 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4136 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4137 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4138 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4139 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4142 pic16_genMult8X8_8 (left, right,result);
4145 /*-----------------------------------------------------------------*/
4146 /* genMultOneWord : 16 bit multiplication */
4147 /*-----------------------------------------------------------------*/
4148 static void genMultOneWord (operand *left,
4153 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4154 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4156 /* (if two literals, the value is computed before)
4157 * if one literal, literal on the right */
4158 if (AOP_TYPE(left) == AOP_LIT){
4164 /* size is checked already == 2 */
4165 // size = AOP_SIZE(result);
4167 if (AOP_TYPE(right) == AOP_LIT) {
4168 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4169 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4170 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4171 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4173 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4174 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4175 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4176 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4179 pic16_genMult16X16_16(left, right,result);
4182 /*-----------------------------------------------------------------*/
4183 /* genMultOneLong : 32 bit multiplication */
4184 /*-----------------------------------------------------------------*/
4185 static void genMultOneLong (operand *left,
4190 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4191 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4193 /* (if two literals, the value is computed before)
4194 * if one literal, literal on the right */
4195 if (AOP_TYPE(left) == AOP_LIT){
4201 /* size is checked already == 4 */
4202 // size = AOP_SIZE(result);
4204 if (AOP_TYPE(right) == AOP_LIT) {
4205 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4206 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4207 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4208 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4210 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4211 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4212 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4213 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4216 pic16_genMult32X32_32(left, right,result);
4221 /*-----------------------------------------------------------------*/
4222 /* genMult - generates code for multiplication */
4223 /*-----------------------------------------------------------------*/
4224 static void genMult (iCode *ic)
4226 operand *left = IC_LEFT(ic);
4227 operand *right = IC_RIGHT(ic);
4228 operand *result= IC_RESULT(ic);
4231 /* assign the amsops */
4232 pic16_aopOp (left,ic,FALSE);
4233 pic16_aopOp (right,ic,FALSE);
4234 pic16_aopOp (result,ic,TRUE);
4236 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4238 /* special cases first *
4240 if (AOP_TYPE(left) == AOP_CRY
4241 && AOP_TYPE(right)== AOP_CRY) {
4242 genMultbits(left,right,result);
4246 /* if both are of size == 1 */
4247 if(AOP_SIZE(left) == 1
4248 && AOP_SIZE(right) == 1) {
4249 genMultOneByte(left,right,result);
4253 /* if both are of size == 2 */
4254 if(AOP_SIZE(left) == 2
4255 && AOP_SIZE(right) == 2) {
4256 genMultOneWord(left, right, result);
4260 /* if both are of size == 4 */
4261 if(AOP_SIZE(left) == 4
4262 && AOP_SIZE(right) == 4) {
4263 genMultOneLong(left, right, result);
4267 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4270 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4271 /* should have been converted to function call */
4275 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4276 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4277 pic16_freeAsmop(result,NULL,ic,TRUE);
4280 /*-----------------------------------------------------------------*/
4281 /* genDivbits :- division of bits */
4282 /*-----------------------------------------------------------------*/
4283 static void genDivbits (operand *left,
4290 /* the result must be bit */
4291 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4292 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4296 pic16_emitcode("div","ab");
4297 pic16_emitcode("rrc","a");
4298 pic16_aopPut(AOP(result),"c",0);
4301 /*-----------------------------------------------------------------*/
4302 /* genDivOneByte : 8 bit division */
4303 /*-----------------------------------------------------------------*/
4304 static void genDivOneByte (operand *left,
4308 sym_link *opetype = operandType(result);
4313 /* result = divident / divisor
4314 * - divident may be a register or a literal,
4315 * - divisor may be a register or a literal,
4316 * so there are 3 cases (literal / literal is optimized
4317 * by the front-end) to handle.
4318 * In addition we must handle signed and unsigned, which
4319 * result in 6 final different cases -- VR */
4323 size = AOP_SIZE(result) - 1;
4325 /* signed or unsigned */
4326 if (SPEC_USIGN(opetype)) {
4327 pCodeOp *pct1, /* count */
4330 symbol *label1, *label2, *label3;;
4333 /* unsigned is easy */
4335 pct1 = pic16_popGetTempReg(1);
4336 pct2 = pic16_popGetTempReg(1);
4337 pct3 = pic16_popGetTempReg(1);
4339 label1 = newiTempLabel(NULL);
4340 label2 = newiTempLabel(NULL);
4341 label3 = newiTempLabel(NULL);
4343 /* the following algorithm is extracted from divuint.c */
4345 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4346 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4348 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4350 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4352 pic16_emitpLabel(label1->key);
4355 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4359 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4363 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4365 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4366 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4368 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4369 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4370 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4372 pic16_emitpLabel( label3->key );
4373 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4374 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4378 pic16_emitpLabel(label2->key);
4379 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4380 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4381 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4383 /* result is in wreg */
4384 if(AOP_TYPE(result) != AOP_ACC)
4385 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4387 pic16_popReleaseTempReg( pct3, 1);
4388 pic16_popReleaseTempReg( pct2, 1);
4389 pic16_popReleaseTempReg( pct1, 1);
4394 /* signed is a little bit more difficult */
4396 /* save the signs of the operands */
4397 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4399 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4400 pic16_emitcode("push","acc"); /* save it on the stack */
4402 /* now sign adjust for both left & right */
4403 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4405 lbl = newiTempLabel(NULL);
4406 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4407 pic16_emitcode("cpl","a");
4408 pic16_emitcode("inc","a");
4409 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4410 pic16_emitcode("mov","b,a");
4412 /* sign adjust left side */
4413 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4416 lbl = newiTempLabel(NULL);
4417 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4418 pic16_emitcode("cpl","a");
4419 pic16_emitcode("inc","a");
4420 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4422 /* now the division */
4423 pic16_emitcode("div","ab");
4424 /* we are interested in the lower order
4426 pic16_emitcode("mov","b,a");
4427 lbl = newiTempLabel(NULL);
4428 pic16_emitcode("pop","acc");
4429 /* if there was an over flow we don't
4430 adjust the sign of the result */
4431 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4432 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4434 pic16_emitcode("clr","a");
4435 pic16_emitcode("subb","a,b");
4436 pic16_emitcode("mov","b,a");
4437 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4439 /* now we are done */
4440 pic16_aopPut(AOP(result),"b",0);
4442 pic16_emitcode("mov","c,b.7");
4443 pic16_emitcode("subb","a,acc");
4446 pic16_aopPut(AOP(result),"a",offset++);
4450 /*-----------------------------------------------------------------*/
4451 /* genDiv - generates code for division */
4452 /*-----------------------------------------------------------------*/
4453 static void genDiv (iCode *ic)
4455 operand *left = IC_LEFT(ic);
4456 operand *right = IC_RIGHT(ic);
4457 operand *result= IC_RESULT(ic);
4460 /* Division is a very lengthy algorithm, so it is better
4461 * to call support routines than inlining algorithm.
4462 * Division functions written here just in case someone
4463 * wants to inline and not use the support libraries -- VR */
4467 /* assign the amsops */
4468 pic16_aopOp (left,ic,FALSE);
4469 pic16_aopOp (right,ic,FALSE);
4470 pic16_aopOp (result,ic,TRUE);
4472 /* special cases first */
4474 if (AOP_TYPE(left) == AOP_CRY &&
4475 AOP_TYPE(right)== AOP_CRY) {
4476 genDivbits(left,right,result);
4480 /* if both are of size == 1 */
4481 if (AOP_SIZE(left) == 1 &&
4482 AOP_SIZE(right) == 1 ) {
4483 genDivOneByte(left,right,result);
4487 /* should have been converted to function call */
4490 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4491 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4492 pic16_freeAsmop(result,NULL,ic,TRUE);
4495 /*-----------------------------------------------------------------*/
4496 /* genModbits :- modulus of bits */
4497 /*-----------------------------------------------------------------*/
4498 static void genModbits (operand *left,
4506 werror(W_POSSBUG2, __FILE__, __LINE__);
4507 /* the result must be bit */
4508 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4509 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4513 pic16_emitcode("div","ab");
4514 pic16_emitcode("mov","a,b");
4515 pic16_emitcode("rrc","a");
4516 pic16_aopPut(AOP(result),"c",0);
4519 /*-----------------------------------------------------------------*/
4520 /* genModOneByte : 8 bit modulus */
4521 /*-----------------------------------------------------------------*/
4522 static void genModOneByte (operand *left,
4526 sym_link *opetype = operandType(result);
4531 werror(W_POSSBUG2, __FILE__, __LINE__);
4533 /* signed or unsigned */
4534 if (SPEC_USIGN(opetype)) {
4535 /* unsigned is easy */
4536 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4537 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4539 pic16_emitcode("div","ab");
4540 pic16_aopPut(AOP(result),"b",0);
4544 /* signed is a little bit more difficult */
4546 /* save the signs of the operands */
4547 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4550 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4551 pic16_emitcode("push","acc"); /* save it on the stack */
4553 /* now sign adjust for both left & right */
4554 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4557 lbl = newiTempLabel(NULL);
4558 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4559 pic16_emitcode("cpl","a");
4560 pic16_emitcode("inc","a");
4561 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4562 pic16_emitcode("mov","b,a");
4564 /* sign adjust left side */
4565 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4568 lbl = newiTempLabel(NULL);
4569 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4570 pic16_emitcode("cpl","a");
4571 pic16_emitcode("inc","a");
4572 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4574 /* now the multiplication */
4575 pic16_emitcode("div","ab");
4576 /* we are interested in the lower order
4578 lbl = newiTempLabel(NULL);
4579 pic16_emitcode("pop","acc");
4580 /* if there was an over flow we don't
4581 adjust the sign of the result */
4582 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4583 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4585 pic16_emitcode("clr","a");
4586 pic16_emitcode("subb","a,b");
4587 pic16_emitcode("mov","b,a");
4588 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4590 /* now we are done */
4591 pic16_aopPut(AOP(result),"b",0);
4595 /*-----------------------------------------------------------------*/
4596 /* genMod - generates code for division */
4597 /*-----------------------------------------------------------------*/
4598 static void genMod (iCode *ic)
4600 operand *left = IC_LEFT(ic);
4601 operand *right = IC_RIGHT(ic);
4602 operand *result= IC_RESULT(ic);
4606 /* assign the amsops */
4607 pic16_aopOp (left,ic,FALSE);
4608 pic16_aopOp (right,ic,FALSE);
4609 pic16_aopOp (result,ic,TRUE);
4611 /* special cases first */
4613 if (AOP_TYPE(left) == AOP_CRY &&
4614 AOP_TYPE(right)== AOP_CRY) {
4615 genModbits(left,right,result);
4619 /* if both are of size == 1 */
4620 if (AOP_SIZE(left) == 1 &&
4621 AOP_SIZE(right) == 1 ) {
4622 genModOneByte(left,right,result);
4626 /* should have been converted to function call */
4630 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4631 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4632 pic16_freeAsmop(result,NULL,ic,TRUE);
4635 /*-----------------------------------------------------------------*/
4636 /* genIfxJump :- will create a jump depending on the ifx */
4637 /*-----------------------------------------------------------------*/
4639 note: May need to add parameter to indicate when a variable is in bit space.
4641 static void genIfxJump (iCode *ic, char *jval)
4645 /* if true label then we jump if condition
4647 if ( IC_TRUE(ic) ) {
4649 if(strcmp(jval,"a") == 0)
4651 else if (strcmp(jval,"c") == 0)
4654 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4655 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4658 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4659 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4663 /* false label is present */
4664 if(strcmp(jval,"a") == 0)
4666 else if (strcmp(jval,"c") == 0)
4669 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4670 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4673 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4674 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4679 /* mark the icode as generated */
4683 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4687 /* if true label then we jump if condition
4689 if ( IC_TRUE(ic) ) {
4690 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4691 pic16_emitpcode(POC_BTFSC, jop);
4693 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4694 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4697 /* false label is present */
4698 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4699 pic16_emitpcode(POC_BTFSS, jop);
4701 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4702 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4706 /* mark the icode as generated */
4713 /*-----------------------------------------------------------------*/
4715 /*-----------------------------------------------------------------*/
4716 static void genSkip(iCode *ifx,int status_bit)
4718 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4722 if ( IC_TRUE(ifx) ) {
4723 switch(status_bit) {
4738 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4739 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4743 switch(status_bit) {
4757 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4758 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4765 /*-----------------------------------------------------------------*/
4767 /*-----------------------------------------------------------------*/
4768 static void genSkipc(resolvedIfx *rifx)
4770 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4780 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4781 rifx->generated = 1;
4784 #if !(USE_SIMPLE_GENCMP)
4785 /*-----------------------------------------------------------------*/
4787 /*-----------------------------------------------------------------*/
4788 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4790 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4795 if( (rifx->condition ^ invert_condition) & 1)
4800 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4801 rifx->generated = 1;
4806 /*-----------------------------------------------------------------*/
4808 /*-----------------------------------------------------------------*/
4809 static void genSkipz(iCode *ifx, int condition)
4820 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4822 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4825 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4827 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4832 #if !(USE_SIMPLE_GENCMP)
4833 /*-----------------------------------------------------------------*/
4835 /*-----------------------------------------------------------------*/
4836 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4842 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4844 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4847 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4848 rifx->generated = 1;
4853 /*-----------------------------------------------------------------*/
4854 /* genChkZeroes :- greater or less than comparison */
4855 /* For each byte in a literal that is zero, inclusive or the */
4856 /* the corresponding byte in the operand with W */
4857 /* returns true if any of the bytes are zero */
4858 /*-----------------------------------------------------------------*/
4859 static int genChkZeroes(operand *op, int lit, int size)
4866 i = (lit >> (size*8)) & 0xff;
4870 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4872 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4881 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4882 #define DEBUGpc(fmt,...) DEBUGpic16_emitcode("; =:=", "%s:%s:%d: " fmt, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
4884 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
4885 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE || AOP_TYPE(x) == AOP_STA)
4887 /*-----------------------------------------------------------------*/
4888 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4889 /* aop (if it's NOT a literal) or from lit (if */
4890 /* aop is a literal) */
4891 /*-----------------------------------------------------------------*/
4892 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4893 if (aop->type == AOP_LIT) {
4894 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4896 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4900 /*-----------------------------------------------------------------*/
4901 /* genCmp :- greater or less than comparison */
4902 /*-----------------------------------------------------------------*/
4904 #if USE_SIMPLE_GENCMP
4906 /* genCmp performs a left < right comparison, stores
4907 * the outcome in result (if != NULL) and generates
4908 * control flow code for the ifx (if != NULL).
4910 * This version leaves in sequences like
4911 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4912 * which should be optmized by the peephole
4913 * optimizer - RN 2005-01-01 */
4914 static void genCmp (operand *left,operand *right,
4915 operand *result, iCode *ifx, int sign)
4928 assert (AOP_SIZE(left) == AOP_SIZE(right));
4929 assert (left && right);
4931 size = AOP_SIZE(right) - 1;
4932 mask = (0x100UL << (size*8)) - 1;
4933 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4938 resolveIfx (&rIfx, ifx);
4940 /**********************************************************************
4941 * handle bits - bit compares are promoted to int compares seemingly! *
4942 **********************************************************************/
4944 // THIS IS COMPLETELY UNTESTED!
4945 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4946 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4947 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4948 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4951 // 1 < {0,1} is false --> clear C by skipping the next instruction
4952 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4953 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4954 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4955 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4956 emitCLRC; // only skipped for left=0 && right=1
4958 goto correct_result_in_carry;
4962 /*************************************************
4963 * make sure that left is register (or the like) *
4964 *************************************************/
4965 if (!isAOP_REGlike(left)) {
4966 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4967 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4969 assert (isAOP_LIT(left));
4970 assert (isAOP_REGlike(right));
4971 // swap left and right
4972 // left < right <==> right > left <==> (right >= left + 1)
4973 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4975 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4976 // MAXVALUE < right? always false
4977 if (performedLt) emitCLRC; else emitSETC;
4978 goto correct_result_in_carry;
4981 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4982 // that's we handled it above.
4989 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1"
4990 } else if (isAOP_LIT(right)) {
4991 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4994 assert (isAOP_REGlike(left)); // left must be register or the like
4995 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4997 /*************************************************
4998 * special cases go here *
4999 *************************************************/
5001 if (isAOP_LIT(right)) {
5003 // unsigned comparison to a literal
5004 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
5005 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5008 // unsigned left < 0? always false
5009 if (performedLt) emitCLRC; else emitSETC;
5010 goto correct_result_in_carry;
5013 // signed comparison to a literal
5014 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
5015 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5017 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5018 // signed left < 0x80000000? always false
5019 if (performedLt) emitCLRC; else emitSETC;
5020 goto correct_result_in_carry;
5021 } else if (lit == 0) {
5022 // compare left < 0; set CARRY if SIGNBIT(left) is set
5023 if (performedLt) emitSETC; else emitCLRC;
5024 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5025 if (performedLt) emitCLRC; else emitSETC;
5026 goto correct_result_in_carry;
5029 } // right is literal
5031 /*************************************************
5032 * perform a general case comparison *
5033 * make sure we get CARRY==1 <==> left >= right *
5034 *************************************************/
5035 // compare most significant bytes
5036 //DEBUGpc ("comparing bytes at offset %d", size);
5038 // unsigned comparison
5039 mov2w_regOrLit (AOP(right), lit, size);
5040 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5042 // signed comparison
5043 // (add 2^n to both operands then perform an unsigned comparison)
5044 if (isAOP_LIT(right)) {
5045 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5046 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5048 if (litbyte == 0x80) {
5049 // left >= 0x80 -- always true, but more bytes to come
5050 pic16_mov2w (AOP(left), size);
5051 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5054 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5055 pic16_mov2w (AOP(left), size);
5056 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5057 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5060 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5061 //pCodeOp *pctemp = pic16_popGetTempReg(1);
5062 pic16_mov2w (AOP(left), size);
5063 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5064 pic16_emitpcode (POC_MOVWF, pctemp);
5065 pic16_mov2w (AOP(right), size);
5066 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5067 pic16_emitpcode (POC_SUBFW, pctemp);
5068 //pic16_popReleaseTempReg(pctemp, 1);
5072 // compare remaining bytes (treat as unsigned case from above)
5073 templbl = newiTempLabel ( NULL );
5076 //DEBUGpc ("comparing bytes at offset %d", offs);
5077 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5078 mov2w_regOrLit (AOP(right), lit, offs);
5079 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5081 pic16_emitpLabel (templbl->key);
5082 goto result_in_carry;
5086 /****************************************************
5087 * now CARRY contains the result of the comparison: *
5088 * SUBWF sets CARRY iff *
5089 * F-W >= 0 <==> F >= W <==> !(F < W) *
5091 ****************************************************/
5094 if (result && AOP_TYPE(result) != AOP_CRY) {
5095 // value will be stored
5098 // value wil only be used in the following genSkipc()
5099 rIfx.condition ^= 1;
5103 correct_result_in_carry:
5105 // assign result to variable (if neccessary)
5106 if (result && AOP_TYPE(result) != AOP_CRY) {
5107 //DEBUGpc ("assign result");
5108 size = AOP_SIZE(result);
5110 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5112 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5115 // perform conditional jump
5116 // genSkipc branches to rifx->label if (rifx->condition != CARRY)
5118 //DEBUGpc ("generate control flow");
5119 rIfx.condition ^= 1;
5128 static void genCmp (operand *left,operand *right,
5129 operand *result, iCode *ifx, int sign)
5131 int size; //, offset = 0 ;
5132 unsigned long lit = 0L,i = 0;
5133 resolvedIfx rFalseIfx;
5134 // resolvedIfx rTrueIfx;
5136 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5139 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5140 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5146 resolveIfx(&rFalseIfx,ifx);
5147 truelbl = newiTempLabel(NULL);
5148 size = max(AOP_SIZE(left),AOP_SIZE(right));
5150 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5154 /* if literal is on the right then swap with left */
5155 if ((AOP_TYPE(right) == AOP_LIT)) {
5156 operand *tmp = right ;
5157 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5158 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5161 lit = (lit - 1) & mask;
5164 rFalseIfx.condition ^= 1;
5167 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5168 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5172 //if(IC_TRUE(ifx) == NULL)
5173 /* if left & right are bit variables */
5174 if (AOP_TYPE(left) == AOP_CRY &&
5175 AOP_TYPE(right) == AOP_CRY ) {
5176 assert (0 && "bit variables used in genCmp");
5177 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5178 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5180 /* subtract right from left if at the
5181 end the carry flag is set then we know that
5182 left is greater than right */
5184 symbol *lbl = newiTempLabel(NULL);
5187 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5188 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5192 if(AOP_TYPE(right) == AOP_LIT) {
5194 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5196 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5203 genSkipCond(&rFalseIfx,left,size-1,7);
5205 /* no need to compare to 0...*/
5206 /* NOTE: this is a de-generate compare that most certainly
5207 * creates some dead code. */
5208 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5210 if(ifx) ifx->generated = 1;
5217 //i = (lit >> (size*8)) & 0xff;
5218 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5220 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5222 i = ((0-lit) & 0xff);
5225 /* lit is 0x7f, all signed chars are less than
5226 * this except for 0x7f itself */
5227 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5228 genSkipz2(&rFalseIfx,0);
5230 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5231 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5232 genSkipc(&rFalseIfx);
5237 genSkipz2(&rFalseIfx,1);
5239 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5240 genSkipc(&rFalseIfx);
5244 if(ifx) ifx->generated = 1;
5248 /* chars are out of the way. now do ints and longs */
5251 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5258 genSkipCond(&rFalseIfx,left,size,7);
5259 if(ifx) ifx->generated = 1;
5264 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5266 //rFalseIfx.condition ^= 1;
5267 //genSkipCond(&rFalseIfx,left,size,7);
5268 //rFalseIfx.condition ^= 1;
5270 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5271 if(rFalseIfx.condition)
5272 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5274 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5276 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5277 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5278 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5281 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5283 if(rFalseIfx.condition) {
5285 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5291 genSkipc(&rFalseIfx);
5292 pic16_emitpLabel(truelbl->key);
5293 if(ifx) ifx->generated = 1;
5300 if( (lit & 0xff) == 0) {
5301 /* lower byte is zero */
5302 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5303 i = ((lit >> 8) & 0xff) ^0x80;
5304 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5305 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5306 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5307 genSkipc(&rFalseIfx);
5310 if(ifx) ifx->generated = 1;
5315 /* Special cases for signed longs */
5316 if( (lit & 0xffffff) == 0) {
5317 /* lower byte is zero */
5318 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5319 i = ((lit >> 8*3) & 0xff) ^0x80;
5320 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5321 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5322 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5323 genSkipc(&rFalseIfx);
5326 if(ifx) ifx->generated = 1;
5334 if(lit & (0x80 << (size*8))) {
5335 /* lit is negative */
5336 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5338 //genSkipCond(&rFalseIfx,left,size,7);
5340 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5342 if(rFalseIfx.condition)
5343 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5345 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5349 /* lit is positive */
5350 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5351 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5352 if(rFalseIfx.condition)
5353 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5355 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5360 This works, but is only good for ints.
5361 It also requires a "known zero" register.
5362 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5363 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5364 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5365 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5366 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5367 genSkipc(&rFalseIfx);
5369 pic16_emitpLabel(truelbl->key);
5370 if(ifx) ifx->generated = 1;
5374 /* There are no more special cases, so perform a general compare */
5376 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5377 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5381 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5383 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5385 //rFalseIfx.condition ^= 1;
5386 genSkipc(&rFalseIfx);
5388 pic16_emitpLabel(truelbl->key);
5390 if(ifx) ifx->generated = 1;
5397 /* sign is out of the way. So now do an unsigned compare */
5398 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5401 /* General case - compare to an unsigned literal on the right.*/
5403 i = (lit >> (size*8)) & 0xff;
5404 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5405 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5407 i = (lit >> (size*8)) & 0xff;
5410 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5412 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5414 /* this byte of the lit is zero,
5415 *if it's not the last then OR in the variable */
5417 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5422 pic16_emitpLabel(lbl->key);
5423 // pic16_emitpLabel(truelbl->key);
5424 //if(emitFinalCheck)
5425 genSkipc(&rFalseIfx);
5427 pic16_emitpLabel(truelbl->key);
5429 if(ifx) ifx->generated = 1;
5436 if(AOP_TYPE(left) == AOP_LIT) {
5437 //symbol *lbl = newiTempLabel(NULL);
5439 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5442 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5445 if((lit == 0) && (sign == 0)){
5448 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5450 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5452 genSkipz2(&rFalseIfx,0);
5453 if(ifx) ifx->generated = 1;
5460 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5461 /* degenerate compare can never be true */
5462 if(rFalseIfx.condition == 0)
5463 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5465 if(ifx) ifx->generated = 1;
5470 /* signed comparisons to a literal byte */
5472 int lp1 = (lit+1) & 0xff;
5474 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5477 rFalseIfx.condition ^= 1;
5478 genSkipCond(&rFalseIfx,right,0,7);
5481 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5482 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5483 genSkipz2(&rFalseIfx,1);
5486 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5487 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5488 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5489 rFalseIfx.condition ^= 1;
5490 genSkipc(&rFalseIfx);
5494 /* unsigned comparisons to a literal byte */
5496 switch(lit & 0xff ) {
5498 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5499 genSkipz2(&rFalseIfx,0);
5502 rFalseIfx.condition ^= 1;
5503 genSkipCond(&rFalseIfx,right,0,7);
5507 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5508 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5509 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5510 rFalseIfx.condition ^= 1;
5511 if (AOP_TYPE(result) == AOP_CRY)
5512 genSkipc(&rFalseIfx);
5514 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5515 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5521 if(ifx) ifx->generated = 1;
5522 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5528 /* Size is greater than 1 */
5536 /* this means lit = 0xffffffff, or -1 */
5539 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5540 rFalseIfx.condition ^= 1;
5541 genSkipCond(&rFalseIfx,right,size,7);
5542 if(ifx) ifx->generated = 1;
5544 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5553 if(rFalseIfx.condition) {
5554 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5555 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5558 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5560 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5564 if(rFalseIfx.condition) {
5565 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5566 pic16_emitpLabel(truelbl->key);
5568 rFalseIfx.condition ^= 1;
5569 genSkipCond(&rFalseIfx,right,s,7);
5572 if(ifx) ifx->generated = 1;
5574 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5580 if((size == 1) && (0 == (lp1&0xff))) {
5581 /* lower byte of signed word is zero */
5582 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5583 i = ((lp1 >> 8) & 0xff) ^0x80;
5584 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5585 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5586 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5588 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5590 if(ifx) ifx->generated = 1;
5593 rFalseIfx.condition ^= 1;
5594 genSkipc(&rFalseIfx);
5595 if(ifx) ifx->generated = 1;
5601 if(lit & (0x80 << (size*8))) {
5602 /* Lit is less than zero */
5603 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5604 //rFalseIfx.condition ^= 1;
5605 //genSkipCond(&rFalseIfx,left,size,7);
5606 //rFalseIfx.condition ^= 1;
5607 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5608 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5610 if(rFalseIfx.condition)
5611 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5613 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5617 /* Lit is greater than or equal to zero */
5618 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5619 //rFalseIfx.condition ^= 1;
5620 //genSkipCond(&rFalseIfx,right,size,7);
5621 //rFalseIfx.condition ^= 1;
5623 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5624 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5626 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5627 if(rFalseIfx.condition)
5628 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5630 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5634 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5635 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5639 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5641 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5643 rFalseIfx.condition ^= 1;
5644 //rFalseIfx.condition = 1;
5645 genSkipc(&rFalseIfx);
5647 pic16_emitpLabel(truelbl->key);
5649 if(ifx) ifx->generated = 1;
5652 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5659 /* compare word or long to an unsigned literal on the right.*/
5664 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5667 break; /* handled above */
5670 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5672 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5673 genSkipz2(&rFalseIfx,0);
5677 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5679 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5682 if(rFalseIfx.condition)
5683 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5685 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5688 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5689 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5691 rFalseIfx.condition ^= 1;
5692 genSkipc(&rFalseIfx);
5695 pic16_emitpLabel(truelbl->key);
5697 if(ifx) ifx->generated = 1;
5699 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5707 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5708 i = (lit >> (size*8)) & 0xff;
5710 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5711 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5714 i = (lit >> (size*8)) & 0xff;
5717 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5719 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5721 /* this byte of the lit is zero,
5722 * if it's not the last then OR in the variable */
5724 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5729 pic16_emitpLabel(lbl->key);
5731 rFalseIfx.condition ^= 1;
5733 genSkipc(&rFalseIfx);
5737 pic16_emitpLabel(truelbl->key);
5738 if(ifx) ifx->generated = 1;
5740 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5746 /* Compare two variables */
5748 DEBUGpic16_emitcode(";sign","%d",sign);
5752 /* Sigh. thus sucks... */
5756 pctemp = pic16_popGetTempReg(1);
5757 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5758 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5759 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5760 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5761 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5762 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5763 pic16_popReleaseTempReg(pctemp, 1);
5765 /* Signed char comparison */
5766 /* Special thanks to Nikolai Golovchenko for this snippet */
5767 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5768 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5769 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5770 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5771 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5772 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5774 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5775 genSkipc(&rFalseIfx);
5777 if(ifx) ifx->generated = 1;
5779 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5787 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5788 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5792 /* The rest of the bytes of a multi-byte compare */
5796 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5799 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5800 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5805 pic16_emitpLabel(lbl->key);
5807 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5808 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5809 (AOP_TYPE(result) == AOP_REG)) {
5810 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5811 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5813 genSkipc(&rFalseIfx);
5815 //genSkipc(&rFalseIfx);
5816 if(ifx) ifx->generated = 1;
5819 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5827 if ((AOP_TYPE(result) != AOP_CRY)
5828 && AOP_SIZE(result)) {
5829 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5831 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5833 pic16_outBitC(result);
5835 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5836 /* if the result is used in the next
5837 ifx conditional branch then generate
5838 code a little differently */
5840 genIfxJump (ifx,"c");
5842 pic16_outBitC(result);
5843 /* leave the result in acc */
5848 #else /* old version of genCmp() */ /* } else { */
5850 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5851 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5852 operand *result, int offset, int invert_op)
5856 /* check condition, > or < ?? */
5857 if(rIfx->condition != 0)invert_op ^= 1;
5859 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5861 if(!ifx)invert_op ^= 1;
5863 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5864 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5867 if(!invert_op)return POC_CPFSGT;
5868 else return POC_CPFSLT;
5871 static int compareAopfirstpass=1;
5873 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5874 operand *oper, int offset, operand *result,
5875 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5881 /* invert if there is a result to be loaded, in order to fit,
5882 * SETC/CLRC sequence */
5883 if(AOP_SIZE(result))invert_op ^= 1;
5885 // if(sign && !offset)invert_op ^= 1;
5887 // if(sign)invert_op ^= 1;
5889 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5891 if(AOP_SIZE(result) && compareAopfirstpass) {
5894 pic16_emitpcode(POC_SETF, pcop2);
5899 pic16_emitpcode(POC_CLRF, pcop2);
5905 compareAopfirstpass = 0;
5907 /* there is a bug when comparing operands with size > 1,
5908 * because higher bytes can be equal and test should be performed
5909 * to the next lower byte, current algorithm, considers operands
5910 * inequal in these cases! -- VR 20041107 */
5914 pic16_emitpcode(op, pcop);
5916 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5919 if((!sign || !offset) && AOP_SIZE(result)) {
5922 pic16_emitpcode(POC_CLRF, pcop2);
5927 pic16_emitpcode(POC_SETF, pcop2);
5932 /* don't emit final branch (offset == 0) */
5936 pic16_emitpcode(POC_RRCF, pcop2);
5938 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5941 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5942 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5943 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5945 truelbl = newiTempLabel( NULL );
5946 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5947 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5948 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5950 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5951 pic16_emitpLabel(truelbl->key);
5953 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5962 static void genCmp (operand *left, operand *right,
5963 operand *result, iCode *ifx, int sign)
5967 resolvedIfx rFalseIfx;
5968 symbol *falselbl, *tlbl;
5972 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5974 resolveIfx(&rFalseIfx, ifx);
5975 size = max(AOP_SIZE(left), AOP_SIZE(right));
5977 /* if left & right are bit variables */
5978 if(AOP_TYPE(left) == AOP_CRY
5979 && AOP_TYPE(right) == AOP_CRY ) {
5981 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5982 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5984 werror(W_POSSBUG2, __FILE__, __LINE__);
5988 /* if literal is on the right then swap with left */
5989 if((AOP_TYPE(right) == AOP_LIT)) {
5990 operand *tmp = right ;
5991 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
5993 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5995 // lit = (lit - 1) & mask;
5998 rFalseIfx.condition ^= 1; /* reverse compare */
6000 if ((AOP_TYPE(left) == AOP_LIT)) {
6001 /* float compares are handled by support functions */
6002 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6005 /* actual comparing algorithm */
6006 // size = AOP_SIZE( right );
6008 falselbl = newiTempLabel( NULL );
6009 if(AOP_TYPE(left) == AOP_LIT) {
6010 /* compare to literal */
6011 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6014 pCodeOp *pct, *pct2;
6017 /* signed compare */
6018 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6020 pct = pic16_popCopyReg(&pic16_pc_prodl);
6021 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6022 tlbl = newiTempLabel( NULL );
6024 /* first compare signs:
6025 * a. if both are positive, compare just like unsigned
6026 * b. if both are negative, invert cmpop, compare just like unsigned
6027 * c. if different signs, determine the result directly */
6033 tlbl1 = newiTempLabel( NULL );
6034 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
6038 /* literal is zero or positive:
6039 * a. if carry is zero, too, continue compare,
6040 * b. if carry is set, then continue depending on cmpop ^ condition:
6041 * 1. '<' return false (literal < variable),
6042 * 2. '>' return true (literal > variable) */
6043 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6044 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6047 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6048 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6052 /* literal is negative:
6053 * a. if carry is set, too, continue compare,
6054 * b. if carry is zero, then continue depending on cmpop ^ condition:
6055 * 1. '<' return true (literal < variable),
6056 * 2. '>' return false (literal > variable) */
6057 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6058 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6060 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6061 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6066 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6068 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6069 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6074 pic16_emitpLabel( tlbl1->key );
6077 compareAopfirstpass=1;
6078 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6079 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6080 // pic16_emitpcode(POC_MOVWF, pct);
6082 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6083 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6084 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6085 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6089 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6090 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6091 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6092 // pic16_emitpcode(POC_MOVWF, pct);
6094 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6095 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6096 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6097 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6098 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6102 if(ifx)ifx->generated = 1;
6104 if(AOP_SIZE(result)) {
6105 pic16_emitpLabel(tlbl->key);
6106 pic16_emitpLabel(falselbl->key);
6107 pic16_outBitOp( result, pct2 );
6109 pic16_emitpLabel(tlbl->key);
6114 /* unsigned compare */
6115 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6117 compareAopfirstpass=1;
6120 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6121 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6125 if(ifx)ifx->generated = 1;
6128 if(AOP_SIZE(result)) {
6129 pic16_emitpLabel(falselbl->key);
6130 pic16_outBitC( result );
6135 /* compare registers */
6136 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6140 pCodeOp *pct, *pct2;
6142 /* signed compare */
6143 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6145 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6146 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6147 tlbl = newiTempLabel( NULL );
6149 compareAopfirstpass=1;
6152 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6153 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6154 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6155 pic16_emitpcode(POC_MOVWF, pct);
6157 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6158 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6159 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6161 /* WREG already holds left + 0x80 */
6162 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6165 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6166 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6167 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6168 pic16_emitpcode(POC_MOVWF, pct);
6170 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6171 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6172 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6174 /* WREG already holds left + 0x80 */
6175 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6176 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6179 if(ifx)ifx->generated = 1;
6181 if(AOP_SIZE(result)) {
6182 pic16_emitpLabel(tlbl->key);
6183 pic16_emitpLabel(falselbl->key);
6184 pic16_outBitOp( result, pct2 );
6186 pic16_emitpLabel(tlbl->key);
6190 /* unsigned compare */
6191 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6193 compareAopfirstpass=1;
6196 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6197 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6201 if(ifx)ifx->generated = 1;
6202 if(AOP_SIZE(result)) {
6204 pic16_emitpLabel(falselbl->key);
6205 pic16_outBitC( result );
6212 #else /* } else { */
6214 /* new version of genCmp -- VR 20041012 */
6215 static void genCmp (operand *left,operand *right,
6216 operand *result, iCode *ifx, int sign)
6218 int size; //, offset = 0 ;
6219 unsigned long lit = 0L,i = 0;
6220 resolvedIfx rFalseIfx;
6221 int willCheckCarry=0;
6222 // resolvedIfx rTrueIfx;
6228 * subtract right from left if at the end the carry flag is set then we
6229 * know that left is greater than right */
6231 resolveIfx(&rFalseIfx,ifx);
6232 truelbl = newiTempLabel(NULL);
6233 size = max(AOP_SIZE(left),AOP_SIZE(right));
6235 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6237 /* POC_CPFSGT compare f, wreg, skip if f greater than wreg
6238 * POC_CPFSLT compare f, wreg, skip if f less then wreg */
6241 /* if literal is on the right then swap with left */
6242 if ((AOP_TYPE(right) == AOP_LIT)) {
6243 operand *tmp = right ;
6244 unsigned long mask = (0x100 << (8*(size-1))) - 1;
6246 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6248 // lit = (lit - 1) & mask;
6251 rFalseIfx.condition ^= 1; /* reverse compare */
6253 if ((AOP_TYPE(left) == AOP_LIT)) {
6254 /* float compares are handled by support functions */
6255 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
6259 //if(IC_TRUE(ifx) == NULL)
6260 /* if left & right are bit variables */
6261 if (AOP_TYPE(left) == AOP_CRY &&
6262 AOP_TYPE(right) == AOP_CRY ) {
6264 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6265 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6268 symbol *lbl = newiTempLabel(NULL);
6270 if(AOP_TYPE(left) == AOP_LIT) {
6271 DEBUGpic16_emitcode(";left lit","lit = 0x%x, sign=%d",lit,sign);
6273 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6275 else willCheckCarry = 0;
6278 if((lit == 0) && (sign == 0)) {
6279 /* unsigned compare to 0 */
6280 DEBUGpic16_emitcode("; unsigned compare to 0","lit = 0x%x, sign=%d",lit,sign);
6283 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6285 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
6287 genSkipz2(&rFalseIfx,0);
6288 if(ifx)ifx->generated = 1;
6295 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
6296 /* degenerate compare can never be true */
6297 if(rFalseIfx.condition == 0)
6298 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
6300 if(ifx) ifx->generated = 1;
6305 /* signed comparisons to a literal byte */
6306 DEBUGpic16_emitcode(";signed compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6308 int lp1 = (lit+1) & 0xff;
6310 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x condition = %d lp1 = %i",__LINE__,lit, rFalseIfx.condition, lp1);
6313 rFalseIfx.condition ^= 1;
6314 genSkipCond(&rFalseIfx,right,0,7);
6317 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6318 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
6319 genSkipz2(&rFalseIfx,1);
6322 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit ));
6324 if(rFalseIfx.condition)
6325 pic16_emitpcode(POC_CPFSLT, pic16_popGet(AOP(right), 0));
6327 pic16_emitpcode(POC_CPFSGT, pic16_popGet(AOP(right), 0));
6329 if(willCheckCarry) {
6330 if(!rFalseIfx.condition) { emitCLRC; emitSETC; }
6331 else { emitSETC; emitCLRC; }
6334 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6337 /* pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6338 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6339 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
6340 rFalseIfx.condition ^= 1;
6341 genSkipc(&rFalseIfx);
6346 /* unsigned comparisons to a literal byte */
6347 DEBUGpic16_emitcode("; unsigned compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6349 switch(lit & 0xff ) {
6352 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6353 genSkipz2(&rFalseIfx,0);
6356 rFalseIfx.condition ^= 1;
6357 genSkipCond(&rFalseIfx,right,0,7);
6360 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
6361 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6362 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6363 rFalseIfx.condition ^= 1;
6364 if (AOP_TYPE(result) == AOP_CRY)
6365 genSkipc(&rFalseIfx);
6367 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6368 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6374 if(ifx) ifx->generated = 1;
6375 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6381 /* Size is greater than 1 */
6389 /* this means lit = 0xffffffff, or -1 */
6392 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
6393 rFalseIfx.condition ^= 1;
6394 genSkipCond(&rFalseIfx,right,size,7);
6395 if(ifx) ifx->generated = 1;
6402 if(rFalseIfx.condition) {
6403 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6404 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6407 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6409 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6413 if(rFalseIfx.condition) {
6414 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6415 pic16_emitpLabel(truelbl->key);
6417 rFalseIfx.condition ^= 1;
6418 genSkipCond(&rFalseIfx,right,s,7);
6421 if(ifx) ifx->generated = 1;
6425 if((size == 1) && (0 == (lp1&0xff))) {
6426 /* lower byte of signed word is zero */
6427 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
6428 i = ((lp1 >> 8) & 0xff) ^0x80;
6429 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6430 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
6431 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
6432 rFalseIfx.condition ^= 1;
6433 genSkipc(&rFalseIfx);
6436 if(ifx) ifx->generated = 1;
6440 if(lit & (0x80 << (size*8))) {
6441 /* Lit is less than zero */
6442 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
6443 //rFalseIfx.condition ^= 1;
6444 //genSkipCond(&rFalseIfx,left,size,7);
6445 //rFalseIfx.condition ^= 1;
6446 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6447 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6449 if(rFalseIfx.condition)
6450 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6452 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6456 /* Lit is greater than or equal to zero */
6457 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
6458 //rFalseIfx.condition ^= 1;
6459 //genSkipCond(&rFalseIfx,right,size,7);
6460 //rFalseIfx.condition ^= 1;
6462 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
6463 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6465 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6466 if(rFalseIfx.condition)
6467 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6469 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6474 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6475 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6479 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6481 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6483 rFalseIfx.condition ^= 1;
6484 //rFalseIfx.condition = 1;
6485 genSkipc(&rFalseIfx);
6487 pic16_emitpLabel(truelbl->key);
6489 if(ifx) ifx->generated = 1;
6494 /* compare word or long to an unsigned literal on the right.*/
6499 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
6502 break; /* handled above */
6505 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6507 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6508 genSkipz2(&rFalseIfx,0);
6512 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6514 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6517 if(rFalseIfx.condition)
6518 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6520 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6523 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6524 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6526 rFalseIfx.condition ^= 1;
6527 genSkipc(&rFalseIfx);
6530 pic16_emitpLabel(truelbl->key);
6532 if(ifx) ifx->generated = 1;
6538 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6539 i = (lit >> (size*8)) & 0xff;
6541 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6542 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6545 i = (lit >> (size*8)) & 0xff;
6548 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6550 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6552 /* this byte of the lit is zero,
6553 * if it's not the last then OR in the variable */
6555 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6560 pic16_emitpLabel(lbl->key);
6562 rFalseIfx.condition ^= 1;
6564 genSkipc(&rFalseIfx);
6568 pic16_emitpLabel(truelbl->key);
6569 if(ifx) ifx->generated = 1;
6573 /* Compare two variables */
6575 DEBUGpic16_emitcode(";sign","%d",sign);
6579 /* Sigh. thus sucks... */
6583 pctemp = pic16_popGetTempReg(1);
6584 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6585 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
6586 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6587 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6588 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6589 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6590 pic16_popReleaseTempReg(pctemp, 1);
6592 /* Signed char comparison */
6593 /* Special thanks to Nikolai Golovchenko for this snippet */
6594 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6595 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6596 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
6597 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6598 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6599 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6601 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6602 genSkipc(&rFalseIfx);
6604 if(ifx) ifx->generated = 1;
6610 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6611 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6615 /* The rest of the bytes of a multi-byte compare */
6619 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
6622 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6623 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6628 pic16_emitpLabel(lbl->key);
6630 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6631 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
6632 (AOP_TYPE(result) == AOP_REG)) {
6633 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6634 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6636 genSkipc(&rFalseIfx);
6638 //genSkipc(&rFalseIfx);
6639 if(ifx) ifx->generated = 1;
6646 if ((AOP_TYPE(result) != AOP_CRY)
6647 && AOP_SIZE(result)) {
6648 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6650 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6652 pic16_outBitC(result);
6654 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6655 /* if the result is used in the next
6656 ifx conditional branch then generate
6657 code a little differently */
6659 genIfxJump (ifx,"c");
6661 pic16_outBitC(result);
6662 /* leave the result in acc */
6673 /*-----------------------------------------------------------------*/
6674 /* genCmpGt :- greater than comparison */
6675 /*-----------------------------------------------------------------*/
6676 static void genCmpGt (iCode *ic, iCode *ifx)
6678 operand *left, *right, *result;
6679 sym_link *letype , *retype;
6685 right= IC_RIGHT(ic);
6686 result = IC_RESULT(ic);
6688 letype = getSpec(operandType(left));
6689 retype =getSpec(operandType(right));
6690 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6691 /* assign the amsops */
6692 pic16_aopOp (left,ic,FALSE);
6693 pic16_aopOp (right,ic,FALSE);
6694 pic16_aopOp (result,ic,TRUE);
6696 genCmp(right, left, result, ifx, sign);
6698 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6699 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6700 pic16_freeAsmop(result,NULL,ic,TRUE);
6703 /*-----------------------------------------------------------------*/
6704 /* genCmpLt - less than comparisons */
6705 /*-----------------------------------------------------------------*/
6706 static void genCmpLt (iCode *ic, iCode *ifx)
6708 operand *left, *right, *result;
6709 sym_link *letype , *retype;
6715 right= IC_RIGHT(ic);
6716 result = IC_RESULT(ic);
6718 letype = getSpec(operandType(left));
6719 retype =getSpec(operandType(right));
6720 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6722 /* assign the amsops */
6723 pic16_aopOp (left,ic,FALSE);
6724 pic16_aopOp (right,ic,FALSE);
6725 pic16_aopOp (result,ic,TRUE);
6727 genCmp(left, right, result, ifx, sign);
6729 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6730 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6731 pic16_freeAsmop(result,NULL,ic,TRUE);
6736 // FIXME reenable literal optimisation when the pic16 port is stable
6738 /*-----------------------------------------------------------------*/
6739 /* genc16bit2lit - compare a 16 bit value to a literal */
6740 /*-----------------------------------------------------------------*/
6741 static void genc16bit2lit(operand *op, int lit, int offset)
6745 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6746 if( (lit&0xff) == 0)
6751 switch( BYTEofLONG(lit,i)) {
6753 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6756 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6759 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6762 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6763 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6768 switch( BYTEofLONG(lit,i)) {
6770 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6774 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6778 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6781 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6783 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6792 /*-----------------------------------------------------------------*/
6793 /* gencjneshort - compare and jump if not equal */
6794 /*-----------------------------------------------------------------*/
6795 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6797 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6799 int res_offset = 0; /* the result may be a different size then left or right */
6800 int res_size = AOP_SIZE(result);
6802 symbol *lbl, *lbl_done;
6804 unsigned long lit = 0L;
6805 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6807 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6808 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6810 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6811 resolveIfx(&rIfx,ifx);
6812 lbl = newiTempLabel(NULL);
6813 lbl_done = newiTempLabel(NULL);
6816 /* if the left side is a literal or
6817 if the right is in a pointer register and left
6819 if ((AOP_TYPE(left) == AOP_LIT) ||
6820 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6825 if(AOP_TYPE(right) == AOP_LIT)
6826 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6828 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6829 preserve_result = 1;
6831 if(result && !preserve_result)
6834 for(i = 0; i < AOP_SIZE(result); i++)
6835 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6839 /* if the right side is a literal then anything goes */
6840 if (AOP_TYPE(right) == AOP_LIT &&
6841 AOP_TYPE(left) != AOP_DIR ) {
6844 genc16bit2lit(left, lit, 0);
6846 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6849 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6852 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6853 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6855 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6859 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6861 if(res_offset < res_size-1)
6869 /* if the right side is in a register or in direct space or
6870 if the left is a pointer register & right is not */
6871 else if (AOP_TYPE(right) == AOP_REG ||
6872 AOP_TYPE(right) == AOP_DIR ||
6873 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6874 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6875 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6876 int lbl_key = lbl->key;
6879 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6880 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6882 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6883 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6884 __FUNCTION__,__LINE__);
6888 /* switch(size) { */
6890 /* genc16bit2lit(left, lit, 0); */
6892 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6897 if((AOP_TYPE(left) == AOP_DIR) &&
6898 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6900 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6901 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6903 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6905 switch (lit & 0xff) {
6907 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6910 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6911 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6912 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6916 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6917 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6918 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6919 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6923 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6924 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6929 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6932 if(AOP_TYPE(result) == AOP_CRY) {
6933 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6938 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6940 /* fix me. probably need to check result size too */
6941 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6946 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6947 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6954 if(res_offset < res_size-1)
6959 } else if(AOP_TYPE(right) == AOP_REG &&
6960 AOP_TYPE(left) != AOP_DIR){
6963 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6964 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6965 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6970 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6972 if(res_offset < res_size-1)
6977 /* right is a pointer reg need both a & b */
6979 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6981 pic16_emitcode("mov","b,%s",l);
6982 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6983 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6988 if(result && preserve_result)
6991 for(i = 0; i < AOP_SIZE(result); i++)
6992 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6995 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6997 if(result && preserve_result)
6998 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
7001 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7003 pic16_emitpLabel(lbl->key);
7005 if(result && preserve_result)
7008 for(i = 0; i < AOP_SIZE(result); i++)
7009 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7011 pic16_emitpLabel(lbl_done->key);
7014 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7022 /*-----------------------------------------------------------------*/
7023 /* gencjne - compare and jump if not equal */
7024 /*-----------------------------------------------------------------*/
7025 static void gencjne(operand *left, operand *right, iCode *ifx)
7027 symbol *tlbl = newiTempLabel(NULL);
7029 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7030 gencjneshort(left, right, lbl);
7032 pic16_emitcode("mov","a,%s",one);
7033 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
7034 pic16_emitcode("","%05d_DS_:",lbl->key+100);
7035 pic16_emitcode("clr","a");
7036 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7038 pic16_emitpLabel(lbl->key);
7039 pic16_emitpLabel(tlbl->key);
7045 /*-----------------------------------------------------------------*/
7046 /* is_LitOp - check if operand has to be treated as literal */
7047 /*-----------------------------------------------------------------*/
7048 static bool is_LitOp(operand *op)
7050 return ((AOP_TYPE(op) == AOP_LIT)
7051 || ( (AOP_TYPE(op) == AOP_PCODE)
7052 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
7053 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
7056 /*-----------------------------------------------------------------*/
7057 /* is_LitAOp - check if operand has to be treated as literal */
7058 /*-----------------------------------------------------------------*/
7059 static bool is_LitAOp(asmop *aop)
7061 return ((aop->type == AOP_LIT)
7062 || ( (aop->type == AOP_PCODE)
7063 && ( (aop->aopu.pcop->type == PO_LITERAL)
7064 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
7069 /*-----------------------------------------------------------------*/
7070 /* genCmpEq - generates code for equal to */
7071 /*-----------------------------------------------------------------*/
7072 static void genCmpEq (iCode *ic, iCode *ifx)
7074 operand *left, *right, *result;
7075 symbol *falselbl = newiTempLabel(NULL);
7076 symbol *donelbl = newiTempLabel(NULL);
7078 int preserve_result = 0;
7079 int generate_result = 0;
7081 unsigned long lit = -1;
7085 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7086 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7087 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7089 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7091 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
7093 werror(W_POSSBUG2, __FILE__, __LINE__);
7094 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
7095 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
7099 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
7101 operand *tmp = right ;
7106 if (AOP_TYPE(right) == AOP_LIT) {
7107 lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
7110 if ( regsInCommon(left, result) || regsInCommon(right, result) )
7111 preserve_result = 1;
7113 if(result && AOP_SIZE(result))
7114 generate_result = 1;
7116 if(generate_result && !preserve_result)
7118 for(i = 0; i < AOP_SIZE(result); i++)
7119 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7122 for(i=0; i < AOP_SIZE(left); i++)
7124 if(AOP_TYPE(left) != AOP_ACC)
7127 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
7129 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
7131 if(is_LitOp(right)) {
7132 if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
7133 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
7136 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
7138 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
7143 if(generate_result && preserve_result)
7145 for(i = 0; i < AOP_SIZE(result); i++)
7146 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7150 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
7152 if(generate_result && preserve_result)
7153 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7155 if(ifx && IC_TRUE(ifx))
7156 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7158 if(ifx && IC_FALSE(ifx))
7159 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7161 pic16_emitpLabel(falselbl->key);
7165 if(ifx && IC_FALSE(ifx))
7166 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7168 if(generate_result && preserve_result)
7170 for(i = 0; i < AOP_SIZE(result); i++)
7171 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7174 pic16_emitpLabel(donelbl->key);
7180 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7181 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7182 pic16_freeAsmop(result,NULL,ic,TRUE);
7188 // old version kept for reference
7190 /*-----------------------------------------------------------------*/
7191 /* genCmpEq - generates code for equal to */
7192 /*-----------------------------------------------------------------*/
7193 static void genCmpEq (iCode *ic, iCode *ifx)
7195 operand *left, *right, *result;
7196 unsigned long lit = 0L;
7198 symbol *falselbl = newiTempLabel(NULL);
7201 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7204 DEBUGpic16_emitcode ("; ifx is non-null","");
7206 DEBUGpic16_emitcode ("; ifx is null","");
7208 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7209 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7210 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7212 size = max(AOP_SIZE(left),AOP_SIZE(right));
7214 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7216 /* if literal, literal on the right or
7217 if the right is in a pointer register and left
7219 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
7220 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
7221 operand *tmp = right ;
7227 if(ifx && !AOP_SIZE(result)){
7229 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
7230 /* if they are both bit variables */
7231 if (AOP_TYPE(left) == AOP_CRY &&
7232 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7233 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
7234 if(AOP_TYPE(right) == AOP_LIT){
7235 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7237 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7238 pic16_emitcode("cpl","c");
7239 } else if(lit == 1L) {
7240 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7242 pic16_emitcode("clr","c");
7244 /* AOP_TYPE(right) == AOP_CRY */
7246 symbol *lbl = newiTempLabel(NULL);
7247 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7248 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7249 pic16_emitcode("cpl","c");
7250 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7252 /* if true label then we jump if condition
7254 tlbl = newiTempLabel(NULL);
7255 if ( IC_TRUE(ifx) ) {
7256 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
7257 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
7259 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
7260 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
7262 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7265 /* left and right are both bit variables, result is carry */
7268 resolveIfx(&rIfx,ifx);
7270 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
7271 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
7272 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
7273 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
7278 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
7280 /* They're not both bit variables. Is the right a literal? */
7281 if(AOP_TYPE(right) == AOP_LIT) {
7282 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7287 switch(lit & 0xff) {
7289 if ( IC_TRUE(ifx) ) {
7290 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
7292 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7294 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
7295 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7299 if ( IC_TRUE(ifx) ) {
7300 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
7302 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7304 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
7305 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7309 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7311 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
7316 /* end of size == 1 */
7320 genc16bit2lit(left,lit,offset);
7323 /* end of size == 2 */
7328 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7329 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
7330 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7331 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7334 /* search for patterns that can be optimized */
7336 genc16bit2lit(left,lit,0);
7340 emitSKPZ; // if hi word unequal
7342 emitSKPNZ; // if hi word equal
7344 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
7345 genc16bit2lit(left,lit,2);
7348 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7349 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7353 pic16_emitpLabel(falselbl->key);
7362 } else if(AOP_TYPE(right) == AOP_CRY ) {
7363 /* we know the left is not a bit, but that the right is */
7364 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7365 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
7366 pic16_popGet(AOP(right),offset));
7367 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
7369 /* if the two are equal, then W will be 0 and the Z bit is set
7370 * we could test Z now, or go ahead and check the high order bytes if
7371 * the variable we're comparing is larger than a byte. */
7374 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
7376 if ( IC_TRUE(ifx) ) {
7378 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7379 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7382 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7383 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7387 /* They're both variables that are larger than bits */
7390 tlbl = newiTempLabel(NULL);
7393 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7394 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7396 if ( IC_TRUE(ifx) ) {
7400 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7402 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7403 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7407 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7410 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7411 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7416 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7418 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7419 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7423 if(s>1 && IC_TRUE(ifx)) {
7424 pic16_emitpLabel(tlbl->key);
7425 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7429 /* mark the icode as generated */
7434 /* if they are both bit variables */
7435 if (AOP_TYPE(left) == AOP_CRY &&
7436 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7437 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7438 if(AOP_TYPE(right) == AOP_LIT){
7439 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7441 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7442 pic16_emitcode("cpl","c");
7443 } else if(lit == 1L) {
7444 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7446 pic16_emitcode("clr","c");
7448 /* AOP_TYPE(right) == AOP_CRY */
7450 symbol *lbl = newiTempLabel(NULL);
7451 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7452 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7453 pic16_emitcode("cpl","c");
7454 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7457 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7458 pic16_outBitC(result);
7462 genIfxJump (ifx,"c");
7465 /* if the result is used in an arithmetic operation
7466 then put the result in place */
7467 pic16_outBitC(result);
7470 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7471 gencjne(left,right,result,ifx);
7474 gencjne(left,right,newiTempLabel(NULL));
7476 if(IC_TRUE(ifx)->key)
7477 gencjne(left,right,IC_TRUE(ifx)->key);
7479 gencjne(left,right,IC_FALSE(ifx)->key);
7483 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7484 pic16_aopPut(AOP(result),"a",0);
7489 genIfxJump (ifx,"a");
7493 /* if the result is used in an arithmetic operation
7494 then put the result in place */
7496 if (AOP_TYPE(result) != AOP_CRY)
7497 pic16_outAcc(result);
7499 /* leave the result in acc */
7503 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7504 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7505 pic16_freeAsmop(result,NULL,ic,TRUE);
7509 /*-----------------------------------------------------------------*/
7510 /* ifxForOp - returns the icode containing the ifx for operand */
7511 /*-----------------------------------------------------------------*/
7512 static iCode *ifxForOp ( operand *op, iCode *ic )
7516 /* if true symbol then needs to be assigned */
7517 if (IS_TRUE_SYMOP(op))
7520 /* if this has register type condition and
7521 the next instruction is ifx with the same operand
7522 and live to of the operand is upto the ifx only then */
7524 && ic->next->op == IFX
7525 && IC_COND(ic->next)->key == op->key
7526 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7528 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7534 ic->next->op == IFX &&
7535 IC_COND(ic->next)->key == op->key) {
7536 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7541 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7543 ic->next->op == IFX)
7544 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7547 ic->next->op == IFX &&
7548 IC_COND(ic->next)->key == op->key) {
7549 DEBUGpic16_emitcode ("; "," key is okay");
7550 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7551 OP_SYMBOL(op)->liveTo,
7556 /* the code below is completely untested
7557 * it just allows ulong2fs.c compile -- VR */
7560 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7561 __FILE__, __FUNCTION__, __LINE__);
7563 /* if this has register type condition and
7564 the next instruction is ifx with the same operand
7565 and live to of the operand is upto the ifx only then */
7567 ic->next->op == IFX &&
7568 IC_COND(ic->next)->key == op->key &&
7569 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7573 ic->next->op == IFX &&
7574 IC_COND(ic->next)->key == op->key) {
7575 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7579 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7580 __FILE__, __FUNCTION__, __LINE__);
7582 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7587 /*-----------------------------------------------------------------*/
7588 /* genAndOp - for && operation */
7589 /*-----------------------------------------------------------------*/
7590 static void genAndOp (iCode *ic)
7592 operand *left,*right, *result;
7597 /* note here that && operations that are in an
7598 if statement are taken away by backPatchLabels
7599 only those used in arthmetic operations remain */
7600 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7601 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7602 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7604 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7606 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7607 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7608 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7610 /* if both are bit variables */
7611 /* if (AOP_TYPE(left) == AOP_CRY && */
7612 /* AOP_TYPE(right) == AOP_CRY ) { */
7613 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7614 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7615 /* pic16_outBitC(result); */
7617 /* tlbl = newiTempLabel(NULL); */
7618 /* pic16_toBoolean(left); */
7619 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7620 /* pic16_toBoolean(right); */
7621 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7622 /* pic16_outBitAcc(result); */
7625 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7626 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7627 pic16_freeAsmop(result,NULL,ic,TRUE);
7631 /*-----------------------------------------------------------------*/
7632 /* genOrOp - for || operation */
7633 /*-----------------------------------------------------------------*/
7636 modified this code, but it doesn't appear to ever get called
7639 static void genOrOp (iCode *ic)
7641 operand *left,*right, *result;
7646 /* note here that || operations that are in an
7647 if statement are taken away by backPatchLabels
7648 only those used in arthmetic operations remain */
7649 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7650 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7651 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7653 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7655 /* if both are bit variables */
7656 if (AOP_TYPE(left) == AOP_CRY &&
7657 AOP_TYPE(right) == AOP_CRY ) {
7658 pic16_emitcode("clrc","");
7659 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7660 AOP(left)->aopu.aop_dir,
7661 AOP(left)->aopu.aop_dir);
7662 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7663 AOP(right)->aopu.aop_dir,
7664 AOP(right)->aopu.aop_dir);
7665 pic16_emitcode("setc","");
7668 tlbl = newiTempLabel(NULL);
7669 pic16_toBoolean(left);
7671 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7672 pic16_toBoolean(right);
7673 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7675 pic16_outBitAcc(result);
7678 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7679 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7680 pic16_freeAsmop(result,NULL,ic,TRUE);
7683 /*-----------------------------------------------------------------*/
7684 /* isLiteralBit - test if lit == 2^n */
7685 /*-----------------------------------------------------------------*/
7686 static int isLiteralBit(unsigned long lit)
7688 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7689 0x100L,0x200L,0x400L,0x800L,
7690 0x1000L,0x2000L,0x4000L,0x8000L,
7691 0x10000L,0x20000L,0x40000L,0x80000L,
7692 0x100000L,0x200000L,0x400000L,0x800000L,
7693 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7694 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7697 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7698 for(idx = 0; idx < 32; idx++)
7704 /*-----------------------------------------------------------------*/
7705 /* continueIfTrue - */
7706 /*-----------------------------------------------------------------*/
7707 static void continueIfTrue (iCode *ic)
7711 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7715 /*-----------------------------------------------------------------*/
7717 /*-----------------------------------------------------------------*/
7718 static void jumpIfTrue (iCode *ic)
7722 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7726 /*-----------------------------------------------------------------*/
7727 /* jmpTrueOrFalse - */
7728 /*-----------------------------------------------------------------*/
7729 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7731 // ugly but optimized by peephole
7734 symbol *nlbl = newiTempLabel(NULL);
7735 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7736 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7737 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7738 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7740 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7741 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7746 /*-----------------------------------------------------------------*/
7747 /* genAnd - code for and */
7748 /*-----------------------------------------------------------------*/
7749 static void genAnd (iCode *ic, iCode *ifx)
7751 operand *left, *right, *result;
7753 unsigned long lit = 0L;
7759 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7760 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7761 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7763 resolveIfx(&rIfx,ifx);
7765 /* if left is a literal & right is not then exchange them */
7766 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7767 AOP_NEEDSACC(left)) {
7768 operand *tmp = right ;
7773 /* if result = right then exchange them */
7774 if(pic16_sameRegs(AOP(result),AOP(right))){
7775 operand *tmp = right ;
7780 /* if right is bit then exchange them */
7781 if (AOP_TYPE(right) == AOP_CRY &&
7782 AOP_TYPE(left) != AOP_CRY){
7783 operand *tmp = right ;
7787 if(AOP_TYPE(right) == AOP_LIT)
7788 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7790 size = AOP_SIZE(result);
7792 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7795 // result = bit & yy;
7796 if (AOP_TYPE(left) == AOP_CRY){
7797 // c = bit & literal;
7798 if(AOP_TYPE(right) == AOP_LIT){
7800 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7803 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7806 if(size && (AOP_TYPE(result) == AOP_CRY)){
7807 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7810 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7814 pic16_emitcode("clr","c");
7817 if (AOP_TYPE(right) == AOP_CRY){
7819 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7820 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7823 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7825 pic16_emitcode("rrc","a");
7826 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7832 pic16_outBitC(result);
7834 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7835 genIfxJump(ifx, "c");
7839 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7840 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7841 if((AOP_TYPE(right) == AOP_LIT) &&
7842 (AOP_TYPE(result) == AOP_CRY) &&
7843 (AOP_TYPE(left) != AOP_CRY)){
7844 int posbit = isLiteralBit(lit);
7848 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7851 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7857 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7858 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7860 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7861 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7864 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7865 size = AOP_SIZE(left);
7868 int bp = posbit, ofs=0;
7875 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7876 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7880 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7881 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7883 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7890 symbol *tlbl = newiTempLabel(NULL);
7891 int sizel = AOP_SIZE(left);
7897 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7899 /* patch provided by Aaron Colwell */
7900 if((posbit = isLiteralBit(bytelit)) != 0) {
7901 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7902 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7903 (posbit-1),0, PO_GPR_REGISTER));
7905 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7906 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7908 if (bytelit == 0xff) {
7909 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7910 * a peephole could optimize it out -- VR */
7911 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7913 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7914 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7917 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7918 pic16_popGetLabel(tlbl->key));
7922 /* old code, left here for reference -- VR 09/2004 */
7923 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7925 if((posbit = isLiteralBit(bytelit)) != 0)
7926 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7928 if(bytelit != 0x0FFL)
7929 pic16_emitcode("anl","a,%s",
7930 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7931 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7937 // bit = left & literal
7940 pic16_emitpLabel(tlbl->key);
7942 // if(left & literal)
7945 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7948 pic16_emitpLabel(tlbl->key);
7953 pic16_outBitC(result);
7957 /* if left is same as result */
7958 if(pic16_sameRegs(AOP(result),AOP(left))){
7960 for(;size--; offset++,lit>>=8) {
7961 if(AOP_TYPE(right) == AOP_LIT){
7962 switch(lit & 0xff) {
7964 /* and'ing with 0 has clears the result */
7965 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7966 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7969 /* and'ing with 0xff is a nop when the result and left are the same */
7974 int p = pic16_my_powof2( (~lit) & 0xff );
7976 /* only one bit is set in the literal, so use a bcf instruction */
7977 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7978 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7981 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7982 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7983 if(know_W != (lit&0xff))
7984 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7986 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7991 if (AOP_TYPE(left) == AOP_ACC) {
7992 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7994 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7995 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
8002 // left & result in different registers
8003 if(AOP_TYPE(result) == AOP_CRY){
8005 // if(size), result in bit
8006 // if(!size && ifx), conditional oper: if(left & right)
8007 symbol *tlbl = newiTempLabel(NULL);
8008 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
8010 pic16_emitcode("setb","c");
8012 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8013 pic16_emitcode("anl","a,%s",
8014 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8015 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8020 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8021 pic16_outBitC(result);
8023 jmpTrueOrFalse(ifx, tlbl);
8025 for(;(size--);offset++) {
8027 // result = left & right
8028 if(AOP_TYPE(right) == AOP_LIT){
8029 int t = (lit >> (offset*8)) & 0x0FFL;
8032 pic16_emitcode("clrf","%s",
8033 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8034 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
8037 pic16_emitcode("movf","%s,w",
8038 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8039 pic16_emitcode("movwf","%s",
8040 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8041 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8042 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8045 pic16_emitcode("movlw","0x%x",t);
8046 pic16_emitcode("andwf","%s,w",
8047 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8048 pic16_emitcode("movwf","%s",
8049 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8051 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8052 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
8053 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8058 if (AOP_TYPE(left) == AOP_ACC) {
8059 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8060 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
8062 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8063 pic16_emitcode("andwf","%s,w",
8064 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8065 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8066 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
8068 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8069 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8075 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8076 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8077 pic16_freeAsmop(result,NULL,ic,TRUE);
8080 /*-----------------------------------------------------------------*/
8081 /* genOr - code for or */
8082 /*-----------------------------------------------------------------*/
8083 static void genOr (iCode *ic, iCode *ifx)
8085 operand *left, *right, *result;
8087 unsigned long lit = 0L;
8089 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8091 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8092 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8093 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8095 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
8097 /* if left is a literal & right is not then exchange them */
8098 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8099 AOP_NEEDSACC(left)) {
8100 operand *tmp = right ;
8105 /* if result = right then exchange them */
8106 if(pic16_sameRegs(AOP(result),AOP(right))){
8107 operand *tmp = right ;
8112 /* if right is bit then exchange them */
8113 if (AOP_TYPE(right) == AOP_CRY &&
8114 AOP_TYPE(left) != AOP_CRY){
8115 operand *tmp = right ;
8120 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
8122 if(AOP_TYPE(right) == AOP_LIT)
8123 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8125 size = AOP_SIZE(result);
8129 if (AOP_TYPE(left) == AOP_CRY){
8130 if(AOP_TYPE(right) == AOP_LIT){
8131 // c = bit & literal;
8133 // lit != 0 => result = 1
8134 if(AOP_TYPE(result) == AOP_CRY){
8136 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8137 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8138 // AOP(result)->aopu.aop_dir,
8139 // AOP(result)->aopu.aop_dir);
8141 continueIfTrue(ifx);
8145 // lit == 0 => result = left
8146 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8148 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
8151 if (AOP_TYPE(right) == AOP_CRY){
8152 if(pic16_sameRegs(AOP(result),AOP(left))){
8154 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8155 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
8156 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8158 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8159 AOP(result)->aopu.aop_dir,
8160 AOP(result)->aopu.aop_dir);
8161 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8162 AOP(right)->aopu.aop_dir,
8163 AOP(right)->aopu.aop_dir);
8164 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8165 AOP(result)->aopu.aop_dir,
8166 AOP(result)->aopu.aop_dir);
8168 if( AOP_TYPE(result) == AOP_ACC) {
8169 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8170 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8171 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8172 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
8176 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8177 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8178 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8179 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8181 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8182 AOP(result)->aopu.aop_dir,
8183 AOP(result)->aopu.aop_dir);
8184 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
8185 AOP(right)->aopu.aop_dir,
8186 AOP(right)->aopu.aop_dir);
8187 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8188 AOP(left)->aopu.aop_dir,
8189 AOP(left)->aopu.aop_dir);
8190 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8191 AOP(result)->aopu.aop_dir,
8192 AOP(result)->aopu.aop_dir);
8197 symbol *tlbl = newiTempLabel(NULL);
8198 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8201 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8202 if( AOP_TYPE(right) == AOP_ACC) {
8203 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
8205 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8206 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8211 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
8212 pic16_emitcode(";XXX setb","c");
8213 pic16_emitcode(";XXX jb","%s,%05d_DS_",
8214 AOP(left)->aopu.aop_dir,tlbl->key+100);
8215 pic16_toBoolean(right);
8216 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8217 if((AOP_TYPE(result) == AOP_CRY) && ifx){
8218 jmpTrueOrFalse(ifx, tlbl);
8222 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8229 pic16_outBitC(result);
8231 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8232 genIfxJump(ifx, "c");
8236 // if(val | 0xZZ) - size = 0, ifx != FALSE -
8237 // bit = val | 0xZZ - size = 1, ifx = FALSE -
8238 if((AOP_TYPE(right) == AOP_LIT) &&
8239 (AOP_TYPE(result) == AOP_CRY) &&
8240 (AOP_TYPE(left) != AOP_CRY)){
8242 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8245 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
8247 continueIfTrue(ifx);
8250 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8251 // lit = 0, result = boolean(left)
8253 pic16_emitcode(";XXX setb","c");
8254 pic16_toBoolean(right);
8256 symbol *tlbl = newiTempLabel(NULL);
8257 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8259 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8261 genIfxJump (ifx,"a");
8265 pic16_outBitC(result);
8269 /* if left is same as result */
8270 if(pic16_sameRegs(AOP(result),AOP(left))){
8272 for(;size--; offset++,lit>>=8) {
8273 if(AOP_TYPE(right) == AOP_LIT){
8274 if((lit & 0xff) == 0)
8275 /* or'ing with 0 has no effect */
8278 int p = pic16_my_powof2(lit & 0xff);
8280 /* only one bit is set in the literal, so use a bsf instruction */
8281 pic16_emitpcode(POC_BSF,
8282 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
8284 if(know_W != (lit & 0xff))
8285 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
8286 know_W = lit & 0xff;
8287 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8292 if (AOP_TYPE(left) == AOP_ACC) {
8293 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
8294 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8296 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8297 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8299 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8300 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8306 // left & result in different registers
8307 if(AOP_TYPE(result) == AOP_CRY){
8309 // if(size), result in bit
8310 // if(!size && ifx), conditional oper: if(left | right)
8311 symbol *tlbl = newiTempLabel(NULL);
8312 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8313 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8317 pic16_emitcode(";XXX setb","c");
8319 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8320 pic16_emitcode(";XXX orl","a,%s",
8321 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8322 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8327 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8328 pic16_outBitC(result);
8330 jmpTrueOrFalse(ifx, tlbl);
8331 } else for(;(size--);offset++){
8333 // result = left & right
8334 if(AOP_TYPE(right) == AOP_LIT){
8335 int t = (lit >> (offset*8)) & 0x0FFL;
8338 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8339 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8341 pic16_emitcode("movf","%s,w",
8342 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8343 pic16_emitcode("movwf","%s",
8344 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8347 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8348 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
8349 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8351 pic16_emitcode("movlw","0x%x",t);
8352 pic16_emitcode("iorwf","%s,w",
8353 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8354 pic16_emitcode("movwf","%s",
8355 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8361 // faster than result <- left, anl result,right
8362 // and better if result is SFR
8363 if (AOP_TYPE(left) == AOP_ACC) {
8364 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
8365 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8367 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8368 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
8370 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8371 pic16_emitcode("iorwf","%s,w",
8372 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8374 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8375 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8380 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8381 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8382 pic16_freeAsmop(result,NULL,ic,TRUE);
8385 /*-----------------------------------------------------------------*/
8386 /* genXor - code for xclusive or */
8387 /*-----------------------------------------------------------------*/
8388 static void genXor (iCode *ic, iCode *ifx)
8390 operand *left, *right, *result;
8392 unsigned long lit = 0L;
8394 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8396 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8397 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8398 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8400 /* if left is a literal & right is not ||
8401 if left needs acc & right does not */
8402 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8403 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8404 operand *tmp = right ;
8409 /* if result = right then exchange them */
8410 if(pic16_sameRegs(AOP(result),AOP(right))){
8411 operand *tmp = right ;
8416 /* if right is bit then exchange them */
8417 if (AOP_TYPE(right) == AOP_CRY &&
8418 AOP_TYPE(left) != AOP_CRY){
8419 operand *tmp = right ;
8423 if(AOP_TYPE(right) == AOP_LIT)
8424 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8426 size = AOP_SIZE(result);
8430 if (AOP_TYPE(left) == AOP_CRY){
8431 if(AOP_TYPE(right) == AOP_LIT){
8432 // c = bit & literal;
8434 // lit>>1 != 0 => result = 1
8435 if(AOP_TYPE(result) == AOP_CRY){
8437 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
8438 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8440 continueIfTrue(ifx);
8443 pic16_emitcode("setb","c");
8447 // lit == 0, result = left
8448 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8450 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8452 // lit == 1, result = not(left)
8453 if(size && pic16_sameRegs(AOP(result),AOP(left))){
8454 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
8455 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
8456 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8459 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8460 pic16_emitcode("cpl","c");
8467 symbol *tlbl = newiTempLabel(NULL);
8468 if (AOP_TYPE(right) == AOP_CRY){
8470 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8473 int sizer = AOP_SIZE(right);
8475 // if val>>1 != 0, result = 1
8476 pic16_emitcode("setb","c");
8478 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8480 // test the msb of the lsb
8481 pic16_emitcode("anl","a,#0xfe");
8482 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8486 pic16_emitcode("rrc","a");
8488 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8489 pic16_emitcode("cpl","c");
8490 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8495 pic16_outBitC(result);
8497 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8498 genIfxJump(ifx, "c");
8502 if(pic16_sameRegs(AOP(result),AOP(left))){
8503 /* if left is same as result */
8504 for(;size--; offset++) {
8505 if(AOP_TYPE(right) == AOP_LIT){
8506 int t = (lit >> (offset*8)) & 0x0FFL;
8510 if (IS_AOP_PREG(left)) {
8511 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8512 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8513 pic16_aopPut(AOP(result),"a",offset);
8515 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8516 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8517 pic16_emitcode("xrl","%s,%s",
8518 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8519 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8522 if (AOP_TYPE(left) == AOP_ACC)
8523 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8525 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8526 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8528 if (IS_AOP_PREG(left)) {
8529 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8530 pic16_aopPut(AOP(result),"a",offset);
8532 pic16_emitcode("xrl","%s,a",
8533 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8539 // left & result in different registers
8540 if(AOP_TYPE(result) == AOP_CRY){
8542 // if(size), result in bit
8543 // if(!size && ifx), conditional oper: if(left ^ right)
8544 symbol *tlbl = newiTempLabel(NULL);
8545 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8547 pic16_emitcode("setb","c");
8549 if((AOP_TYPE(right) == AOP_LIT) &&
8550 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8551 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8553 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8554 pic16_emitcode("xrl","a,%s",
8555 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8557 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8562 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8563 pic16_outBitC(result);
8565 jmpTrueOrFalse(ifx, tlbl);
8566 } else for(;(size--);offset++){
8568 // result = left & right
8569 if(AOP_TYPE(right) == AOP_LIT){
8570 int t = (lit >> (offset*8)) & 0x0FFL;
8573 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8574 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8575 pic16_emitcode("movf","%s,w",
8576 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8577 pic16_emitcode("movwf","%s",
8578 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8581 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8582 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8583 pic16_emitcode("comf","%s,w",
8584 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8585 pic16_emitcode("movwf","%s",
8586 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8589 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8590 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8591 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8592 pic16_emitcode("movlw","0x%x",t);
8593 pic16_emitcode("xorwf","%s,w",
8594 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8595 pic16_emitcode("movwf","%s",
8596 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8602 // faster than result <- left, anl result,right
8603 // and better if result is SFR
8604 if (AOP_TYPE(left) == AOP_ACC) {
8605 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8606 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8608 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8609 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8610 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8611 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8613 if ( AOP_TYPE(result) != AOP_ACC){
8614 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8615 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8621 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8622 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8623 pic16_freeAsmop(result,NULL,ic,TRUE);
8626 /*-----------------------------------------------------------------*/
8627 /* genInline - write the inline code out */
8628 /*-----------------------------------------------------------------*/
8629 static void genInline (iCode *ic)
8631 char *buffer, *bp, *bp1;
8633 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8635 _G.inLine += (!options.asmpeep);
8637 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8638 strcpy(buffer,IC_INLINE(ic));
8640 while((bp1=strstr(bp, "\\n"))) {
8647 /* emit each line as a code */
8653 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8661 /* print label, use this special format with NULL directive
8662 * to denote that the argument should not be indented with tab */
8663 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8670 if ((bp1 != bp) && *bp1)
8671 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8676 _G.inLine -= (!options.asmpeep);
8679 /*-----------------------------------------------------------------*/
8680 /* genRRC - rotate right with carry */
8681 /*-----------------------------------------------------------------*/
8682 static void genRRC (iCode *ic)
8684 operand *left , *result ;
8685 int size, offset = 0, same;
8687 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8689 /* rotate right with carry */
8691 result=IC_RESULT(ic);
8692 pic16_aopOp (left,ic,FALSE);
8693 pic16_aopOp (result,ic,TRUE);
8695 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8697 same = pic16_sameRegs(AOP(result),AOP(left));
8699 size = AOP_SIZE(result);
8701 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8703 /* get the lsb and put it into the carry */
8704 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8711 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8713 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8714 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8720 pic16_freeAsmop(left,NULL,ic,TRUE);
8721 pic16_freeAsmop(result,NULL,ic,TRUE);
8724 /*-----------------------------------------------------------------*/
8725 /* genRLC - generate code for rotate left with carry */
8726 /*-----------------------------------------------------------------*/
8727 static void genRLC (iCode *ic)
8729 operand *left , *result ;
8730 int size, offset = 0;
8733 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8734 /* rotate right with carry */
8736 result=IC_RESULT(ic);
8737 pic16_aopOp (left,ic,FALSE);
8738 pic16_aopOp (result,ic,TRUE);
8740 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8742 same = pic16_sameRegs(AOP(result),AOP(left));
8744 /* move it to the result */
8745 size = AOP_SIZE(result);
8747 /* get the msb and put it into the carry */
8748 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8755 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8757 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8758 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8765 pic16_freeAsmop(left,NULL,ic,TRUE);
8766 pic16_freeAsmop(result,NULL,ic,TRUE);
8770 /* gpasm can get the highest order bit with HIGH/UPPER
8771 * so the following probably is not needed -- VR */
8773 /*-----------------------------------------------------------------*/
8774 /* genGetHbit - generates code get highest order bit */
8775 /*-----------------------------------------------------------------*/
8776 static void genGetHbit (iCode *ic)
8778 operand *left, *result;
8780 result=IC_RESULT(ic);
8781 pic16_aopOp (left,ic,FALSE);
8782 pic16_aopOp (result,ic,FALSE);
8784 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8785 /* get the highest order byte into a */
8786 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8787 if(AOP_TYPE(result) == AOP_CRY){
8788 pic16_emitcode("rlc","a");
8789 pic16_outBitC(result);
8792 pic16_emitcode("rl","a");
8793 pic16_emitcode("anl","a,#0x01");
8794 pic16_outAcc(result);
8798 pic16_freeAsmop(left,NULL,ic,TRUE);
8799 pic16_freeAsmop(result,NULL,ic,TRUE);
8803 /*-----------------------------------------------------------------*/
8804 /* AccRol - rotate left accumulator by known count */
8805 /*-----------------------------------------------------------------*/
8806 static void AccRol (int shCount)
8808 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8809 shCount &= 0x0007; // shCount : 0..7
8814 pic16_emitcode("rl","a");
8817 pic16_emitcode("rl","a");
8818 pic16_emitcode("rl","a");
8821 pic16_emitcode("swap","a");
8822 pic16_emitcode("rr","a");
8825 pic16_emitcode("swap","a");
8828 pic16_emitcode("swap","a");
8829 pic16_emitcode("rl","a");
8832 pic16_emitcode("rr","a");
8833 pic16_emitcode("rr","a");
8836 pic16_emitcode("rr","a");
8842 /*-----------------------------------------------------------------*/
8843 /* AccLsh - left shift accumulator by known count */
8844 /*-----------------------------------------------------------------*/
8845 static void AccLsh (int shCount)
8847 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8853 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8856 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8857 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8860 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8861 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8864 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8867 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8868 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8871 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8872 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8875 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8879 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8882 /*-----------------------------------------------------------------*/
8883 /* AccRsh - right shift accumulator by known count */
8884 /*-----------------------------------------------------------------*/
8885 static void AccRsh (int shCount, int andmask)
8887 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8892 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8895 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8896 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8899 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8900 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8903 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8906 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8907 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8910 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8911 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8914 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8919 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8921 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8925 /*-----------------------------------------------------------------*/
8926 /* AccSRsh - signed right shift accumulator by known count */
8927 /*-----------------------------------------------------------------*/
8928 static void AccSRsh (int shCount)
8931 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8934 pic16_emitcode("mov","c,acc.7");
8935 pic16_emitcode("rrc","a");
8936 } else if(shCount == 2){
8937 pic16_emitcode("mov","c,acc.7");
8938 pic16_emitcode("rrc","a");
8939 pic16_emitcode("mov","c,acc.7");
8940 pic16_emitcode("rrc","a");
8942 tlbl = newiTempLabel(NULL);
8943 /* rotate right accumulator */
8944 AccRol(8 - shCount);
8945 /* and kill the higher order bits */
8946 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8947 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8948 pic16_emitcode("orl","a,#0x%02x",
8949 (unsigned char)~SRMask[shCount]);
8950 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8956 /*-----------------------------------------------------------------*/
8957 /* shiftR1Left2Result - shift right one byte from left to result */
8958 /*-----------------------------------------------------------------*/
8959 static void shiftR1Left2ResultSigned (operand *left, int offl,
8960 operand *result, int offr,
8965 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8967 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8971 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8973 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8975 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8976 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8982 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8984 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8986 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8987 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8989 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8990 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8996 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8998 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8999 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9002 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
9003 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9004 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9006 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
9007 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
9009 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9013 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9014 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9015 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9016 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
9017 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9021 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9023 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9024 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9026 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9027 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
9028 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
9029 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
9030 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9035 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
9036 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9037 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
9038 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
9039 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
9040 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9042 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9043 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9044 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
9045 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
9046 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9052 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
9053 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9054 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9055 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9057 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9058 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9059 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
9067 /*-----------------------------------------------------------------*/
9068 /* shiftR1Left2Result - shift right one byte from left to result */
9069 /*-----------------------------------------------------------------*/
9070 static void shiftR1Left2Result (operand *left, int offl,
9071 operand *result, int offr,
9072 int shCount, int sign)
9076 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9078 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
9080 /* Copy the msb into the carry if signed. */
9082 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
9092 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9094 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9095 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9101 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9103 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9104 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9107 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9112 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9114 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9115 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9118 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
9119 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9120 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9121 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9125 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9126 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9127 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9131 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9132 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
9133 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9135 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
9140 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
9141 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
9142 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9143 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9144 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
9149 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9150 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9151 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9160 /*-----------------------------------------------------------------*/
9161 /* shiftL1Left2Result - shift left one byte from left to result */
9162 /*-----------------------------------------------------------------*/
9163 static void shiftL1Left2Result (operand *left, int offl,
9164 operand *result, int offr, int shCount)
9169 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9171 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9172 DEBUGpic16_emitcode ("; ***","same = %d",same);
9173 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9175 /* shift left accumulator */
9176 //AccLsh(shCount); // don't comment out just yet...
9177 // pic16_aopPut(AOP(result),"a",offr);
9181 /* Shift left 1 bit position */
9182 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9184 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9186 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9187 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9191 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9192 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9193 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9194 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9197 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9198 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9199 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9200 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9201 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9204 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9205 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9206 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9209 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9210 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9211 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9212 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9215 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9216 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9217 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9218 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9219 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9222 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9223 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9224 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9228 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9233 /*-----------------------------------------------------------------*/
9234 /* movLeft2Result - move byte from left to result */
9235 /*-----------------------------------------------------------------*/
9236 static void movLeft2Result (operand *left, int offl,
9237 operand *result, int offr)
9240 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9241 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9242 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9244 if (*l == '@' && (IS_AOP_PREG(result))) {
9245 pic16_emitcode("mov","a,%s",l);
9246 pic16_aopPut(AOP(result),"a",offr);
9248 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9249 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9254 /*-----------------------------------------------------------------*/
9255 /* shiftL2Left2Result - shift left two bytes from left to result */
9256 /*-----------------------------------------------------------------*/
9257 static void shiftL2Left2Result (operand *left, int offl,
9258 operand *result, int offr, int shCount)
9260 int same = pic16_sameRegs(AOP(result), AOP(left));
9263 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9265 if (same && (offl != offr)) { // shift bytes
9268 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9269 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9271 } else { // just treat as different later on
9284 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9285 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9286 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9290 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9291 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9297 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9298 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9299 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9300 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9301 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9302 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9303 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9305 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9306 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9310 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9311 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9312 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9313 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9314 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9315 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9316 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9317 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9318 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9319 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9322 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9323 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9324 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9325 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9326 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9336 /* note, use a mov/add for the shift since the mov has a
9337 chance of getting optimized out */
9338 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9339 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9340 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9341 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9342 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9346 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9347 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9353 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9354 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9355 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9356 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9357 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9358 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9359 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9360 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9364 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9365 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9369 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9370 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9371 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9372 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9374 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9375 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9376 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9377 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9378 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9379 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9380 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9381 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9384 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9385 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9386 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9387 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9388 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9393 /*-----------------------------------------------------------------*/
9394 /* shiftR2Left2Result - shift right two bytes from left to result */
9395 /*-----------------------------------------------------------------*/
9396 static void shiftR2Left2Result (operand *left, int offl,
9397 operand *result, int offr,
9398 int shCount, int sign)
9400 int same = pic16_sameRegs(AOP(result), AOP(left));
9402 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9404 if (same && (offl != offr)) { // shift right bytes
9407 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9408 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9410 } else { // just treat as different later on
9422 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9427 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9428 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9430 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9431 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9432 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9433 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9438 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9441 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9442 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9449 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9450 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9451 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9453 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9454 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9455 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9456 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9458 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9459 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9460 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9462 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9463 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9464 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9465 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9466 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9470 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9471 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9475 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9476 pic16_emitpcode(POC_BTFSC,
9477 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9478 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9486 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9487 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9489 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9490 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9491 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9492 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9494 pic16_emitpcode(POC_BTFSC,
9495 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9496 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9498 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9499 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9500 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9501 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9503 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9504 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9505 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9506 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9507 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9508 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9509 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9510 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9512 pic16_emitpcode(POC_BTFSC,
9513 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9514 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9516 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9517 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9524 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9525 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9526 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9527 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9530 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9532 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9537 /*-----------------------------------------------------------------*/
9538 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9539 /*-----------------------------------------------------------------*/
9540 static void shiftLLeftOrResult (operand *left, int offl,
9541 operand *result, int offr, int shCount)
9543 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9545 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9546 /* shift left accumulator */
9548 /* or with result */
9549 /* back to result */
9550 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9553 /*-----------------------------------------------------------------*/
9554 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9555 /*-----------------------------------------------------------------*/
9556 static void shiftRLeftOrResult (operand *left, int offl,
9557 operand *result, int offr, int shCount)
9559 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9561 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9562 /* shift right accumulator */
9564 /* or with result */
9565 /* back to result */
9566 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9569 /*-----------------------------------------------------------------*/
9570 /* genlshOne - left shift a one byte quantity by known count */
9571 /*-----------------------------------------------------------------*/
9572 static void genlshOne (operand *result, operand *left, int shCount)
9574 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9575 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9578 /*-----------------------------------------------------------------*/
9579 /* genlshTwo - left shift two bytes by known amount != 0 */
9580 /*-----------------------------------------------------------------*/
9581 static void genlshTwo (operand *result,operand *left, int shCount)
9585 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9586 size = pic16_getDataSize(result);
9588 /* if shCount >= 8 */
9594 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9596 movLeft2Result(left, LSB, result, MSB16);
9598 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9601 /* 1 <= shCount <= 7 */
9604 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9606 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9610 /*-----------------------------------------------------------------*/
9611 /* shiftLLong - shift left one long from left to result */
9612 /* offr = LSB or MSB16 */
9613 /*-----------------------------------------------------------------*/
9614 static void shiftLLong (operand *left, operand *result, int offr )
9616 int size = AOP_SIZE(result);
9617 int same = pic16_sameRegs(AOP(left),AOP(result));
9620 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9622 if (same && (offr == MSB16)) { //shift one byte
9623 for(i=size-1;i>=MSB16;i--) {
9624 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9625 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9628 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9631 if (size > LSB+offr ){
9633 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9635 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9636 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9640 if(size > MSB16+offr){
9642 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9644 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9645 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9649 if(size > MSB24+offr){
9651 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9653 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9654 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9658 if(size > MSB32+offr){
9660 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9662 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9663 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9667 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9671 /*-----------------------------------------------------------------*/
9672 /* genlshFour - shift four byte by a known amount != 0 */
9673 /*-----------------------------------------------------------------*/
9674 static void genlshFour (operand *result, operand *left, int shCount)
9678 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9679 size = AOP_SIZE(result);
9681 /* if shifting more that 3 bytes */
9682 if (shCount >= 24 ) {
9685 /* lowest order of left goes to the highest
9686 order of the destination */
9687 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9689 movLeft2Result(left, LSB, result, MSB32);
9691 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9692 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9693 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9698 /* more than two bytes */
9699 else if ( shCount >= 16 ) {
9700 /* lower order two bytes goes to higher order two bytes */
9702 /* if some more remaining */
9704 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9706 movLeft2Result(left, MSB16, result, MSB32);
9707 movLeft2Result(left, LSB, result, MSB24);
9709 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9710 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9714 /* if more than 1 byte */
9715 else if ( shCount >= 8 ) {
9716 /* lower order three bytes goes to higher order three bytes */
9720 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9722 movLeft2Result(left, LSB, result, MSB16);
9724 else{ /* size = 4 */
9726 movLeft2Result(left, MSB24, result, MSB32);
9727 movLeft2Result(left, MSB16, result, MSB24);
9728 movLeft2Result(left, LSB, result, MSB16);
9729 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9731 else if(shCount == 1)
9732 shiftLLong(left, result, MSB16);
9734 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9735 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9736 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9737 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9742 /* 1 <= shCount <= 7 */
9743 else if(shCount <= 3)
9745 shiftLLong(left, result, LSB);
9746 while(--shCount >= 1)
9747 shiftLLong(result, result, LSB);
9749 /* 3 <= shCount <= 7, optimize */
9751 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9752 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9753 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9757 /*-----------------------------------------------------------------*/
9758 /* genLeftShiftLiteral - left shifting by known count */
9759 /*-----------------------------------------------------------------*/
9760 void pic16_genLeftShiftLiteral (operand *left,
9765 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9769 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9770 pic16_freeAsmop(right,NULL,ic,TRUE);
9772 pic16_aopOp(left,ic,FALSE);
9773 pic16_aopOp(result,ic,TRUE);
9775 size = getSize(operandType(result));
9778 pic16_emitcode("; shift left ","result %d, left %d",size,
9782 /* I suppose that the left size >= result size */
9785 movLeft2Result(left, size, result, size);
9789 else if(shCount >= (size * 8))
9791 pic16_aopPut(AOP(result),zero,size);
9795 genlshOne (result,left,shCount);
9800 genlshTwo (result,left,shCount);
9804 genlshFour (result,left,shCount);
9808 pic16_freeAsmop(left,NULL,ic,TRUE);
9809 pic16_freeAsmop(result,NULL,ic,TRUE);
9812 /*-----------------------------------------------------------------*
9813 * genMultiAsm - repeat assembly instruction for size of register.
9814 * if endian == 1, then the high byte (i.e base address + size of
9815 * register) is used first else the low byte is used first;
9816 *-----------------------------------------------------------------*/
9817 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9822 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9835 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9841 #if !(USE_GENERIC_SIGNED_SHIFT)
9842 /*-----------------------------------------------------------------*/
9843 /* genLeftShift - generates code for left shifting */
9844 /*-----------------------------------------------------------------*/
9845 static void genLeftShift (iCode *ic)
9847 operand *left,*right, *result;
9850 symbol *tlbl , *tlbl1;
9853 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9855 right = IC_RIGHT(ic);
9857 result = IC_RESULT(ic);
9859 pic16_aopOp(right,ic,FALSE);
9861 /* if the shift count is known then do it
9862 as efficiently as possible */
9863 if (AOP_TYPE(right) == AOP_LIT) {
9864 pic16_genLeftShiftLiteral (left,right,result,ic);
9868 /* shift count is unknown then we have to form
9869 * a loop. Get the loop count in WREG : Note: we take
9870 * only the lower order byte since shifting
9871 * more than 32 bits make no sense anyway, ( the
9872 * largest size of an object can be only 32 bits ) */
9874 pic16_aopOp(left,ic,FALSE);
9875 pic16_aopOp(result,ic,FALSE);
9877 /* now move the left to the result if they are not the
9878 * same, and if size > 1,
9879 * and if right is not same to result (!!!) -- VR */
9880 if (!pic16_sameRegs(AOP(left),AOP(result))
9881 && (AOP_SIZE(result) > 1)) {
9883 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9885 size = AOP_SIZE(result);
9890 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9891 if (*l == '@' && (IS_AOP_PREG(result))) {
9893 pic16_emitcode("mov","a,%s",l);
9894 pic16_aopPut(AOP(result),"a",offset);
9898 /* we don't know if left is a literal or a register, take care -- VR */
9899 mov2f(AOP(result), AOP(left), offset);
9905 size = AOP_SIZE(result);
9907 /* if it is only one byte then */
9909 if(optimized_for_speed) {
9910 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9911 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9912 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9913 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9914 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9915 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9916 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9917 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9918 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9919 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9920 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9921 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9924 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9926 tlbl = newiTempLabel(NULL);
9929 /* this is already done, why change it? */
9930 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9931 mov2f(AOP(result), AOP(left), 0);
9935 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9936 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9937 pic16_emitpLabel(tlbl->key);
9938 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9939 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9941 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9946 if (pic16_sameRegs(AOP(left),AOP(result))) {
9948 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9950 tlbl = newiTempLabel(NULL);
9951 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9952 genMultiAsm(POC_RRCF, result, size,1);
9953 pic16_emitpLabel(tlbl->key);
9954 genMultiAsm(POC_RLCF, result, size,0);
9955 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9957 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9961 //tlbl = newiTempLabel(NULL);
9963 //tlbl1 = newiTempLabel(NULL);
9965 //reAdjustPreg(AOP(result));
9967 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9968 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9969 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9971 //pic16_emitcode("add","a,acc");
9972 //pic16_aopPut(AOP(result),"a",offset++);
9974 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9976 // pic16_emitcode("rlc","a");
9977 // pic16_aopPut(AOP(result),"a",offset++);
9979 //reAdjustPreg(AOP(result));
9981 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9982 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9985 tlbl = newiTempLabel(NULL);
9986 tlbl1= newiTempLabel(NULL);
9988 size = AOP_SIZE(result);
9991 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9993 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9995 /* offset should be 0, 1 or 3 */
9997 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9999 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10001 pic16_emitpcode(POC_MOVWF, pctemp);
10004 pic16_emitpLabel(tlbl->key);
10007 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10009 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
10011 pic16_emitpcode(POC_DECFSZ, pctemp);
10012 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10013 pic16_emitpLabel(tlbl1->key);
10015 pic16_popReleaseTempReg(pctemp,1);
10019 pic16_freeAsmop (right,NULL,ic,TRUE);
10020 pic16_freeAsmop(left,NULL,ic,TRUE);
10021 pic16_freeAsmop(result,NULL,ic,TRUE);
10027 #error old code (left here for reference)
10028 /*-----------------------------------------------------------------*/
10029 /* genLeftShift - generates code for left shifting */
10030 /*-----------------------------------------------------------------*/
10031 static void genLeftShift (iCode *ic)
10033 operand *left,*right, *result;
10036 symbol *tlbl , *tlbl1;
10039 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10041 right = IC_RIGHT(ic);
10042 left = IC_LEFT(ic);
10043 result = IC_RESULT(ic);
10045 pic16_aopOp(right,ic,FALSE);
10047 /* if the shift count is known then do it
10048 as efficiently as possible */
10049 if (AOP_TYPE(right) == AOP_LIT) {
10050 pic16_genLeftShiftLiteral (left,right,result,ic);
10054 /* shift count is unknown then we have to form
10055 a loop get the loop count in B : Note: we take
10056 only the lower order byte since shifting
10057 more that 32 bits make no sense anyway, ( the
10058 largest size of an object can be only 32 bits ) */
10061 pic16_aopOp(left,ic,FALSE);
10062 pic16_aopOp(result,ic,FALSE);
10064 /* now move the left to the result if they are not the
10066 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10067 AOP_SIZE(result) > 1) {
10069 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10071 size = AOP_SIZE(result);
10074 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10075 if (*l == '@' && (IS_AOP_PREG(result))) {
10077 pic16_emitcode("mov","a,%s",l);
10078 pic16_aopPut(AOP(result),"a",offset);
10081 /* we don't know if left is a literal or a register, take care -- VR */
10082 mov2f(AOP(result), AOP(left), offset);
10088 size = AOP_SIZE(result);
10090 /* if it is only one byte then */
10092 if(optimized_for_speed) {
10093 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
10094 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
10095 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
10096 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10097 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10098 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
10099 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
10100 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
10101 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
10102 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
10103 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
10104 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
10107 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10109 tlbl = newiTempLabel(NULL);
10110 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10111 mov2f(AOP(result), AOP(left), 0);
10113 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10114 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10117 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10118 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10119 pic16_emitpLabel(tlbl->key);
10120 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10121 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10123 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10128 if (pic16_sameRegs(AOP(left),AOP(result))) {
10130 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10132 tlbl = newiTempLabel(NULL);
10133 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10134 genMultiAsm(POC_RRCF, result, size,1);
10135 pic16_emitpLabel(tlbl->key);
10136 genMultiAsm(POC_RLCF, result, size,0);
10137 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10139 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10143 //tlbl = newiTempLabel(NULL);
10145 //tlbl1 = newiTempLabel(NULL);
10147 //reAdjustPreg(AOP(result));
10149 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10150 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10151 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10153 //pic16_emitcode("add","a,acc");
10154 //pic16_aopPut(AOP(result),"a",offset++);
10156 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10158 // pic16_emitcode("rlc","a");
10159 // pic16_aopPut(AOP(result),"a",offset++);
10161 //reAdjustPreg(AOP(result));
10163 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10164 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10167 tlbl = newiTempLabel(NULL);
10168 tlbl1= newiTempLabel(NULL);
10170 size = AOP_SIZE(result);
10173 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10175 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10177 /* offset should be 0, 1 or 3 */
10179 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10181 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10183 pic16_emitpcode(POC_MOVWF, pctemp);
10186 pic16_emitpLabel(tlbl->key);
10189 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10191 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
10193 pic16_emitpcode(POC_DECFSZ, pctemp);
10194 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10195 pic16_emitpLabel(tlbl1->key);
10197 pic16_popReleaseTempReg(pctemp,1);
10201 pic16_freeAsmop (right,NULL,ic,TRUE);
10202 pic16_freeAsmop(left,NULL,ic,TRUE);
10203 pic16_freeAsmop(result,NULL,ic,TRUE);
10207 /*-----------------------------------------------------------------*/
10208 /* genrshOne - right shift a one byte quantity by known count */
10209 /*-----------------------------------------------------------------*/
10210 static void genrshOne (operand *result, operand *left,
10211 int shCount, int sign)
10213 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10214 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10217 /*-----------------------------------------------------------------*/
10218 /* genrshTwo - right shift two bytes by known amount != 0 */
10219 /*-----------------------------------------------------------------*/
10220 static void genrshTwo (operand *result,operand *left,
10221 int shCount, int sign)
10223 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10224 /* if shCount >= 8 */
10225 if (shCount >= 8) {
10228 shiftR1Left2Result(left, MSB16, result, LSB,
10231 movLeft2Result(left, MSB16, result, LSB);
10233 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
10236 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10237 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
10241 /* 1 <= shCount <= 7 */
10243 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
10246 /*-----------------------------------------------------------------*/
10247 /* shiftRLong - shift right one long from left to result */
10248 /* offl = LSB or MSB16 */
10249 /*-----------------------------------------------------------------*/
10250 static void shiftRLong (operand *left, int offl,
10251 operand *result, int sign)
10253 int size = AOP_SIZE(result);
10254 int same = pic16_sameRegs(AOP(left),AOP(result));
10256 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10258 if (same && (offl == MSB16)) { //shift one byte right
10259 for(i=MSB16;i<size;i++) {
10260 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10261 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10266 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10272 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10274 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10275 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10278 if(offl == MSB16) {
10279 /* add sign of "a" */
10280 pic16_addSign(result, MSB32, sign);
10284 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10286 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10287 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10291 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10293 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10294 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10298 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10301 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10302 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10307 /*-----------------------------------------------------------------*/
10308 /* genrshFour - shift four byte by a known amount != 0 */
10309 /*-----------------------------------------------------------------*/
10310 static void genrshFour (operand *result, operand *left,
10311 int shCount, int sign)
10313 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10314 /* if shifting more that 3 bytes */
10315 if(shCount >= 24 ) {
10318 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10320 movLeft2Result(left, MSB32, result, LSB);
10322 pic16_addSign(result, MSB16, sign);
10324 else if(shCount >= 16){
10327 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10329 movLeft2Result(left, MSB24, result, LSB);
10330 movLeft2Result(left, MSB32, result, MSB16);
10332 pic16_addSign(result, MSB24, sign);
10334 else if(shCount >= 8){
10337 shiftRLong(left, MSB16, result, sign);
10338 else if(shCount == 0){
10339 movLeft2Result(left, MSB16, result, LSB);
10340 movLeft2Result(left, MSB24, result, MSB16);
10341 movLeft2Result(left, MSB32, result, MSB24);
10342 pic16_addSign(result, MSB32, sign);
10344 else{ //shcount >= 2
10345 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10346 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10347 /* the last shift is signed */
10348 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10349 pic16_addSign(result, MSB32, sign);
10352 else{ /* 1 <= shCount <= 7 */
10354 shiftRLong(left, LSB, result, sign);
10356 shiftRLong(result, LSB, result, sign);
10359 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10360 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10361 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10366 /*-----------------------------------------------------------------*/
10367 /* genRightShiftLiteral - right shifting by known count */
10368 /*-----------------------------------------------------------------*/
10369 static void genRightShiftLiteral (operand *left,
10375 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10376 int lsize,res_size;
10378 pic16_freeAsmop(right,NULL,ic,TRUE);
10380 pic16_aopOp(left,ic,FALSE);
10381 pic16_aopOp(result,ic,TRUE);
10383 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10386 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10390 lsize = pic16_getDataSize(left);
10391 res_size = pic16_getDataSize(result);
10392 /* test the LEFT size !!! */
10394 /* I suppose that the left size >= result size */
10396 assert (res_size <= lsize);
10397 while (res_size--) {
10398 mov2f (AOP(result), AOP(left), res_size);
10402 else if(shCount >= (lsize * 8)){
10404 if(res_size == 1) {
10405 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10407 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10408 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
10413 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10414 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10415 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10417 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10422 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10427 switch (res_size) {
10429 genrshOne (result,left,shCount,sign);
10433 genrshTwo (result,left,shCount,sign);
10437 genrshFour (result,left,shCount,sign);
10445 pic16_freeAsmop(left,NULL,ic,TRUE);
10446 pic16_freeAsmop(result,NULL,ic,TRUE);
10449 #if !(USE_GENERIC_SIGNED_SHIFT)
10450 /*-----------------------------------------------------------------*/
10451 /* genSignedRightShift - right shift of signed number */
10452 /*-----------------------------------------------------------------*/
10453 static void genSignedRightShift (iCode *ic)
10455 operand *right, *left, *result;
10458 symbol *tlbl, *tlbl1 ;
10461 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10463 /* we do it the hard way put the shift count in b
10464 and loop thru preserving the sign */
10465 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10467 right = IC_RIGHT(ic);
10468 left = IC_LEFT(ic);
10469 result = IC_RESULT(ic);
10471 pic16_aopOp(right,ic,FALSE);
10472 pic16_aopOp(left,ic,FALSE);
10473 pic16_aopOp(result,ic,FALSE);
10476 if ( AOP_TYPE(right) == AOP_LIT) {
10477 genRightShiftLiteral (left,right,result,ic,1);
10480 /* shift count is unknown then we have to form
10481 a loop get the loop count in B : Note: we take
10482 only the lower order byte since shifting
10483 more that 32 bits make no sense anyway, ( the
10484 largest size of an object can be only 32 bits ) */
10486 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10487 //pic16_emitcode("inc","b");
10488 //pic16_freeAsmop (right,NULL,ic,TRUE);
10489 //pic16_aopOp(left,ic,FALSE);
10490 //pic16_aopOp(result,ic,FALSE);
10492 /* now move the left to the result if they are not the
10494 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10495 AOP_SIZE(result) > 1) {
10497 size = AOP_SIZE(result);
10501 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10502 if (*l == '@' && IS_AOP_PREG(result)) {
10504 pic16_emitcode("mov","a,%s",l);
10505 pic16_aopPut(AOP(result),"a",offset);
10507 pic16_aopPut(AOP(result),l,offset);
10509 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10510 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10516 /* mov the highest order bit to OVR */
10517 tlbl = newiTempLabel(NULL);
10518 tlbl1= newiTempLabel(NULL);
10520 size = AOP_SIZE(result);
10523 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10525 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10527 /* offset should be 0, 1 or 3 */
10528 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10530 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10532 pic16_emitpcode(POC_MOVWF, pctemp);
10535 pic16_emitpLabel(tlbl->key);
10537 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10538 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10541 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10544 pic16_emitpcode(POC_DECFSZ, pctemp);
10545 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10546 pic16_emitpLabel(tlbl1->key);
10548 pic16_popReleaseTempReg(pctemp,1);
10550 size = AOP_SIZE(result);
10552 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10553 pic16_emitcode("rlc","a");
10554 pic16_emitcode("mov","ov,c");
10555 /* if it is only one byte then */
10557 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10559 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10560 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10561 pic16_emitcode("mov","c,ov");
10562 pic16_emitcode("rrc","a");
10563 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10564 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10565 pic16_aopPut(AOP(result),"a",0);
10569 reAdjustPreg(AOP(result));
10570 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10571 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10572 pic16_emitcode("mov","c,ov");
10574 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10576 pic16_emitcode("rrc","a");
10577 pic16_aopPut(AOP(result),"a",offset--);
10579 reAdjustPreg(AOP(result));
10580 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10581 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10586 pic16_freeAsmop(left,NULL,ic,TRUE);
10587 pic16_freeAsmop(result,NULL,ic,TRUE);
10588 pic16_freeAsmop(right,NULL,ic,TRUE);
10592 #if !(USE_GENERIC_SIGNED_SHIFT)
10593 #warning This implementation of genRightShift() is incomplete!
10594 /*-----------------------------------------------------------------*/
10595 /* genRightShift - generate code for right shifting */
10596 /*-----------------------------------------------------------------*/
10597 static void genRightShift (iCode *ic)
10599 operand *right, *left, *result;
10603 symbol *tlbl, *tlbl1 ;
10605 /* if signed then we do it the hard way preserve the
10606 sign bit moving it inwards */
10607 letype = getSpec(operandType(IC_LEFT(ic)));
10608 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10610 if (!SPEC_USIGN(letype)) {
10611 genSignedRightShift (ic);
10615 /* signed & unsigned types are treated the same : i.e. the
10616 signed is NOT propagated inwards : quoting from the
10617 ANSI - standard : "for E1 >> E2, is equivalent to division
10618 by 2**E2 if unsigned or if it has a non-negative value,
10619 otherwise the result is implementation defined ", MY definition
10620 is that the sign does not get propagated */
10622 right = IC_RIGHT(ic);
10623 left = IC_LEFT(ic);
10624 result = IC_RESULT(ic);
10626 pic16_aopOp(right,ic,FALSE);
10628 /* if the shift count is known then do it
10629 as efficiently as possible */
10630 if (AOP_TYPE(right) == AOP_LIT) {
10631 genRightShiftLiteral (left,right,result,ic, 0);
10635 /* shift count is unknown then we have to form
10636 a loop get the loop count in B : Note: we take
10637 only the lower order byte since shifting
10638 more that 32 bits make no sense anyway, ( the
10639 largest size of an object can be only 32 bits ) */
10641 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10642 pic16_emitcode("inc","b");
10643 pic16_aopOp(left,ic,FALSE);
10644 pic16_aopOp(result,ic,FALSE);
10646 /* now move the left to the result if they are not the
10648 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10649 AOP_SIZE(result) > 1) {
10651 size = AOP_SIZE(result);
10654 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10655 if (*l == '@' && IS_AOP_PREG(result)) {
10657 pic16_emitcode("mov","a,%s",l);
10658 pic16_aopPut(AOP(result),"a",offset);
10660 pic16_aopPut(AOP(result),l,offset);
10665 tlbl = newiTempLabel(NULL);
10666 tlbl1= newiTempLabel(NULL);
10667 size = AOP_SIZE(result);
10670 /* if it is only one byte then */
10673 tlbl = newiTempLabel(NULL);
10674 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10675 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10676 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10679 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10680 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10681 pic16_emitpLabel(tlbl->key);
10682 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10683 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10685 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10690 reAdjustPreg(AOP(result));
10691 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10692 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10695 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10697 pic16_emitcode("rrc","a");
10698 pic16_aopPut(AOP(result),"a",offset--);
10700 reAdjustPreg(AOP(result));
10702 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10703 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10706 pic16_freeAsmop(left,NULL,ic,TRUE);
10707 pic16_freeAsmop (right,NULL,ic,TRUE);
10708 pic16_freeAsmop(result,NULL,ic,TRUE);
10712 #if (USE_GENERIC_SIGNED_SHIFT)
10713 /*-----------------------------------------------------------------*/
10714 /* genGenericShift - generates code for left or right shifting */
10715 /*-----------------------------------------------------------------*/
10716 static void genGenericShift (iCode *ic, int isShiftLeft) {
10717 operand *left,*right, *result;
10719 int sign, signedCount;
10720 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10721 PIC_OPCODE pos_shift, neg_shift;
10725 right = IC_RIGHT(ic);
10726 left = IC_LEFT(ic);
10727 result = IC_RESULT(ic);
10729 pic16_aopOp(right,ic,FALSE);
10730 pic16_aopOp(left,ic,FALSE);
10731 pic16_aopOp(result,ic,TRUE);
10733 sign = !SPEC_USIGN(operandType (left));
10734 signedCount = !SPEC_USIGN(operandType (right));
10736 /* if the shift count is known then do it
10737 as efficiently as possible */
10738 if (AOP_TYPE(right) == AOP_LIT) {
10739 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10740 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10741 // we should modify right->aopu.aop_lit here!
10742 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10743 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10745 pic16_genLeftShiftLiteral (left,right,result,ic);
10747 genRightShiftLiteral (left,right,result,ic, sign);
10750 } // if (right is literal)
10752 /* shift count is unknown then we have to form a loop.
10753 * Note: we take only the lower order byte since shifting
10754 * more than 32 bits make no sense anyway, ( the
10755 * largest size of an object can be only 32 bits )
10756 * Note: we perform arithmetic shifts if the left operand is
10757 * signed and we do an (effective) right shift, i. e. we
10758 * shift in the sign bit from the left. */
10760 label_complete = newiTempLabel ( NULL );
10761 label_loop_pos = newiTempLabel ( NULL );
10762 label_loop_neg = NULL;
10763 label_negative = NULL;
10764 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10765 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10768 // additional labels needed
10769 label_loop_neg = newiTempLabel ( NULL );
10770 label_negative = newiTempLabel ( NULL );
10773 // copy source to result -- this will effectively truncate the left operand to the size of result!
10774 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10775 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10776 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10777 mov2f (AOP(result),AOP(left), offset);
10780 // if result is longer than left, fill with zeros (or sign)
10781 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10782 if (sign && AOP_SIZE(left) > 0) {
10783 // shift signed operand -- fill with sign
10784 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10785 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10786 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10787 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10788 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10791 // shift unsigned operand -- fill result with zeros
10792 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10793 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10796 } // if (size mismatch)
10798 pic16_mov2w (AOP(right), 0);
10799 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10800 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10803 // perform a shift by one (shift count is positive)
10804 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10805 // 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])
10806 pic16_emitpLabel (label_loop_pos->key);
10808 if (sign && (pos_shift == POC_RRCF)) {
10809 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10812 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10813 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10814 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10816 // perform a shift by one (shift count is positive)
10817 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10818 // 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])
10819 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10820 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10822 pic16_emitpLabel (label_loop_pos->key);
10823 if (sign && (pos_shift == POC_RRCF)) {
10824 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10827 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10828 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10829 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10830 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10834 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10836 pic16_emitpLabel (label_negative->key);
10837 // perform a shift by -1 (shift count is negative)
10838 // 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)
10840 pic16_emitpLabel (label_loop_neg->key);
10841 if (sign && (neg_shift == POC_RRCF)) {
10842 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10845 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10846 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10847 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10848 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10849 } // if (signedCount)
10851 pic16_emitpLabel (label_complete->key);
10854 pic16_freeAsmop (right,NULL,ic,TRUE);
10855 pic16_freeAsmop(left,NULL,ic,TRUE);
10856 pic16_freeAsmop(result,NULL,ic,TRUE);
10859 static void genLeftShift (iCode *ic) {
10860 genGenericShift (ic, 1);
10863 static void genRightShift (iCode *ic) {
10864 genGenericShift (ic, 0);
10869 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10870 void pic16_loadFSR0(operand *op, int lit)
10872 if(OP_SYMBOL(op)->remat || is_LitOp( op )) {
10873 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10875 assert (!OP_SYMBOL(op)->remat);
10876 // set up FSR0 with address of result
10877 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10878 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10882 /*-----------------------------------------------------------------*/
10883 /* genUnpackBits - generates code for unpacking bits */
10884 /*-----------------------------------------------------------------*/
10885 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10889 sym_link *etype, *letype;
10890 int blen=0, bstr=0;
10894 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10895 etype = getSpec(operandType(result));
10896 letype = getSpec(operandType(left));
10898 // if(IS_BITFIELD(etype)) {
10899 blen = SPEC_BLEN(etype);
10900 bstr = SPEC_BSTR(etype);
10903 lbstr = SPEC_BSTR( letype );
10906 if((blen == 1) && (bstr < 8)) {
10907 /* it is a single bit, so use the appropriate bit instructions */
10908 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10910 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10912 // distinguish (p->bitfield) and p.bitfield, remat seems to work...
10913 if(OP_SYMBOL(left)->remat && (ptype == POINTER) && (result)) {
10914 /* workaround to reduce the extra lfsr instruction */
10915 pic16_emitpcode(POC_BTFSC,
10916 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10918 pic16_loadFSR0 (left, 0);
10919 pic16_emitpcode(POC_BTFSC,
10920 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10923 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10925 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10931 /* the following call to pic16_loadFSR0 is temporary until
10932 * optimization to handle single bit assignments is added
10933 * to the function. Until then use the old safe way! -- VR */
10935 if (OP_SYMBOL(left)->remat) {
10936 // access symbol directly
10937 pic16_mov2w (AOP(left), 0);
10939 pic16_loadFSR0( left, 0 );
10941 /* read the first byte */
10948 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10951 pic16_emitcode("clr","a");
10952 pic16_emitcode("movc","a","@a+dptr");
10958 /* if we have bitdisplacement then it fits */
10959 /* into this byte completely or if length is */
10960 /* less than a byte */
10961 if ((shCnt = SPEC_BSTR(etype)) ||
10962 (SPEC_BLEN(etype) <= 8)) {
10964 /* shift right acc */
10967 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10968 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10970 /* VR -- normally I would use the following, but since we use the hack,
10971 * to avoid the masking from AccRsh, why not mask it right now? */
10974 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10977 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10983 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10984 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10987 /* bit field did not fit in a byte */
10988 rlen = SPEC_BLEN(etype) - 8;
10989 pic16_aopPut(AOP(result),"a",offset++);
10996 pic16_emitcode("inc","%s",rname);
10997 pic16_emitcode("mov","a,@%s",rname);
11001 pic16_emitcode("inc","%s",rname);
11002 pic16_emitcode("movx","a,@%s",rname);
11006 pic16_emitcode("inc","dptr");
11007 pic16_emitcode("movx","a,@dptr");
11011 pic16_emitcode("clr","a");
11012 pic16_emitcode("inc","dptr");
11013 pic16_emitcode("movc","a","@a+dptr");
11017 pic16_emitcode("inc","dptr");
11018 pic16_emitcode("lcall","__gptrget");
11023 /* if we are done */
11027 pic16_aopPut(AOP(result),"a",offset++);
11032 pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
11033 pic16_aopPut(AOP(result),"a",offset);
11040 static void genDataPointerGet(operand *left,
11044 int size, offset = 0, leoffset=0 ;
11046 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11047 pic16_aopOp(result, ic, TRUE);
11049 size = AOP_SIZE(result);
11050 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11054 /* The following tests may save a redudant movff instruction when
11055 * accessing unions */
11057 /* if they are the same */
11058 if (operandsEqu (left, result)) {
11059 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
11065 /* if they are the same registers */
11066 if (pic16_sameRegs(AOP(left),AOP(result))) {
11067 DEBUGpic16_emitcode("; ***", "left and result registers are same");
11073 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
11074 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
11075 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
11082 if ( AOP_TYPE(left) == AOP_PCODE) {
11083 fprintf(stderr,"genDataPointerGet %s, %d\n",
11084 AOP(left)->aopu.pcop->name,
11085 (AOP(left)->aopu.pcop->type == PO_DIR)?
11086 PCOR(AOP(left)->aopu.pcop)->instance:
11087 PCOI(AOP(left)->aopu.pcop)->offset);
11091 if(AOP(left)->aopu.pcop->type == PO_DIR)
11092 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
11094 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11097 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
11099 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
11100 || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
11101 pic16_mov2w(AOP(left), offset); // patch 8
11102 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
11104 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11105 pic16_popGet(AOP(left), offset), //patch 8
11106 pic16_popGet(AOP(result), offset)));
11114 pic16_freeAsmop(result,NULL,ic,TRUE);
11119 /*-----------------------------------------------------------------*/
11120 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
11121 /*-----------------------------------------------------------------*/
11122 static void genNearPointerGet (operand *left,
11126 // asmop *aop = NULL;
11127 //regs *preg = NULL ;
11128 sym_link *rtype, *retype;
11129 sym_link *ltype = operandType(left);
11133 rtype = operandType(result);
11134 retype= getSpec(rtype);
11136 pic16_aopOp(left,ic,FALSE);
11138 // pic16_DumpOp("(left)",left);
11139 // pic16_DumpOp("(result)",result);
11141 /* if left is rematerialisable and
11142 * result is not bit variable type and
11143 * the left is pointer to data space i.e
11144 * lower 128 bytes of space */
11146 if (AOP_TYPE(left) == AOP_PCODE
11147 && !IS_BITFIELD(retype)
11148 && DCL_TYPE(ltype) == POINTER) {
11150 genDataPointerGet (left,result,ic);
11151 pic16_freeAsmop(left, NULL, ic, TRUE);
11155 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11156 pic16_aopOp (result,ic,TRUE);
11158 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11161 if(IS_BITFIELD( retype )
11162 && (SPEC_BLEN(operandType(result))==1)
11166 int bitstrt, bytestrt;
11168 /* if this is bitfield of size 1, see if we are checking the value
11169 * of a single bit in an if-statement,
11170 * if yes, then don't generate usual code, but execute the
11171 * genIfx directly -- VR */
11175 /* CHECK: if next iCode is IFX
11176 * and current result operand is nextic's conditional operand
11177 * and current result operand live ranges ends at nextic's key number
11179 if((nextic->op == IFX)
11180 && (result == IC_COND(nextic))
11181 && (OP_LIVETO(result) == nextic->seq)
11182 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
11184 /* everything is ok then */
11185 /* find a way to optimize the genIfx iCode */
11187 bytestrt = SPEC_BSTR(operandType(result))/8;
11188 bitstrt = SPEC_BSTR(operandType(result))%8;
11190 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
11192 genIfxpCOpJump(nextic, jop);
11194 pic16_freeAsmop(left, NULL, ic, TRUE);
11195 pic16_freeAsmop(result, NULL, ic, TRUE);
11202 /* if the value is already in a pointer register
11203 * then don't need anything more */
11204 if (1 || !AOP_INPREG(AOP(left))) { // AOP_INPREG(AOP(left)) is not always correct...
11205 /* otherwise get a free pointer register */
11206 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11211 /* if bitfield then unpack the bits */
11212 if (IS_BITFIELD(retype))
11213 genUnpackBits (result, left, NULL, POINTER);
11215 /* we have can just get the values */
11216 int size = AOP_SIZE(result);
11219 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11221 pic16_loadFSR0( left, 0 );
11225 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11226 pic16_popGet(AOP(result), offset++)));
11228 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11229 pic16_popGet(AOP(result), offset++)));
11235 /* now some housekeeping stuff */
11237 /* we had to allocate for this iCode */
11238 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11239 pic16_freeAsmop(NULL,aop,ic,TRUE);
11241 /* we did not allocate which means left
11242 * already in a pointer register, then
11243 * if size > 0 && this could be used again
11244 * we have to point it back to where it
11246 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11247 if (AOP_SIZE(result) > 1
11248 && !OP_SYMBOL(left)->remat
11249 && ( OP_SYMBOL(left)->liveTo > ic->seq
11251 // int size = AOP_SIZE(result) - 1;
11253 // pic16_emitcode("dec","%s",rname);
11259 pic16_freeAsmop(left,NULL,ic,TRUE);
11260 pic16_freeAsmop(result,NULL,ic,TRUE);
11263 /*-----------------------------------------------------------------*/
11264 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
11265 /*-----------------------------------------------------------------*/
11266 static void genPagedPointerGet (operand *left,
11271 regs *preg = NULL ;
11273 sym_link *rtype, *retype;
11275 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11277 rtype = operandType(result);
11278 retype= getSpec(rtype);
11280 pic16_aopOp(left,ic,FALSE);
11282 /* if the value is already in a pointer register
11283 then don't need anything more */
11284 if (!AOP_INPREG(AOP(left))) {
11285 /* otherwise get a free pointer register */
11287 preg = getFreePtr(ic,&aop,FALSE);
11288 pic16_emitcode("mov","%s,%s",
11290 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11291 rname = preg->name ;
11293 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11295 pic16_freeAsmop(left,NULL,ic,TRUE);
11296 pic16_aopOp (result,ic,TRUE);
11298 /* if bitfield then unpack the bits */
11299 if (IS_BITFIELD(retype))
11300 genUnpackBits (result,left,rname,PPOINTER);
11302 /* we have can just get the values */
11303 int size = AOP_SIZE(result);
11308 pic16_emitcode("movx","a,@%s",rname);
11309 pic16_aopPut(AOP(result),"a",offset);
11314 pic16_emitcode("inc","%s",rname);
11318 /* now some housekeeping stuff */
11320 /* we had to allocate for this iCode */
11321 pic16_freeAsmop(NULL,aop,ic,TRUE);
11323 /* we did not allocate which means left
11324 already in a pointer register, then
11325 if size > 0 && this could be used again
11326 we have to point it back to where it
11328 if (AOP_SIZE(result) > 1 &&
11329 !OP_SYMBOL(left)->remat &&
11330 ( OP_SYMBOL(left)->liveTo > ic->seq ||
11332 int size = AOP_SIZE(result) - 1;
11334 pic16_emitcode("dec","%s",rname);
11339 pic16_freeAsmop(result,NULL,ic,TRUE);
11344 /*-----------------------------------------------------------------*/
11345 /* genFarPointerGet - gget value from far space */
11346 /*-----------------------------------------------------------------*/
11347 static void genFarPointerGet (operand *left,
11348 operand *result, iCode *ic)
11351 sym_link *retype = getSpec(operandType(result));
11353 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11355 pic16_aopOp(left,ic,FALSE);
11357 /* if the operand is already in dptr
11358 then we do nothing else we move the value to dptr */
11359 if (AOP_TYPE(left) != AOP_STR) {
11360 /* if this is remateriazable */
11361 if (AOP_TYPE(left) == AOP_IMMD)
11362 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11363 else { /* we need to get it byte by byte */
11364 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11365 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11366 if (options.model == MODEL_FLAT24)
11368 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11372 /* so dptr know contains the address */
11373 pic16_freeAsmop(left,NULL,ic,TRUE);
11374 pic16_aopOp(result,ic,TRUE);
11376 /* if bit then unpack */
11377 if (IS_BITFIELD(retype))
11378 genUnpackBits(result,left,"dptr",FPOINTER);
11380 size = AOP_SIZE(result);
11384 pic16_emitcode("movx","a,@dptr");
11385 pic16_aopPut(AOP(result),"a",offset++);
11387 pic16_emitcode("inc","dptr");
11391 pic16_freeAsmop(result,NULL,ic,TRUE);
11395 /*-----------------------------------------------------------------*/
11396 /* genCodePointerGet - get value from code space */
11397 /*-----------------------------------------------------------------*/
11398 static void genCodePointerGet (operand *left,
11399 operand *result, iCode *ic)
11402 sym_link *retype = getSpec(operandType(result));
11404 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11406 pic16_aopOp(left,ic,FALSE);
11408 /* if the operand is already in dptr
11409 then we do nothing else we move the value to dptr */
11410 if (AOP_TYPE(left) != AOP_STR) {
11411 /* if this is remateriazable */
11412 if (AOP_TYPE(left) == AOP_IMMD)
11413 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11414 else { /* we need to get it byte by byte */
11415 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11416 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11417 if (options.model == MODEL_FLAT24)
11419 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11423 /* so dptr know contains the address */
11424 pic16_freeAsmop(left,NULL,ic,TRUE);
11425 pic16_aopOp(result,ic,FALSE);
11427 /* if bit then unpack */
11428 if (IS_BITFIELD(retype))
11429 genUnpackBits(result,left,"dptr",CPOINTER);
11431 size = AOP_SIZE(result);
11435 pic16_emitcode("clr","a");
11436 pic16_emitcode("movc","a,@a+dptr");
11437 pic16_aopPut(AOP(result),"a",offset++);
11439 pic16_emitcode("inc","dptr");
11443 pic16_freeAsmop(result,NULL,ic,TRUE);
11448 /*-----------------------------------------------------------------*/
11449 /* genGenPointerGet - gget value from generic pointer space */
11450 /*-----------------------------------------------------------------*/
11451 static void genGenPointerGet (operand *left,
11452 operand *result, iCode *ic)
11454 int size, offset, lit;
11455 sym_link *retype = getSpec(operandType(result));
11457 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11458 pic16_aopOp(left,ic,FALSE);
11459 pic16_aopOp(result,ic,FALSE);
11460 size = AOP_SIZE(result);
11462 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11464 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11466 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11467 // load FSR0 from immediate
11468 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11470 // pic16_loadFSR0( left );
11475 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11477 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11484 else { /* we need to get it byte by byte */
11485 // set up FSR0 with address from left
11486 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11487 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11493 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11495 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11502 /* if bit then unpack */
11503 if (IS_BITFIELD(retype))
11504 genUnpackBits(result,left,"BAD",GPOINTER);
11507 pic16_freeAsmop(left,NULL,ic,TRUE);
11508 pic16_freeAsmop(result,NULL,ic,TRUE);
11514 /*-----------------------------------------------------------------*/
11515 /* genGenPointerGet - gget value from generic pointer space */
11516 /*-----------------------------------------------------------------*/
11517 static void genGenPointerGet (operand *left,
11518 operand *result, iCode *ic)
11520 int size, offset, lit;
11521 sym_link *retype = getSpec(operandType(result));
11524 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11525 pic16_aopOp(left,ic,FALSE);
11526 pic16_aopOp(result,ic,TRUE);
11527 size = AOP_SIZE(result);
11529 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11531 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11533 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11534 // load FSR0 from immediate
11535 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11537 werror(W_POSSBUG2, __FILE__, __LINE__);
11542 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11544 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11551 } else { /* we need to get it byte by byte */
11553 /* set up WREG:PRODL:FSR0L with address from left */
11554 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11555 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11556 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11559 case 1: strcpy(fgptrget, "__gptrget1"); break;
11560 case 2: strcpy(fgptrget, "__gptrget2"); break;
11561 case 3: strcpy(fgptrget, "__gptrget3"); break;
11562 case 4: strcpy(fgptrget, "__gptrget4"); break;
11564 werror(W_POSSBUG2, __FILE__, __LINE__);
11568 pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
11570 assignResultValue(result, 1);
11575 sym = newSymbol( fgptrget, 0 );
11577 strcpy(sym->rname, fgptrget);
11578 checkAddSym(&externs, sym);
11580 // fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
11586 /* if bit then unpack */
11587 if (IS_BITFIELD(retype))
11588 genUnpackBits(result,left,"BAD",GPOINTER);
11591 pic16_freeAsmop(left,NULL,ic,TRUE);
11592 pic16_freeAsmop(result,NULL,ic,TRUE);
11595 /*-----------------------------------------------------------------*/
11596 /* genConstPointerGet - get value from const generic pointer space */
11597 /*-----------------------------------------------------------------*/
11598 static void genConstPointerGet (operand *left,
11599 operand *result, iCode *ic)
11601 //sym_link *retype = getSpec(operandType(result));
11602 // symbol *albl = newiTempLabel(NULL); // patch 15
11603 // symbol *blbl = newiTempLabel(NULL); //
11604 // PIC_OPCODE poc; // patch 15
11608 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11609 pic16_aopOp(left,ic,FALSE);
11610 pic16_aopOp(result,ic,TRUE);
11611 size = AOP_SIZE(result);
11613 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11615 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11617 // set up table pointer
11618 if( (AOP_TYPE(left) == AOP_PCODE)
11619 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11620 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11622 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11623 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11624 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11625 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11626 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11627 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11629 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11630 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11631 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11635 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11636 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11640 pic16_freeAsmop(left,NULL,ic,TRUE);
11641 pic16_freeAsmop(result,NULL,ic,TRUE);
11645 /*-----------------------------------------------------------------*/
11646 /* genPointerGet - generate code for pointer get */
11647 /*-----------------------------------------------------------------*/
11648 static void genPointerGet (iCode *ic)
11650 operand *left, *result ;
11651 sym_link *type, *etype;
11656 left = IC_LEFT(ic);
11657 result = IC_RESULT(ic) ;
11659 /* depending on the type of pointer we need to
11660 move it to the correct pointer register */
11661 type = operandType(left);
11662 etype = getSpec(type);
11665 if (IS_PTR_CONST(type))
11667 if (IS_CODEPTR(type))
11669 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11671 /* if left is of type of pointer then it is simple */
11672 if (IS_PTR(type) && !IS_FUNC(type->next))
11673 p_type = DCL_TYPE(type);
11675 /* we have to go by the storage class */
11676 p_type = PTR_TYPE(SPEC_OCLS(etype));
11678 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11680 if (SPEC_OCLS(etype)->codesp ) {
11681 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11682 //p_type = CPOINTER ;
11684 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11685 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11686 /*p_type = FPOINTER ;*/
11688 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11689 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11690 /* p_type = PPOINTER; */
11692 if (SPEC_OCLS(etype) == idata ) {
11693 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11694 /* p_type = IPOINTER; */
11696 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11697 /* p_type = POINTER ; */
11701 /* now that we have the pointer type we assign
11702 the pointer values */
11706 genNearPointerGet (left,result,ic);
11710 genPagedPointerGet(left,result,ic);
11714 genFarPointerGet (left,result,ic);
11718 genConstPointerGet (left,result,ic);
11719 //pic16_emitcodePointerGet (left,result,ic);
11724 if (IS_PTR_CONST(type))
11725 genConstPointerGet (left,result,ic);
11728 genGenPointerGet (left,result,ic);
11732 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11733 "genPointerGet: illegal pointer type");
11738 /*-----------------------------------------------------------------*/
11739 /* genPackBits - generates code for packed bit storage */
11740 /*-----------------------------------------------------------------*/
11741 static void genPackBits (sym_link *etype , operand *result,
11743 char *rname, int p_type)
11751 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11752 blen = SPEC_BLEN(etype);
11753 bstr = SPEC_BSTR(etype);
11755 retype = getSpec(operandType(right));
11757 if(AOP_TYPE(right) == AOP_LIT) {
11758 if((blen == 1) && (bstr < 8)) {
11760 /* it is a single bit, so use the appropriate bit instructions */
11762 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11764 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11765 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11766 if(OP_SYMBOL(result)->remat && (p_type == POINTER) && (result)) {
11767 /* workaround to reduce the extra lfsr instruction */
11769 pic16_emitpcode(POC_BSF,
11770 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11772 pic16_emitpcode(POC_BCF,
11773 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11776 pic16_loadFSR0(result, 0);
11778 pic16_emitpcode(POC_BSF,
11779 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11781 pic16_emitpcode(POC_BCF,
11782 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11788 /* move literal to W */
11789 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11792 if(IS_BITFIELD(retype)
11793 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11797 rblen = SPEC_BLEN( retype );
11798 rbstr = SPEC_BSTR( retype );
11801 if(IS_BITFIELD(etype)) {
11802 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11803 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11805 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11808 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11810 if(IS_BITFIELD(etype)) {
11811 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11813 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11816 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11820 /* move right to W */
11821 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11824 /* if the bit length is less than or */
11825 /* it exactly fits a byte then */
11826 if((shCnt=SPEC_BSTR(etype))
11827 || SPEC_BLEN(etype) <= 8 ) {
11828 int fsr0_setup = 0;
11830 if (blen != 8 || bstr != 0) {
11831 // we need to combine the value with the old value
11832 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11834 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11835 SPEC_BSTR(etype), SPEC_BLEN(etype));
11837 /* shift left acc */
11840 /* using PRODH as a temporary register here */
11841 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11843 if (OP_SYMBOL(result)->remat) {
11844 // access symbol directly
11845 pic16_mov2w (AOP(result), 0);
11847 /* get old value */
11851 pic16_loadFSR0( result, 0 );
11853 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11854 // pic16_emitcode ("mov","b,a");
11855 // pic16_emitcode("mov","a,@%s",rname);
11859 if (AOP(result)->aopu.aop_reg[2]) {
11860 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
11861 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11862 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11863 pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11864 pic16_emitpcode (POC_CALL, pic16_popGetWithString ("__gptrget1"));
11867 sym = newSymbol( "__gptrget1", 0 );
11868 strcpy(sym->rname, "__gptrget1");
11869 checkAddSym(&externs, sym);
11872 // data pointer (just 2 byte given)
11873 pic16_loadFSR0( result, 0 );
11875 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11878 // warnings will be emitted below
11879 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER...");
11880 //werror(W_POSSBUG2, __FILE__, __LINE__);
11884 assert (0 && "invalid pointer type specified");
11889 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11890 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11891 (unsigned char)(0xff >> (8-bstr))) ));
11892 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11893 } // if (blen != 8 || bstr != 0)
11895 /* write new value back */
11896 if (OP_SYMBOL(result)->remat) {
11897 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11902 if (!fsr0_setup) pic16_loadFSR0( result, 0 );
11903 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11907 if (AOP(result)->aopu.aop_reg[2]) {
11908 // prepare call to __gptrset1, this is actually genGenPointerSet(WREG, result, ?ic?)
11909 pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (pic16_stack_postdec/*pic16_pc_postdec1*/));
11910 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11911 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11912 pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11913 pic16_emitpcode (POC_CALL, pic16_popGetWithString ("__gptrput1"));
11916 sym = newSymbol( "__gptrput1", 0 );
11917 strcpy(sym->rname, "__gptrput1");
11918 checkAddSym(&externs, sym);
11921 // data pointer (just 2 byte given)
11922 if (!fsr0_setup) pic16_loadFSR0( result, 0 );
11923 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11926 // this should work in all cases (as soon as gptrget/gptrput work on EEPROM and PROGRAM MEMORY)
11927 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER access");
11928 werror(W_POSSBUG2, __FILE__, __LINE__);
11932 assert (0 && "invalid pointer type specified");
11943 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11944 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11949 pic16_loadFSR0(result, 0); // load FSR0 with address of result
11950 rLen = SPEC_BLEN(etype)-8;
11952 /* now generate for lengths greater than one byte */
11956 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11962 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11968 pic16_emitcode("movx","@dptr,a");
11973 DEBUGpic16_emitcode(";lcall","__gptrput");
11981 pic16_mov2w(AOP(right), offset++);
11984 /* last last was not complete */
11986 /* save the byte & read byte */
11989 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11990 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11995 pic16_emitcode ("mov","b,a");
11996 pic16_emitcode("movx","a,@dptr");
12000 pic16_emitcode ("push","b");
12001 pic16_emitcode ("push","acc");
12002 pic16_emitcode ("lcall","__gptrget");
12003 pic16_emitcode ("pop","b");
12009 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
12010 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
12011 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
12012 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
12013 // pic16_emitcode ("orl","a,b");
12016 // if (p_type == GPOINTER)
12017 // pic16_emitcode("pop","b");
12022 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12023 // pic16_emitcode("mov","@%s,a",rname);
12027 pic16_emitcode("movx","@dptr,a");
12031 DEBUGpic16_emitcode(";lcall","__gptrput");
12038 // pic16_freeAsmop(right, NULL, ic, TRUE);
12040 /*-----------------------------------------------------------------*/
12041 /* genDataPointerSet - remat pointer to data space */
12042 /*-----------------------------------------------------------------*/
12043 static void genDataPointerSet(operand *right,
12047 int size, offset = 0, resoffset=0 ;
12049 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12050 pic16_aopOp(right,ic,FALSE);
12052 size = AOP_SIZE(right);
12054 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
12057 if ( AOP_TYPE(result) == AOP_PCODE) {
12058 fprintf(stderr,"genDataPointerSet %s, %d\n",
12059 AOP(result)->aopu.pcop->name,
12060 (AOP(result)->aopu.pcop->type == PO_DIR)?
12061 PCOR(AOP(result)->aopu.pcop)->instance:
12062 PCOI(AOP(result)->aopu.pcop)->offset);
12066 if(AOP(result)->aopu.pcop->type == PO_DIR)
12067 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
12070 if (AOP_TYPE(right) == AOP_LIT) {
12073 if(!IS_FLOAT(operandType( right )))
12074 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
12077 unsigned long lit_int;
12081 /* take care if literal is a float */
12082 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
12083 lit = info.lit_int;
12086 lit = lit >> (8*offset);
12088 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
12089 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
12091 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
12094 pic16_mov2w(AOP(right), offset);
12095 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
12101 pic16_freeAsmop(right,NULL,ic,TRUE);
12106 /*-----------------------------------------------------------------*/
12107 /* genNearPointerSet - pic16_emitcode for near pointer put */
12108 /*-----------------------------------------------------------------*/
12109 static void genNearPointerSet (operand *right,
12115 sym_link *ptype = operandType(result);
12116 sym_link *resetype;
12118 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12119 retype= getSpec(operandType(right));
12120 resetype = getSpec(operandType(result));
12122 pic16_aopOp(result,ic,FALSE);
12124 /* if the result is rematerializable &
12125 * in data space & not a bit variable */
12127 /* and result is not a bit variable */
12128 if (AOP_TYPE(result) == AOP_PCODE
12129 // && AOP_TYPE(result) == AOP_IMMD
12130 && DCL_TYPE(ptype) == POINTER
12131 && !IS_BITFIELD(retype)
12132 && !IS_BITFIELD(resetype)) {
12134 genDataPointerSet (right,result,ic);
12135 pic16_freeAsmop(result,NULL,ic,TRUE);
12139 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12140 pic16_aopOp(right,ic,FALSE);
12141 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12143 /* if the value is already in a pointer register
12144 * then don't need anything more */
12145 if (1 || !AOP_INPREG(AOP(result))) { // AOP_INPREG(AOP(result)) is not always correct...
12146 /* otherwise get a free pointer register */
12147 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12152 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12154 /* if bitfield then unpack the bits */
12155 if (IS_BITFIELD(resetype)) {
12156 genPackBits (resetype, result, right, NULL, POINTER);
12158 /* we have can just get the values */
12159 int size = AOP_SIZE(right);
12162 pic16_loadFSR0(result, 0);
12164 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12166 if (AOP_TYPE(right) == AOP_LIT) {
12167 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12169 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12171 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12173 } else { // no literal
12175 pic16_emitpcode(POC_MOVFF,
12176 pic16_popGet2p(pic16_popGet(AOP(right),offset),
12177 pic16_popCopyReg(&pic16_pc_postinc0)));
12179 pic16_emitpcode(POC_MOVFF,
12180 pic16_popGet2p(pic16_popGet(AOP(right),offset),
12181 pic16_popCopyReg(&pic16_pc_indf0)));
12188 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12189 /* now some housekeeping stuff */
12191 /* we had to allocate for this iCode */
12192 pic16_freeAsmop(NULL,aop,ic,TRUE);
12194 /* we did not allocate which means left
12195 * already in a pointer register, then
12196 * if size > 0 && this could be used again
12197 * we have to point it back to where it
12199 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12200 if (AOP_SIZE(right) > 1
12201 && !OP_SYMBOL(result)->remat
12202 && ( OP_SYMBOL(result)->liveTo > ic->seq
12205 int size = AOP_SIZE(right) - 1;
12208 pic16_emitcode("decf","fsr0,f");
12209 //pic16_emitcode("dec","%s",rname);
12213 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12216 pic16_freeAsmop(right,NULL,ic,TRUE);
12217 pic16_freeAsmop(result,NULL,ic,TRUE);
12220 /*-----------------------------------------------------------------*/
12221 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
12222 /*-----------------------------------------------------------------*/
12223 static void genPagedPointerSet (operand *right,
12228 regs *preg = NULL ;
12232 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12234 retype= getSpec(operandType(right));
12236 pic16_aopOp(result,ic,FALSE);
12238 /* if the value is already in a pointer register
12239 then don't need anything more */
12240 if (!AOP_INPREG(AOP(result))) {
12241 /* otherwise get a free pointer register */
12243 preg = getFreePtr(ic,&aop,FALSE);
12244 pic16_emitcode("mov","%s,%s",
12246 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12247 rname = preg->name ;
12249 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12251 pic16_freeAsmop(result,NULL,ic,TRUE);
12252 pic16_aopOp (right,ic,FALSE);
12254 /* if bitfield then unpack the bits */
12255 if (IS_BITFIELD(retype))
12256 genPackBits (retype,result,right,rname,PPOINTER);
12258 /* we have can just get the values */
12259 int size = AOP_SIZE(right);
12263 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12266 pic16_emitcode("movx","@%s,a",rname);
12269 pic16_emitcode("inc","%s",rname);
12275 /* now some housekeeping stuff */
12277 /* we had to allocate for this iCode */
12278 pic16_freeAsmop(NULL,aop,ic,TRUE);
12280 /* we did not allocate which means left
12281 already in a pointer register, then
12282 if size > 0 && this could be used again
12283 we have to point it back to where it
12285 if (AOP_SIZE(right) > 1 &&
12286 !OP_SYMBOL(result)->remat &&
12287 ( OP_SYMBOL(result)->liveTo > ic->seq ||
12289 int size = AOP_SIZE(right) - 1;
12291 pic16_emitcode("dec","%s",rname);
12296 pic16_freeAsmop(right,NULL,ic,TRUE);
12301 /*-----------------------------------------------------------------*/
12302 /* genFarPointerSet - set value from far space */
12303 /*-----------------------------------------------------------------*/
12304 static void genFarPointerSet (operand *right,
12305 operand *result, iCode *ic)
12308 sym_link *retype = getSpec(operandType(right));
12310 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12311 pic16_aopOp(result,ic,FALSE);
12313 /* if the operand is already in dptr
12314 then we do nothing else we move the value to dptr */
12315 if (AOP_TYPE(result) != AOP_STR) {
12316 /* if this is remateriazable */
12317 if (AOP_TYPE(result) == AOP_IMMD)
12318 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12319 else { /* we need to get it byte by byte */
12320 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12321 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12322 if (options.model == MODEL_FLAT24)
12324 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12328 /* so dptr know contains the address */
12329 pic16_freeAsmop(result,NULL,ic,TRUE);
12330 pic16_aopOp(right,ic,FALSE);
12332 /* if bit then unpack */
12333 if (IS_BITFIELD(retype))
12334 genPackBits(retype,result,right,"dptr",FPOINTER);
12336 size = AOP_SIZE(right);
12340 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12342 pic16_emitcode("movx","@dptr,a");
12344 pic16_emitcode("inc","dptr");
12348 pic16_freeAsmop(right,NULL,ic,TRUE);
12351 /*-----------------------------------------------------------------*/
12352 /* genGenPointerSet - set value from generic pointer space */
12353 /*-----------------------------------------------------------------*/
12355 static void genGenPointerSet (operand *right,
12356 operand *result, iCode *ic)
12358 int i, size, offset, lit;
12359 sym_link *retype = getSpec(operandType(right));
12361 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12363 pic16_aopOp(result,ic,FALSE);
12364 pic16_aopOp(right,ic,FALSE);
12365 size = AOP_SIZE(right);
12368 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12370 /* if the operand is already in dptr
12371 then we do nothing else we move the value to dptr */
12372 if (AOP_TYPE(result) != AOP_STR) {
12373 /* if this is remateriazable */
12374 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12375 // WARNING: anythig until "else" is untested!
12376 if (AOP_TYPE(result) == AOP_IMMD) {
12377 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12378 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12379 // load FSR0 from immediate
12380 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12384 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12386 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12392 else { /* we need to get it byte by byte */
12393 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12394 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12396 // set up FSR0 with address of result
12397 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12398 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12400 /* hack hack! see if this the FSR. If so don't load W */
12401 if(AOP_TYPE(right) != AOP_ACC) {
12403 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12405 if(AOP_TYPE(right) == AOP_LIT)
12408 // note: pic16_popGet handles sign extension
12409 for(i=0;i<size;i++) {
12410 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12412 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12414 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12419 for(i=0;i<size;i++) {
12421 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12422 pic16_popCopyReg(&pic16_pc_postinc0)));
12424 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12425 pic16_popCopyReg(&pic16_pc_indf0)));
12431 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12432 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12434 } // if (AOP_TYPE(result) != AOP_IMMD)
12436 } // if (AOP_TYPE(result) != AOP_STR)
12437 /* so dptr know contains the address */
12440 /* if bit then unpack */
12441 if (IS_BITFIELD(retype))
12442 genPackBits(retype,result,right,"dptr",GPOINTER);
12444 size = AOP_SIZE(right);
12447 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12449 // set up FSR0 with address of result
12450 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12451 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12454 if (AOP_TYPE(right) == AOP_LIT) {
12455 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12457 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12459 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12461 } else { // no literal
12463 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12465 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12473 pic16_freeAsmop(right,NULL,ic,TRUE);
12474 pic16_freeAsmop(result,NULL,ic,TRUE);
12478 static void genGenPointerSet (operand *right,
12479 operand *result, iCode *ic)
12482 sym_link *retype = getSpec(operandType(right));
12485 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12487 pic16_aopOp(result,ic,FALSE);
12488 pic16_aopOp(right,ic,FALSE);
12489 size = AOP_SIZE(right);
12491 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12494 /* if bit then unpack */
12495 if (IS_BITFIELD(retype)) {
12496 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12497 genPackBits(retype,result,right,"dptr",GPOINTER);
12501 size = AOP_SIZE(right);
12503 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12507 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12509 /* value of right+0 is placed on stack, which will be retrieved
12510 * by the support function this restoring the stack. The important
12511 * thing is that there is no need to manually restore stack pointer
12513 pushaop(AOP(right), 0);
12514 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12515 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12516 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12517 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12519 /* load address to write to in WREG:FSR0H:FSR0L */
12520 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12521 pic16_popCopyReg(&pic16_pc_fsr0l)));
12522 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12523 pic16_popCopyReg(&pic16_pc_prodl)));
12524 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12527 /* put code here */
12529 case 1: strcpy(fgptrput, "__gptrput1"); break;
12530 case 2: strcpy(fgptrput, "__gptrput2"); break;
12531 case 3: strcpy(fgptrput, "__gptrput3"); break;
12532 case 4: strcpy(fgptrput, "__gptrput4"); break;
12534 werror(W_POSSBUG2, __FILE__, __LINE__);
12538 pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
12543 sym = newSymbol( fgptrput, 0 );
12545 strcpy(sym->rname, fgptrput);
12546 checkAddSym(&externs, sym);
12550 pic16_freeAsmop(right,NULL,ic,TRUE);
12551 pic16_freeAsmop(result,NULL,ic,TRUE);
12554 /*-----------------------------------------------------------------*/
12555 /* genPointerSet - stores the value into a pointer location */
12556 /*-----------------------------------------------------------------*/
12557 static void genPointerSet (iCode *ic)
12559 operand *right, *result ;
12560 sym_link *type, *etype;
12565 right = IC_RIGHT(ic);
12566 result = IC_RESULT(ic) ;
12568 /* depending on the type of pointer we need to
12569 move it to the correct pointer register */
12570 type = operandType(result);
12571 etype = getSpec(type);
12572 /* if left is of type of pointer then it is simple */
12573 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12574 p_type = DCL_TYPE(type);
12577 /* we have to go by the storage class */
12578 p_type = PTR_TYPE(SPEC_OCLS(etype));
12580 /* if (SPEC_OCLS(etype)->codesp ) { */
12581 /* p_type = CPOINTER ; */
12584 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12585 /* p_type = FPOINTER ; */
12587 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12588 /* p_type = PPOINTER ; */
12590 /* if (SPEC_OCLS(etype) == idata ) */
12591 /* p_type = IPOINTER ; */
12593 /* p_type = POINTER ; */
12596 /* now that we have the pointer type we assign
12597 the pointer values */
12601 genNearPointerSet (right,result,ic);
12605 genPagedPointerSet (right,result,ic);
12609 genFarPointerSet (right,result,ic);
12613 genGenPointerSet (right,result,ic);
12617 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12618 "genPointerSet: illegal pointer type");
12622 /*-----------------------------------------------------------------*/
12623 /* genIfx - generate code for Ifx statement */
12624 /*-----------------------------------------------------------------*/
12625 static void genIfx (iCode *ic, iCode *popIc)
12627 operand *cond = IC_COND(ic);
12632 pic16_aopOp(cond,ic,FALSE);
12634 /* get the value into acc */
12635 if (AOP_TYPE(cond) != AOP_CRY)
12636 pic16_toBoolean(cond);
12639 /* the result is now in the accumulator */
12640 pic16_freeAsmop(cond,NULL,ic,TRUE);
12642 /* if there was something to be popped then do it */
12646 /* if the condition is a bit variable */
12647 if (isbit && IS_ITEMP(cond) &&
12649 genIfxJump(ic,"c");
12650 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12652 if (isbit && !IS_ITEMP(cond))
12653 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12655 genIfxJump(ic,"a");
12660 /*-----------------------------------------------------------------*/
12661 /* genAddrOf - generates code for address of */
12662 /*-----------------------------------------------------------------*/
12663 static void genAddrOf (iCode *ic)
12665 operand *result, *left;
12667 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12668 pCodeOp *pcop0, *pcop1, *pcop2;
12672 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12674 sym = OP_SYMBOL( IC_LEFT(ic) );
12677 /* get address of symbol on stack */
12678 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12680 fprintf(stderr, "%s:%d symbol %s on stack offset %d\n", __FILE__, __LINE__,
12681 OP_SYMBOL(left)->name, OP_SYMBOL(left)->stack);
12684 // operands on stack are accessible via "FSR2 + index" with index
12685 // starting at 2 for arguments and growing from 0 downwards for
12686 // local variables (index == 0 is not assigned so we add one here)
12688 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12690 assert (soffs < 0);
12693 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12694 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12695 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12696 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12697 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12698 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12699 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12705 // if(pic16_debug_verbose) {
12706 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12707 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12710 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12711 size = AOP_SIZE(IC_RESULT(ic));
12713 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12714 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12715 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12718 pic16_emitpcode(POC_MOVLW, pcop0);
12719 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12720 pic16_emitpcode(POC_MOVLW, pcop1);
12721 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12722 pic16_emitpcode(POC_MOVLW, pcop2);
12723 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12726 pic16_emitpcode(POC_MOVLW, pcop0);
12727 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12728 pic16_emitpcode(POC_MOVLW, pcop1);
12729 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12731 pic16_emitpcode(POC_MOVLW, pcop0);
12732 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12735 pic16_freeAsmop(left, NULL, ic, FALSE);
12737 pic16_freeAsmop(result,NULL,ic,TRUE);
12742 /*-----------------------------------------------------------------*/
12743 /* genFarFarAssign - assignment when both are in far space */
12744 /*-----------------------------------------------------------------*/
12745 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12747 int size = AOP_SIZE(right);
12750 /* first push the right side on to the stack */
12752 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12754 pic16_emitcode ("push","acc");
12757 pic16_freeAsmop(right,NULL,ic,FALSE);
12758 /* now assign DPTR to result */
12759 pic16_aopOp(result,ic,FALSE);
12760 size = AOP_SIZE(result);
12762 pic16_emitcode ("pop","acc");
12763 pic16_aopPut(AOP(result),"a",--offset);
12765 pic16_freeAsmop(result,NULL,ic,FALSE);
12770 /*-----------------------------------------------------------------*/
12771 /* genAssign - generate code for assignment */
12772 /*-----------------------------------------------------------------*/
12773 static void genAssign (iCode *ic)
12775 operand *result, *right;
12776 int size, offset,know_W;
12777 unsigned long lit = 0L;
12779 result = IC_RESULT(ic);
12780 right = IC_RIGHT(ic) ;
12784 /* if they are the same */
12785 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12788 /* reversed order operands are aopOp'ed so that result operand
12789 * is effective in case right is a stack symbol. This maneauver
12790 * allows to use the _G.resDirect flag later */
12791 pic16_aopOp(result,ic,TRUE);
12792 pic16_aopOp(right,ic,FALSE);
12794 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12796 /* if they are the same registers */
12797 if (pic16_sameRegs(AOP(right),AOP(result)))
12800 /* if the result is a bit */
12801 if (AOP_TYPE(result) == AOP_CRY) {
12802 /* if the right size is a literal then
12803 we know what the value is */
12804 if (AOP_TYPE(right) == AOP_LIT) {
12806 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12807 pic16_popGet(AOP(result),0));
12809 if (((int) operandLitValue(right)))
12810 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12811 AOP(result)->aopu.aop_dir,
12812 AOP(result)->aopu.aop_dir);
12814 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12815 AOP(result)->aopu.aop_dir,
12816 AOP(result)->aopu.aop_dir);
12820 /* the right is also a bit variable */
12821 if (AOP_TYPE(right) == AOP_CRY) {
12822 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12823 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12824 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12826 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12827 AOP(result)->aopu.aop_dir,
12828 AOP(result)->aopu.aop_dir);
12829 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12830 AOP(right)->aopu.aop_dir,
12831 AOP(right)->aopu.aop_dir);
12832 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12833 AOP(result)->aopu.aop_dir,
12834 AOP(result)->aopu.aop_dir);
12838 /* we need to or */
12839 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12840 pic16_toBoolean(right);
12842 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12843 //pic16_aopPut(AOP(result),"a",0);
12847 /* bit variables done */
12849 size = AOP_SIZE(result);
12852 if(AOP_TYPE(right) == AOP_LIT) {
12853 if(!IS_FLOAT(operandType( right )))
12854 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12857 unsigned long lit_int;
12861 /* take care if literal is a float */
12862 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12863 lit = info.lit_int;
12867 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12868 // sizeof(unsigned long int), sizeof(float));
12871 if (AOP_TYPE(right) == AOP_REG) {
12872 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12875 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12880 if(AOP_TYPE(right) != AOP_LIT
12881 && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12882 && !IS_FUNC(OP_SYM_TYPE(right))
12884 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12885 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12887 // set up table pointer
12888 if(is_LitOp(right)) {
12889 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12890 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12891 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12892 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12893 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12894 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12895 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12897 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12898 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12899 pic16_popCopyReg(&pic16_pc_tblptrl)));
12900 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12901 pic16_popCopyReg(&pic16_pc_tblptrh)));
12902 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12903 pic16_popCopyReg(&pic16_pc_tblptru)));
12906 size = min(getSize(OP_SYM_ETYPE(right)), AOP_SIZE(result));
12908 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12909 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12910 pic16_popGet(AOP(result),offset)));
12914 size = getSize(OP_SYM_ETYPE(right));
12915 if(AOP_SIZE(result) > size) {
12916 size = AOP_SIZE(result) - size;
12918 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12928 /* VR - What is this?! */
12929 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12930 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12931 if(aopIdx(AOP(result),0) == 4) {
12933 /* this is a workaround to save value of right into wreg too,
12934 * value of wreg is going to be used later */
12935 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12936 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12937 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12941 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12947 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12948 if(AOP_TYPE(right) == AOP_LIT) {
12950 if(know_W != (lit&0xff))
12951 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12953 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12955 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12959 } else if (AOP_TYPE(right) == AOP_CRY) {
12960 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12962 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12963 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12964 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12966 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12967 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12968 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12970 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12972 if(!_G.resDirect) /* use this aopForSym feature */
12973 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12980 pic16_freeAsmop (right,NULL,ic,FALSE);
12981 pic16_freeAsmop (result,NULL,ic,TRUE);
12984 /*-----------------------------------------------------------------*/
12985 /* genJumpTab - generates code for jump table */
12986 /*-----------------------------------------------------------------*/
12987 static void genJumpTab (iCode *ic)
12992 pCodeOp *jt_offs_hi;
12997 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12998 /* get the condition into accumulator */
12999 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
13001 /* multiply by three */
13002 pic16_emitcode("add","a,acc");
13003 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
13005 jtab = newiTempLabel(NULL);
13006 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
13007 pic16_emitcode("jmp","@a+dptr");
13008 pic16_emitcode("","%05d_DS_:",jtab->key+100);
13011 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
13012 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
13014 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
13015 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
13016 pic16_emitpLabel(jtab->key);
13020 jt_offs = pic16_popGetTempReg(0);
13021 jt_offs_hi = pic16_popGetTempReg(1);
13022 jt_label = pic16_popGetLabel (jtab->key);
13023 //fprintf (stderr, "Creating jump table...\n");
13025 // calculate offset into jump table (idx * sizeof (GOTO))
13026 pic16_emitpcode(POC_CLRF , jt_offs_hi);
13027 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
13028 pic16_emitpcode(POC_RLCF , jt_offs_hi);
13029 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
13030 pic16_emitpcode(POC_RLCF , jt_offs_hi);
13031 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
13032 pic16_emitpcode(POC_MOVWF , jt_offs);
13034 // prepare PCLATx (set to first entry in jump table)
13035 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
13036 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
13037 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
13038 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
13039 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
13041 // set PCLATx to selected entry (new PCL is stored in jt_offs)
13042 pic16_emitpcode(POC_ADDWF , jt_offs);
13043 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
13044 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
13046 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
13048 // release temporaries and prepare jump into table (new PCL --> WREG)
13049 pic16_emitpcode(POC_MOVFW , jt_offs);
13050 pic16_popReleaseTempReg (jt_offs_hi, 1);
13051 pic16_popReleaseTempReg (jt_offs, 0);
13053 // jump into the table
13054 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
13056 pic16_emitpLabelFORCE(jtab->key);
13059 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
13061 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
13062 /* now generate the jump labels */
13063 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
13064 jtab = setNextItem(IC_JTLABELS(ic))) {
13065 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
13066 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
13069 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
13073 /*-----------------------------------------------------------------*/
13074 /* genMixedOperation - gen code for operators between mixed types */
13075 /*-----------------------------------------------------------------*/
13077 TSD - Written for the PIC port - but this unfortunately is buggy.
13078 This routine is good in that it is able to efficiently promote
13079 types to different (larger) sizes. Unfortunately, the temporary
13080 variables that are optimized out by this routine are sometimes
13081 used in other places. So until I know how to really parse the
13082 iCode tree, I'm going to not be using this routine :(.
13084 static int genMixedOperation (iCode *ic)
13087 operand *result = IC_RESULT(ic);
13088 sym_link *ctype = operandType(IC_LEFT(ic));
13089 operand *right = IC_RIGHT(ic);
13095 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
13097 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13103 nextright = IC_RIGHT(nextic);
13104 nextleft = IC_LEFT(nextic);
13105 nextresult = IC_RESULT(nextic);
13107 pic16_aopOp(right,ic,FALSE);
13108 pic16_aopOp(result,ic,FALSE);
13109 pic16_aopOp(nextright, nextic, FALSE);
13110 pic16_aopOp(nextleft, nextic, FALSE);
13111 pic16_aopOp(nextresult, nextic, FALSE);
13113 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
13115 operand *t = right;
13119 pic16_emitcode(";remove right +","");
13121 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
13123 operand *t = right;
13127 pic16_emitcode(";remove left +","");
13131 big = AOP_SIZE(nextleft);
13132 small = AOP_SIZE(nextright);
13134 switch(nextic->op) {
13137 pic16_emitcode(";optimize a +","");
13138 /* if unsigned or not an integral type */
13139 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
13140 pic16_emitcode(";add a bit to something","");
13143 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
13145 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
13146 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
13147 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
13149 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
13157 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13158 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13159 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13162 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13164 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13165 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
13166 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
13167 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13168 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
13171 pic16_emitcode("rlf","known_zero,w");
13178 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13179 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13180 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13182 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13192 pic16_freeAsmop(right,NULL,ic,TRUE);
13193 pic16_freeAsmop(result,NULL,ic,TRUE);
13194 pic16_freeAsmop(nextright,NULL,ic,TRUE);
13195 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
13197 nextic->generated = 1;
13204 /*-----------------------------------------------------------------*/
13205 /* genCast - gen code for casting */
13206 /*-----------------------------------------------------------------*/
13207 static void genCast (iCode *ic)
13209 operand *result = IC_RESULT(ic);
13210 sym_link *ctype = operandType(IC_LEFT(ic));
13211 sym_link *rtype = operandType(IC_RIGHT(ic));
13212 sym_link *restype = operandType(IC_RESULT(ic));
13213 operand *right = IC_RIGHT(ic);
13219 /* if they are equivalent then do nothing */
13220 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13223 pic16_aopOp(right,ic,FALSE) ;
13224 pic16_aopOp(result,ic,FALSE);
13226 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13229 /* if the result is a bit */
13230 if (AOP_TYPE(result) == AOP_CRY) {
13232 /* if the right size is a literal then
13233 * we know what the value is */
13234 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13236 if (AOP_TYPE(right) == AOP_LIT) {
13237 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13238 pic16_popGet(AOP(result),0));
13240 if (((int) operandLitValue(right)))
13241 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13242 AOP(result)->aopu.aop_dir,
13243 AOP(result)->aopu.aop_dir);
13245 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13246 AOP(result)->aopu.aop_dir,
13247 AOP(result)->aopu.aop_dir);
13251 /* the right is also a bit variable */
13252 if (AOP_TYPE(right) == AOP_CRY) {
13254 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13256 pic16_emitcode("clrc","");
13257 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13258 AOP(right)->aopu.aop_dir,
13259 AOP(right)->aopu.aop_dir);
13260 pic16_aopPut(AOP(result),"c",0);
13264 /* we need to or */
13265 if (AOP_TYPE(right) == AOP_REG) {
13266 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
13267 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13268 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
13270 pic16_toBoolean(right);
13271 pic16_aopPut(AOP(result),"a",0);
13275 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13278 size = AOP_SIZE(result);
13280 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13282 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
13283 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13284 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
13287 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13292 if(IS_BITFIELD(getSpec(restype))
13293 && IS_BITFIELD(getSpec(rtype))) {
13294 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13297 /* if they are the same size : or less */
13298 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13300 /* if they are in the same place */
13301 if (pic16_sameRegs(AOP(right),AOP(result)))
13304 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13306 if (IS_PTR_CONST(rtype))
13308 if (IS_CODEPTR(rtype))
13310 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13313 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13315 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13317 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13320 if(AOP_TYPE(right) == AOP_IMMD) {
13321 pCodeOp *pcop0, *pcop1, *pcop2;
13322 symbol *sym = OP_SYMBOL( right );
13324 size = AOP_SIZE(result);
13326 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13328 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13330 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13333 pic16_emitpcode(POC_MOVLW, pcop0);
13334 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13335 pic16_emitpcode(POC_MOVLW, pcop1);
13336 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13337 pic16_emitpcode(POC_MOVLW, pcop2);
13338 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13341 pic16_emitpcode(POC_MOVLW, pcop0);
13342 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13343 pic16_emitpcode(POC_MOVLW, pcop1);
13344 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13346 pic16_emitpcode(POC_MOVLW, pcop0);
13347 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13351 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13352 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13353 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13354 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13355 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13356 if(AOP_SIZE(result) <2)
13357 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13359 /* if they in different places then copy */
13360 size = AOP_SIZE(result);
13363 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13364 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13371 /* if the result is of type pointer */
13372 if (IS_PTR(ctype)) {
13374 sym_link *type = operandType(right);
13375 sym_link *etype = getSpec(type);
13377 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
13379 /* pointer to generic pointer */
13380 if (IS_GENPTR(ctype)) {
13384 p_type = DCL_TYPE(type);
13386 /* we have to go by the storage class */
13387 p_type = PTR_TYPE(SPEC_OCLS(etype));
13389 /* if (SPEC_OCLS(etype)->codesp ) */
13390 /* p_type = CPOINTER ; */
13392 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13393 /* p_type = FPOINTER ; */
13395 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13396 /* p_type = PPOINTER; */
13398 /* if (SPEC_OCLS(etype) == idata ) */
13399 /* p_type = IPOINTER ; */
13401 /* p_type = POINTER ; */
13404 /* the first two bytes are known */
13405 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
13406 size = GPTRSIZE - 1;
13409 if(offset < AOP_SIZE(right)) {
13410 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13411 mov2f(AOP(result), AOP(right), offset);
13413 if ((AOP_TYPE(right) == AOP_PCODE) &&
13414 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13415 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13416 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13419 pic16_aopPut(AOP(result),
13420 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13425 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13428 /* the last byte depending on type */
13432 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13433 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13434 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13438 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13442 pic16_emitcode(";BUG!? ","%d",__LINE__);
13446 pic16_emitcode(";BUG!? ","%d",__LINE__);
13451 if (GPTRSIZE > AOP_SIZE(right)) {
13452 // assume data pointer... THIS MIGHT BE WRONG!
13453 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13454 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13456 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13461 /* this should never happen */
13462 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13463 "got unknown pointer type");
13466 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13470 /* just copy the pointers */
13471 size = AOP_SIZE(result);
13474 pic16_aopPut(AOP(result),
13475 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13484 /* so we now know that the size of destination is greater
13485 than the size of the source.
13486 Now, if the next iCode is an operator then we might be
13487 able to optimize the operation without performing a cast.
13489 if(genMixedOperation(ic))
13492 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13494 /* we move to result for the size of source */
13495 size = AOP_SIZE(right);
13498 mov2f(AOP(result), AOP(right), offset);
13502 /* now depending on the sign of the destination */
13503 size = AOP_SIZE(result) - AOP_SIZE(right);
13504 /* if unsigned or not an integral type */
13505 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13507 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13509 /* we need to extend the sign :( */
13512 /* Save one instruction of casting char to int */
13513 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13514 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13515 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset));
13517 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13520 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13522 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13524 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13527 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13532 pic16_freeAsmop(right,NULL,ic,TRUE);
13533 pic16_freeAsmop(result,NULL,ic,TRUE);
13537 /*-----------------------------------------------------------------*/
13538 /* genDjnz - generate decrement & jump if not zero instrucion */
13539 /*-----------------------------------------------------------------*/
13540 static int genDjnz (iCode *ic, iCode *ifx)
13542 symbol *lbl, *lbl1;
13543 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13548 /* if the if condition has a false label
13549 then we cannot save */
13553 /* if the minus is not of the form
13555 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13556 !IS_OP_LITERAL(IC_RIGHT(ic)))
13559 if (operandLitValue(IC_RIGHT(ic)) != 1)
13562 /* if the size of this greater than one then no
13564 if (getSize(operandType(IC_RESULT(ic))) > 1)
13567 /* otherwise we can save BIG */
13568 lbl = newiTempLabel(NULL);
13569 lbl1= newiTempLabel(NULL);
13571 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13573 if (IS_AOP_PREG(IC_RESULT(ic))) {
13574 pic16_emitcode("dec","%s",
13575 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13576 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13577 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13581 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13582 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13584 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13585 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13589 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13590 ifx->generated = 1;
13594 /*-----------------------------------------------------------------*/
13595 /* genReceive - generate code for a receive iCode */
13596 /*-----------------------------------------------------------------*/
13597 static void genReceive (iCode *ic)
13603 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13604 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13606 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13608 if (isOperandInFarSpace(IC_RESULT(ic))
13609 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13610 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13612 int size = getSize(operandType(IC_RESULT(ic)));
13613 int offset = pic16_fReturnSizePic - size;
13617 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13618 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13622 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13624 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13625 size = AOP_SIZE(IC_RESULT(ic));
13628 pic16_emitcode ("pop","acc");
13629 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13632 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13634 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13637 /* set pseudo stack pointer to where it should be - dw*/
13638 GpsuedoStkPtr = ic->parmBytes;
13640 /* setting GpsuedoStkPtr has side effects here: */
13641 assignResultValue(IC_RESULT(ic), 0);
13644 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13647 /*-----------------------------------------------------------------*/
13648 /* genDummyRead - generate code for dummy read of volatiles */
13649 /*-----------------------------------------------------------------*/
13651 genDummyRead (iCode * ic)
13657 if (op && IS_SYMOP(op)) {
13658 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13659 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13662 pic16_aopOp (op, ic, FALSE);
13663 for (i=0; i < AOP_SIZE(op); i++) {
13664 // may need to protect this from the peepholer -- this is not nice but works...
13665 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13666 pic16_mov2w (AOP(op),i);
13667 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13669 pic16_freeAsmop (op, NULL, ic, TRUE);
13671 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13675 /*-----------------------------------------------------------------*/
13676 /* genpic16Code - generate code for pic16 based controllers */
13677 /*-----------------------------------------------------------------*/
13679 * At this point, ralloc.c has gone through the iCode and attempted
13680 * to optimize in a way suitable for a PIC. Now we've got to generate
13681 * PIC instructions that correspond to the iCode.
13683 * Once the instructions are generated, we'll pass through both the
13684 * peep hole optimizer and the pCode optimizer.
13685 *-----------------------------------------------------------------*/
13687 void genpic16Code (iCode *lic)
13692 lineHead = lineCurr = NULL;
13694 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13695 pic16_addpBlock(pb);
13698 /* if debug information required */
13699 if (options.debug && currFunc) {
13701 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13706 for (ic = lic ; ic ; ic = ic->next ) {
13708 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13709 if ( cln != ic->lineno ) {
13710 if ( options.debug ) {
13711 debugFile->writeCLine (ic);
13714 if(!options.noCcodeInAsm) {
13715 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13716 printCLine(ic->filename, ic->lineno)));
13722 if(options.iCodeInAsm) {
13725 /* insert here code to print iCode as comment */
13726 l = Safe_strdup(printILine(ic));
13727 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13730 /* if the result is marked as
13731 * spilt and rematerializable or code for
13732 * this has already been generated then
13734 if (resultRemat(ic) || ic->generated )
13737 /* depending on the operation */
13756 /* IPOP happens only when trying to restore a
13757 * spilt live range, if there is an ifx statement
13758 * following this pop then the if statement might
13759 * be using some of the registers being popped which
13760 * would destroy the contents of the register so
13761 * we need to check for this condition and handle it */
13763 && ic->next->op == IFX
13764 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13765 genIfx (ic->next,ic);
13783 genEndFunction (ic);
13799 pic16_genPlus (ic) ;
13803 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13804 pic16_genMinus (ic);
13820 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13824 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13830 /* note these two are xlated by algebraic equivalence
13831 * during parsing SDCC.y */
13832 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13833 "got '>=' or '<=' shouldn't have come here");
13837 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13849 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13853 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13857 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13881 genRightShift (ic);
13884 case GET_VALUE_AT_ADDRESS:
13889 if (POINTER_SET(ic))
13916 addSet(&_G.sendSet,ic);
13919 case DUMMY_READ_VOLATILE:
13929 /* now we are ready to call the
13930 peep hole optimizer */
13931 if (!options.nopeep)
13932 peepHole (&lineHead);
13934 /* now do the actual printing */
13935 printLine (lineHead, codeOutFile);
13938 DFPRINTF((stderr,"printing pBlock\n\n"));
13939 pic16_printpBlock(stdout,pb);