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)
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 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
51 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
52 void pic16_genMult8X8_8 (operand *, operand *,operand *);
53 void pic16_genMult16X16_16(operand *, operand *, operand *);
54 void pic16_genMult32X32_32(operand *, operand *, operand *);
55 pCode *pic16_AssembleLine(char *line, int peeps);
56 extern void pic16_printpBlock(FILE *of, pBlock *pb);
57 static asmop *newAsmop (short type);
58 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
59 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
60 static void mov2w (asmop *aop, int offset);
61 static void mov2f(asmop *dst, asmop *src, int offset);
62 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
63 static pCodeOp *pic16_popRegFromIdx(int rIdx);
65 //static int aopIdx (asmop *aop, int offset);
67 int pic16_labelOffset=0;
68 extern int pic16_debug_verbose;
69 static int optimized_for_speed = 0;
77 /* max_key keeps track of the largest label number used in
78 a function. This is then used to adjust the label offset
79 for the next function.
82 static int GpsuedoStkPtr=0;
84 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
86 unsigned int pic16aopLiteral (value *val, int offset);
87 const char *pic16_AopType(short type);
88 static iCode *ifxForOp ( operand *op, iCode *ic );
90 void pic16_pushpCodeOp(pCodeOp *pcop);
91 void pic16_poppCodeOp(pCodeOp *pcop);
93 static bool is_LitOp(operand *op);
94 static bool is_LitAOp(asmop *aop);
97 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
99 /* set the following macro to 1 to enable passing the
100 * first byte of functions parameters via WREG */
101 #define USE_WREG_IN_FUNC_PARAMS 0
104 /* this is the down and dirty file with all kinds of
105 kludgy & hacky stuff. This is what it is all about
106 CODE GENERATION for a specific MCU . some of the
107 routines may be reusable, will have to see */
109 static char *zero = "#0x00";
110 static char *one = "#0x01";
111 //static char *spname = "sp";
115 * Function return value policy (MSB-->LSB):
117 * 16 bits -> PRODL:WREG
118 * 24 bits -> PRODH:PRODL:WREG
119 * 32 bits -> FSR0L:PRODH:PRODL:WREG
120 * >32 bits -> on stack, and FSR0 points to the beginning
125 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
126 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
127 static char **fReturn = fReturnpic16;
129 static char *accUse[] = {"WREG"};
131 //static short rbank = -1;
147 int stack_lat; /* stack offset latency */
149 int useWreg; /* flag when WREG is used to pass function parameter */
152 /* Resolved ifx structure. This structure stores information
153 about an iCode ifx that makes it easier to generate code.
155 typedef struct resolvedIfx {
156 symbol *lbl; /* pointer to a label */
157 int condition; /* true or false ifx */
158 int generated; /* set true when the code associated with the ifx
162 extern int pic16_ptrRegReq ;
163 extern int pic16_nRegs;
164 extern FILE *codeOutFile;
165 //static void saverbank (int, iCode *,bool);
167 static lineNode *lineHead = NULL;
168 static lineNode *lineCurr = NULL;
170 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
171 0xE0, 0xC0, 0x80, 0x00};
172 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
173 0x07, 0x03, 0x01, 0x00};
177 /*-----------------------------------------------------------------*/
178 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
179 /* exponent of 2 is returned, otherwise -1 is */
181 /* note that this is similar to the function `powof2' in SDCCsymt */
185 /*-----------------------------------------------------------------*/
186 int pic16_my_powof2 (unsigned long num)
189 if( (num & (num-1)) == 0) {
202 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
204 DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
206 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
207 ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
208 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
209 ((left) ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
210 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
211 ((right) ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
212 ((result) ? AOP_SIZE(result) : 0));
215 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
218 DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
220 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
221 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
222 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
223 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
224 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
225 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
229 void pic16_emitpcomment (char *fmt, ...)
232 char lb[INITIAL_INLINEASM];
238 vsprintf(lb+1,fmt,ap);
240 while (isspace(*lbp)) lbp++;
243 lineCurr = (lineCurr ?
244 connectLine(lineCurr,newLineNode(lb)) :
245 (lineHead = newLineNode(lb)));
246 lineCurr->isInline = _G.inLine;
247 lineCurr->isDebug = _G.debugLine;
249 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
252 // fprintf(stderr, "%s\n", lb);
255 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
258 char lb[INITIAL_INLINEASM];
261 if(!pic16_debug_verbose)
268 sprintf(lb,"%s\t",inst);
270 sprintf(lb,"%s",inst);
271 vsprintf(lb+(strlen(lb)),fmt,ap);
275 while (isspace(*lbp)) lbp++;
278 lineCurr = (lineCurr ?
279 connectLine(lineCurr,newLineNode(lb)) :
280 (lineHead = newLineNode(lb)));
281 lineCurr->isInline = _G.inLine;
282 lineCurr->isDebug = _G.debugLine;
284 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
287 // fprintf(stderr, "%s\n", lb);
292 void pic16_emitpLabel(int key)
294 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
297 void pic16_emitpLabelFORCE(int key)
299 pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
302 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
306 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
308 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
311 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
314 pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
316 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
319 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
322 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
328 #define pic16_emitcode DEBUGpic16_emitcode
330 /*-----------------------------------------------------------------*/
331 /* pic16_emitcode - writes the code into a file : for now it is simple */
332 /*-----------------------------------------------------------------*/
333 void pic16_emitcode (char *inst,char *fmt, ...)
336 char lb[INITIAL_INLINEASM];
343 sprintf(lb,"%s\t",inst);
345 sprintf(lb,"%s",inst);
346 vsprintf(lb+(strlen(lb)),fmt,ap);
350 while (isspace(*lbp)) lbp++;
353 lineCurr = (lineCurr ?
354 connectLine(lineCurr,newLineNode(lb)) :
355 (lineHead = newLineNode(lb)));
356 lineCurr->isInline = _G.inLine;
357 lineCurr->isDebug = _G.debugLine;
359 // VR fprintf(stderr, "lb = <%s>\n", lbp);
361 // if(pic16_debug_verbose)
362 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
369 /*-----------------------------------------------------------------*/
370 /* pic16_emitDebuggerSymbol - associate the current code location */
371 /* with a debugger symbol */
372 /*-----------------------------------------------------------------*/
374 pic16_emitDebuggerSymbol (char * debugSym)
377 pic16_emitcode (";", "%s ==.", debugSym);
382 /*-----------------------------------------------------------------*/
383 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
384 /*-----------------------------------------------------------------*/
385 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
387 // bool r0iu = FALSE , r1iu = FALSE;
388 // bool r0ou = FALSE , r1ou = FALSE;
389 bool fsr0iu = FALSE, fsr0ou;
390 bool fsr2iu = FALSE, fsr2ou;
392 fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
395 fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
396 fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
398 fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
399 fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
401 if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
402 fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
403 DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
406 if(!fsr0iu && !fsr0ou) {
407 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
408 (*aopp)->type = AOP_FSR0;
410 fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
412 return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
416 /* no usage of FSR2 */
417 if(!fsr2iu && !fsr2ou) {
418 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
419 (*aopp)->type = AOP_FSR2;
421 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
425 /* now we know they both have usage */
426 /* if fsr0 not used in this instruction */
428 if (!_G.fsr0Pushed) {
429 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
430 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
434 ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
435 (*aopp)->type = AOP_FSR0;
437 // fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
439 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
443 fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
448 /* the logic: if r0 & r1 used in the instruction
449 then we are in trouble otherwise */
451 /* first check if r0 & r1 are used by this
452 instruction, in which case we are in trouble */
453 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
454 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
459 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
460 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
462 /* if no usage of r0 then return it */
463 if (!r0iu && !r0ou) {
464 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
465 (*aopp)->type = AOP_R0;
467 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
470 /* if no usage of r1 then return it */
471 if (!r1iu && !r1ou) {
472 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
473 (*aopp)->type = AOP_R1;
475 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
478 /* now we know they both have usage */
479 /* if r0 not used in this instruction */
481 /* push it if not already pushed */
483 //pic16_emitcode ("push","%s",
484 // pic16_regWithIdx(R0_IDX)->dname);
488 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
489 (*aopp)->type = AOP_R0;
491 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
494 /* if r1 not used then */
497 /* push it if not already pushed */
499 //pic16_emitcode ("push","%s",
500 // pic16_regWithIdx(R1_IDX)->dname);
504 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
505 (*aopp)->type = AOP_R1;
506 return pic16_regWithIdx(R1_IDX);
510 /* I said end of world but not quite end of world yet */
511 /* if this is a result then we can push it on the stack*/
513 (*aopp)->type = AOP_STK;
517 /* other wise this is true end of the world */
518 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
519 "getFreePtr should never reach here");
524 /*-----------------------------------------------------------------*/
525 /* newAsmop - creates a new asmOp */
526 /*-----------------------------------------------------------------*/
527 static asmop *newAsmop (short type)
531 aop = Safe_calloc(1,sizeof(asmop));
536 static void genSetDPTR(int n)
540 pic16_emitcode(";", "Select standard DPTR");
541 pic16_emitcode("mov", "dps, #0x00");
545 pic16_emitcode(";", "Select alternate DPTR");
546 pic16_emitcode("mov", "dps, #0x01");
550 /*-----------------------------------------------------------------*/
551 /* resolveIfx - converts an iCode ifx into a form more useful for */
552 /* generating code */
553 /*-----------------------------------------------------------------*/
554 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
558 // DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
564 resIfx->condition = 1; /* assume that the ifx is true */
565 resIfx->generated = 0; /* indicate that the ifx has not been used */
568 resIfx->lbl = newiTempLabel(NULL); /* oops, there is no ifx. so create a label */
571 DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
572 __FUNCTION__,__LINE__,resIfx->lbl->key);
577 resIfx->lbl = IC_TRUE(ifx);
579 resIfx->lbl = IC_FALSE(ifx);
580 resIfx->condition = 0;
585 DEBUGpic16_emitcode("; +++","ifx true is non-null");
587 DEBUGpic16_emitcode("; +++","ifx true is null");
589 DEBUGpic16_emitcode("; +++","ifx false is non-null");
591 DEBUGpic16_emitcode("; +++","ifx false is null");
595 DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
599 /*-----------------------------------------------------------------*/
600 /* pointerCode - returns the code for a pointer type */
601 /*-----------------------------------------------------------------*/
602 static int pointerCode (sym_link *etype)
605 return PTR_TYPE(SPEC_OCLS(etype));
610 /*-----------------------------------------------------------------*/
611 /* aopForSym - for a true symbol */
612 /*-----------------------------------------------------------------*/
613 static asmop *aopForSym (iCode *ic, operand *op, bool result)
615 symbol *sym=OP_SYMBOL(op);
617 memmap *space= SPEC_OCLS(sym->etype);
621 _G.resDirect = 0; /* clear flag that instructs the result is loaded directly from aopForSym */
623 // sym = OP_SYMBOL(op);
625 /* if already has one */
627 DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
632 /* if symbol was initially placed onStack then we must re-place it
633 * to direct memory, since pic16 does not have a specific stack */
635 fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
640 /* assign depending on the storage class */
641 /* if it is on the stack or indirectly addressable */
642 /* space we need to assign either r0 or r1 to it */
643 if (sym->onStack || sym->iaccess) {
647 DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
648 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
650 /* acquire a temporary register -- it is saved in function */
652 sym->aop = aop = newAsmop(AOP_STA);
653 aop->aopu.stk.stk = sym->stack;
654 aop->size = getSize(sym->type);
657 DEBUGpic16_emitcode("; +++", "%s:%d", __FILE__, __LINE__);
658 pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
659 if((ic->op == '=') && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
660 && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG) ) {
662 for(i=0;i<aop->size;i++)
663 aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
664 _G.resDirect = 1; /* notify that result will be loaded directly from aopForSym */
666 for(i=0;i<aop->size;i++) {
667 aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond( _G.fregsUsed, 0 );
668 _G.fregsUsed = bitVectSetBit(_G.fregsUsed, PCOR(pcop[i])->r->rIdx);
672 // fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
675 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
678 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
681 for(i=0;i<aop->size;i++) {
683 /* initialise for stack access via frame pointer */
684 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack + i + _G.stack_lat));
686 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
687 pic16_popCopyReg(&pic16_pc_plusw2), pcop[i]));
691 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
698 /* now assign the address of the variable to
699 the pointer register */
700 if (aop->type != AOP_STK) {
704 pic16_emitcode("push","acc");
706 pic16_emitcode("mov","a,_bp");
707 pic16_emitcode("add","a,#0x%02x",
709 ((char)(sym->stack - _G.nRegsSaved )) :
710 ((char)sym->stack)) & 0xff);
711 pic16_emitcode("mov","%s,a",
712 aop->aopu.aop_ptr->name);
715 pic16_emitcode("pop","acc");
717 pic16_emitcode("mov","%s,#%s",
718 aop->aopu.aop_ptr->name,
720 aop->paged = space->paged;
722 aop->aopu.aop_stk = sym->stack;
730 if (sym->onStack && options.stack10bit)
732 /* It's on the 10 bit stack, which is located in
736 //DEBUGpic16_emitcode(";","%d",__LINE__);
739 pic16_emitcode("push","acc");
741 pic16_emitcode("mov","a,_bp");
742 pic16_emitcode("add","a,#0x%02x",
744 ((char)(sym->stack - _G.nRegsSaved )) :
745 ((char)sym->stack)) & 0xff);
748 pic16_emitcode ("mov","dpx1,#0x40");
749 pic16_emitcode ("mov","dph1,#0x00");
750 pic16_emitcode ("mov","dpl1, a");
754 pic16_emitcode("pop","acc");
756 sym->aop = aop = newAsmop(AOP_DPTR2);
757 aop->size = getSize(sym->type);
763 /* special case for a function */
764 if (IS_FUNC(sym->type)) {
765 sym->aop = aop = newAsmop(AOP_PCODE);
766 //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
767 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
768 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
769 PCOI(aop->aopu.pcop)->index = 0;
770 aop->size = FPTRSIZE;
771 DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
778 //DEBUGpic16_emitcode(";","%d",__LINE__);
779 /* if in bit space */
780 if (IN_BITSPACE(space)) {
781 sym->aop = aop = newAsmop (AOP_CRY);
782 aop->aopu.aop_dir = sym->rname ;
783 aop->size = getSize(sym->type);
784 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
787 /* if it is in direct space */
788 if (IN_DIRSPACE(space)) {
789 sym->aop = aop = newAsmop (AOP_DIR);
790 aop->aopu.aop_dir = sym->rname ;
791 aop->size = getSize(sym->type);
792 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
793 pic16_allocDirReg( IC_LEFT(ic) );
798 if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
799 sym->aop = aop = newAsmop (AOP_DIR);
800 aop->aopu.aop_dir = sym->rname ;
801 aop->size = getSize(sym->type);
802 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
803 pic16_allocDirReg( IC_LEFT(ic) );
808 /* only remaining is far space */
809 sym->aop = aop = newAsmop(AOP_PCODE);
811 /* change the next if to 1 to revert to good old immediate code */
812 if(IN_CODESPACE(space)) {
813 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
814 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
815 PCOI(aop->aopu.pcop)->index = 0;
817 /* try to allocate via direct register */
818 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
819 // aop->size = getSize( sym->type );
822 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
823 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
826 if(!pic16_allocDirReg (IC_LEFT(ic)))
830 if(IN_DIRSPACE( space ))
832 else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
833 aop->size = FPTRSIZE;
834 else if(IC_LEFT(ic)) aop->size = AOP_SIZE( IC_LEFT(ic) );
835 else if(IC_RIGHT(ic)) aop->size = AOP_SIZE( IC_RIGHT(ic) );
836 else if(sym->onStack) {
842 DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
844 /* if it is in code space */
845 if (IN_CODESPACE(space))
851 /*-----------------------------------------------------------------*/
852 /* aopForRemat - rematerialzes an object */
853 /*-----------------------------------------------------------------*/
854 static asmop *aopForRemat (operand *op) // x symbol *sym)
856 symbol *sym = OP_SYMBOL(op);
858 iCode *ic = NULL, *oldic;
859 asmop *aop = newAsmop(AOP_PCODE);
866 ic = sym->rematiCode;
868 if(IS_OP_POINTER(op)) {
869 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
875 // pic16_emitpcomment("ic: %s\n", printILine(ic));
878 val += (int) operandLitValue(IC_RIGHT(ic));
879 } else if (ic->op == '-') {
880 val -= (int) operandLitValue(IC_RIGHT(ic));
884 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
887 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
890 if(!op->isaddr)viaimmd++; else viaimmd=0;
892 /* set the following if to 1 to revert to good old immediate code */
893 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
896 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
898 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
901 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
903 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
906 PCOI(aop->aopu.pcop)->index = val;
908 aop->size = getSize( sym->type );
910 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__, getSize( OP_SYMBOL( IC_LEFT(ic))->type));
912 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
913 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
915 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
919 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
920 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
922 val, IS_PTR_CONST(operandType(op)));
924 val, IS_CODEPTR(operandType(op)));
927 // DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
929 pic16_allocDirReg (IC_LEFT(ic));
931 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
938 static int aopIdx (asmop *aop, int offset)
943 if(aop->type != AOP_REG)
946 return aop->aopu.aop_reg[offset]->rIdx;
951 /*-----------------------------------------------------------------*/
952 /* regsInCommon - two operands have some registers in common */
953 /*-----------------------------------------------------------------*/
954 static bool regsInCommon (operand *op1, operand *op2)
959 /* if they have registers in common */
960 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
963 sym1 = OP_SYMBOL(op1);
964 sym2 = OP_SYMBOL(op2);
966 if (sym1->nRegs == 0 || sym2->nRegs == 0)
969 for (i = 0 ; i < sym1->nRegs ; i++) {
974 for (j = 0 ; j < sym2->nRegs ;j++ ) {
978 if (sym2->regs[j] == sym1->regs[i])
986 /*-----------------------------------------------------------------*/
987 /* operandsEqu - equivalent */
988 /*-----------------------------------------------------------------*/
989 static bool operandsEqu ( operand *op1, operand *op2)
993 /* if they not symbols */
994 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
997 sym1 = OP_SYMBOL(op1);
998 sym2 = OP_SYMBOL(op2);
1000 /* if both are itemps & one is spilt
1001 and the other is not then false */
1002 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1003 sym1->isspilt != sym2->isspilt )
1006 /* if they are the same */
1010 if (sym1->rname[0] && sym2->rname[0]
1011 && strcmp (sym1->rname, sym2->rname) == 0)
1015 /* if left is a tmp & right is not */
1016 if (IS_ITEMP(op1) &&
1019 (sym1->usl.spillLoc == sym2))
1022 if (IS_ITEMP(op2) &&
1026 (sym2->usl.spillLoc == sym1))
1032 /*-----------------------------------------------------------------*/
1033 /* pic16_sameRegs - two asmops have the same registers */
1034 /*-----------------------------------------------------------------*/
1035 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1042 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1043 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1045 if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1047 if (aop1->type != AOP_REG ||
1048 aop2->type != AOP_REG )
1051 if (aop1->size != aop2->size )
1054 for (i = 0 ; i < aop1->size ; i++ ) {
1055 // if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1057 // if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1058 if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1065 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1067 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1068 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1070 if(aop1 == aop2)return TRUE;
1071 if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1073 if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1079 /*-----------------------------------------------------------------*/
1080 /* pic16_aopOp - allocates an asmop for an operand : */
1081 /*-----------------------------------------------------------------*/
1082 void pic16_aopOp (operand *op, iCode *ic, bool result)
1091 DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1093 /* if this a literal */
1094 if (IS_OP_LITERAL(op)) {
1095 op->aop = aop = newAsmop(AOP_LIT);
1096 aop->aopu.aop_lit = op->operand.valOperand;
1097 aop->size = getSize(operandType(op));
1102 sym_link *type = operandType(op);
1104 if(IS_PTR_CONST(type))
1106 if(IS_CODEPTR(type))
1108 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1111 /* if already has a asmop then continue */
1115 /* if the underlying symbol has a aop */
1116 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1117 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1118 op->aop = OP_SYMBOL(op)->aop;
1122 /* if this is a true symbol */
1123 if (IS_TRUE_SYMOP(op)) {
1124 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1125 op->aop = aopForSym(ic, op, result);
1129 /* this is a temporary : this has
1135 e) can be a return use only */
1137 sym = OP_SYMBOL(op);
1139 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1140 /* if the type is a conditional */
1141 if (sym->regType == REG_CND) {
1142 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1147 /* if it is spilt then two situations
1149 b) has a spill location */
1150 if (sym->isspilt || sym->nRegs == 0) {
1152 DEBUGpic16_emitcode(";","%d",__LINE__);
1153 /* rematerialize it NOW */
1156 sym->aop = op->aop = aop = aopForRemat (op);
1157 // aop->size = getSize(sym->type);
1158 // DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1165 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1166 aop->size = getSize(sym->type);
1167 for ( i = 0 ; i < 1 ; i++ ) {
1168 aop->aopu.aop_str[i] = accUse[i];
1169 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1171 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1172 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1180 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1181 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1182 //pic16_allocDirReg (IC_LEFT(ic));
1183 aop->size = getSize(sym->type);
1188 aop = op->aop = sym->aop = newAsmop(AOP_STR);
1189 aop->size = getSize(sym->type);
1190 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1191 aop->aopu.aop_str[i] = fReturn[i];
1193 DEBUGpic16_emitcode(";","%d",__LINE__);
1197 /* else spill location */
1198 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1199 /* force a new aop if sizes differ */
1200 sym->usl.spillLoc->aop = NULL;
1204 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1205 __FUNCTION__,__LINE__,
1206 sym->usl.spillLoc->rname,
1207 sym->rname, sym->usl.spillLoc->offset);
1210 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1211 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1212 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1214 sym->usl.spillLoc->offset, op);
1215 aop->size = getSize(sym->type);
1221 sym_link *type = operandType(op);
1223 if(IS_PTR_CONST(type))
1225 if(IS_CODEPTR(type))
1227 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1230 /* must be in a register */
1231 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1232 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1233 aop->size = sym->nRegs;
1234 for ( i = 0 ; i < sym->nRegs ;i++)
1235 aop->aopu.aop_reg[i] = sym->regs[i];
1238 /*-----------------------------------------------------------------*/
1239 /* pic16_freeAsmop - free up the asmop given to an operand */
1240 /*----------------------------------------------------------------*/
1241 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1258 /* depending on the asmop type only three cases need work AOP_RO
1259 , AOP_R1 && AOP_STK */
1261 switch (aop->type) {
1263 if (_G.fsr0Pushed ) {
1265 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1266 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1267 // pic16_emitcode ("pop","ar0");
1271 bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1275 bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1281 pic16_emitcode ("pop","ar0");
1285 bitVectUnSetBit(ic->rUsed,R0_IDX);
1291 pic16_emitcode ("pop","ar1");
1295 bitVectUnSetBit(ic->rUsed,R1_IDX);
1302 /* we must store the result on stack */
1303 if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1304 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1305 for(i=0;i<aop->size;i++) {
1306 /* initialise for stack access via frame pointer */
1307 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(OP_SYMBOL(IC_RESULT(ic))->stack + i + _G.stack_lat));
1309 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1310 aop->aopu.stk.pop[i], pic16_popCopyReg(&pic16_pc_plusw2)));
1313 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1317 for(i=0;i<aop->size;i++)
1318 PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1327 int stk = aop->aopu.aop_stk + aop->size;
1328 bitVectUnSetBit(ic->rUsed,R0_IDX);
1329 bitVectUnSetBit(ic->rUsed,R1_IDX);
1331 getFreePtr(ic,&aop,FALSE);
1333 if (options.stack10bit)
1335 /* I'm not sure what to do here yet... */
1338 "*** Warning: probably generating bad code for "
1339 "10 bit stack mode.\n");
1343 pic16_emitcode ("mov","a,_bp");
1344 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1345 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1347 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1351 pic16_emitcode("pop","acc");
1352 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1354 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1357 pic16_freeAsmop(op,NULL,ic,TRUE);
1359 pic16_emitcode("pop","ar0");
1364 pic16_emitcode("pop","ar1");
1374 /* all other cases just dealloc */
1378 OP_SYMBOL(op)->aop = NULL;
1379 /* if the symbol has a spill */
1381 SPIL_LOC(op)->aop = NULL;
1386 /*-----------------------------------------------------------------*/
1387 /* pic16_aopGet - for fetching value of the aop */
1388 /*-----------------------------------------------------------------*/
1389 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1394 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1396 /* offset is greater than size then zero */
1397 if (offset > (aop->size - 1) &&
1398 aop->type != AOP_LIT)
1401 /* depending on type */
1402 switch (aop->type) {
1406 sprintf(s, "%s", aop->aopu.aop_ptr->name);
1407 rs = Safe_calloc(1, strlen(s)+1);
1412 /* if we need to increment it */
1413 while (offset > aop->coff)
1415 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1419 while (offset < aop->coff)
1421 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1427 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1428 return (dname ? "acc" : "a");
1430 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1431 rs = Safe_calloc (1, strlen (s) + 1);
1439 sprintf (s,"%s",aop->aopu.aop_immd);
1442 sprintf(s,"(%s >> %d)",
1447 aop->aopu.aop_immd);
1448 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1449 rs = Safe_calloc(1,strlen(s)+1);
1455 sprintf(s,"(%s + %d)",
1458 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1460 sprintf(s,"%s",aop->aopu.aop_dir);
1461 rs = Safe_calloc(1,strlen(s)+1);
1467 // return aop->aopu.aop_reg[offset]->dname;
1469 return aop->aopu.aop_reg[offset]->name;
1472 //pic16_emitcode(";","%d",__LINE__);
1473 return aop->aopu.aop_dir;
1476 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1477 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1479 // return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1480 rs = Safe_strdup("WREG");
1484 sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1485 rs = Safe_calloc(1,strlen(s)+1);
1490 aop->coff = offset ;
1491 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1494 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1496 return aop->aopu.aop_str[offset];
1500 pCodeOp *pcop = aop->aopu.pcop;
1501 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1503 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1504 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1505 sprintf(s,"%s", pcop->name);
1507 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1510 rs = Safe_calloc(1,strlen(s)+1);
1515 rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1519 // pCodeOp *pcop = aop->aop
1524 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1525 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1526 "aopget got unsupported aop->type");
1532 /* lock has the following meaning: When allocating temporary registers
1533 * for stack variables storage, the value of the temporary register is
1534 * saved on stack. Its value is restored at the end. This procedure is
1535 * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1536 * a possibility that before a call to pic16_aopOp, a temporary register
1537 * is allocated for a while and it is freed after some time, this will
1538 * mess the stack and values will not be restored properly. So use lock=1
1539 * to allocate temporary registers used internally by the programmer, and
1540 * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1541 * to inform the compiler developer about a possible bug. This is an internal
1542 * feature for developing the compiler -- VR */
1544 int _TempReg_lock = 0;
1545 /*-----------------------------------------------------------------*/
1546 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1547 /*-----------------------------------------------------------------*/
1548 pCodeOp *pic16_popGetTempReg(int lock)
1553 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1555 // werror(W_POSSBUG2, __FILE__, __LINE__);
1558 _TempReg_lock += lock;
1563 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1564 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1565 PCOR(pcop)->r->wasUsed=1;
1566 PCOR(pcop)->r->isFree=0;
1568 /* push value on stack */
1569 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1577 /*-----------------------------------------------------------------*/
1578 /* pic16_popGetTempRegCond - create a new temporary pCodeOp, but */
1579 /* don't save if inside v */
1580 /*-----------------------------------------------------------------*/
1581 pCodeOp *pic16_popGetTempRegCond(bitVect *v, int lock)
1586 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1589 // werror(W_POSSBUG2, __FILE__, __LINE__);
1592 _TempReg_lock += lock;
1597 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1598 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1599 PCOR(pcop)->r->wasUsed=1;
1600 PCOR(pcop)->r->isFree=0;
1602 if(!bitVectBitValue(v, PCOR(pcop)->r->rIdx)) {
1603 /* push value on stack */
1604 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1614 /*-----------------------------------------------------------------*/
1615 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1616 /*-----------------------------------------------------------------*/
1617 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1619 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1621 _TempReg_lock -= lock;
1623 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1624 PCOR(pcop)->r->isFree = 1;
1625 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1628 /*-----------------------------------------------------------------*/
1629 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1630 /*-----------------------------------------------------------------*/
1631 pCodeOp *pic16_popGetLabel(unsigned int key)
1634 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1639 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1642 /*-----------------------------------------------------------------*/
1643 /* pic16_popCopyReg - copy a pcode operator */
1644 /*-----------------------------------------------------------------*/
1645 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1649 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1650 pcor->pcop.type = pc->pcop.type;
1652 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1653 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1655 pcor->pcop.name = NULL;
1658 pcor->rIdx = pc->rIdx;
1661 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1666 /*-----------------------------------------------------------------*/
1667 /* pic16_popGetLit - asm operator to pcode operator conversion */
1668 /*-----------------------------------------------------------------*/
1669 pCodeOp *pic16_popGetLit(int lit)
1671 return pic16_newpCodeOpLit(lit);
1674 /*-----------------------------------------------------------------*/
1675 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1676 /*-----------------------------------------------------------------*/
1677 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1679 return pic16_newpCodeOpLit2(lit, arg2);
1683 /*-----------------------------------------------------------------*/
1684 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1685 /*-----------------------------------------------------------------*/
1686 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1688 return pic16_newpCodeOpImmd(name, offset,index, 0);
1692 /*-----------------------------------------------------------------*/
1693 /* pic16_popGet - asm operator to pcode operator conversion */
1694 /*-----------------------------------------------------------------*/
1695 pCodeOp *pic16_popGetWithString(char *str)
1701 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1705 pcop = pic16_newpCodeOp(str,PO_STR);
1710 /*-----------------------------------------------------------------*/
1711 /* pic16_popRegFromString - */
1712 /*-----------------------------------------------------------------*/
1713 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1716 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1717 pcop->type = PO_DIR;
1719 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1720 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1725 pcop->name = Safe_calloc(1,strlen(str)+1);
1726 strcpy(pcop->name,str);
1728 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1730 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1732 /* make sure that register doesn't exist,
1733 * and operand isn't NULL
1734 * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1735 if((PCOR(pcop)->r == NULL)
1737 && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1738 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1739 // __FUNCTION__, __LINE__, str, size, offset);
1741 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1742 fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1745 PCOR(pcop)->instance = offset;
1750 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1754 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1756 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1757 PCOR(pcop)->rIdx = rIdx;
1758 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1760 PCOR(pcop)->r->isFree = 0;
1761 PCOR(pcop)->r->wasUsed = 1;
1763 pcop->type = PCOR(pcop)->r->pc_type;
1768 /*---------------------------------------------------------------------------------*/
1769 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1771 /*---------------------------------------------------------------------------------*/
1772 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1777 pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1779 /* comment the following check, so errors to throw up */
1780 // if(!pcop2)return NULL;
1782 temp = pic16_popGet(aop_dst, offset);
1783 pcop2->pcop2 = temp;
1790 /*--------------------------------------------------------------------------------.-*/
1791 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1792 /* VR 030601 , adapted by Hans Dorn */
1793 /*--------------------------------------------------------------------------------.-*/
1794 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1798 pcop2 = (pCodeOpReg2 *)src;
1806 /*---------------------------------------------------------------------------------*/
1807 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
1808 /* movff instruction */
1809 /*---------------------------------------------------------------------------------*/
1810 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1815 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1816 pcop2->pcop2 = pic16_popCopyReg(dst);
1818 /* the pCodeOp may be already allocated */
1819 pcop2 = (pCodeOpReg2 *)(src);
1820 pcop2->pcop2 = (pCodeOp *)(dst);
1827 /*-----------------------------------------------------------------*/
1828 /* pic16_popGet - asm operator to pcode operator conversion */
1829 /*-----------------------------------------------------------------*/
1830 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1832 //char *s = buffer ;
1837 /* offset is greater than
1840 // if (offset > (aop->size - 1) &&
1841 // aop->type != AOP_LIT)
1842 // return NULL; //zero;
1844 /* depending on type */
1845 switch (aop->type) {
1851 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1852 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1859 pcop = Safe_calloc(1, sizeof(pCodeOpReg));
1860 PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */
1861 PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
1862 PCOR(pcop)->r->wasUsed = 1;
1863 PCOR(pcop)->r->isFree = 0;
1865 PCOR(pcop)->instance = offset;
1866 pcop->type = PCOR(pcop)->r->pc_type;
1870 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1871 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1874 /* pCodeOp is already allocated from aopForSym */
1875 DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
1876 pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
1882 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
1884 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1886 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1888 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1889 PCOR(pcop)->rIdx = rIdx;
1890 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1891 PCOR(pcop)->r->wasUsed=1;
1892 PCOR(pcop)->r->isFree=0;
1894 PCOR(pcop)->instance = offset;
1895 pcop->type = PCOR(pcop)->r->pc_type;
1896 // rs = aop->aopu.aop_reg[offset]->name;
1897 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1901 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1902 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1908 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1909 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1913 int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1915 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1917 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1918 // pcop->type = PO_GPR_REGISTER;
1919 PCOR(pcop)->rIdx = rIdx;
1920 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
1921 PCOR(pcop)->r->wasUsed=1;
1922 PCOR(pcop)->r->isFree=0;
1924 PCOR(pcop)->instance = offset;
1925 pcop->type = PCOR(pcop)->r->pc_type;
1927 DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s\n", __LINE__, dumpPicOptype(pcop->type));
1928 rs = aop->aopu.aop_reg[offset]->name;
1929 DEBUGpic16_emitcode(";","%d regiser idx = %d name = %s",__LINE__,rIdx,rs);
1934 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1936 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
1937 PCOR(pcop)->instance = offset;
1938 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1939 //if(PCOR(pcop)->r == NULL)
1940 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1944 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1945 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1948 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1949 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1952 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1953 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1954 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1955 pcop->type = PCOR(pcop)->r->pc_type;
1956 pcop->name = PCOR(pcop)->r->name;
1962 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1964 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1965 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1967 switch( aop->aopu.pcop->type ) {
1968 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
1969 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1971 assert( 0 ); /* should never reach here */;
1974 PCOI(pcop)->offset = offset;
1979 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1980 "pic16_popGet got unsupported aop->type");
1983 /*-----------------------------------------------------------------*/
1984 /* pic16_aopPut - puts a string for a aop */
1985 /*-----------------------------------------------------------------*/
1986 void pic16_aopPut (asmop *aop, char *s, int offset)
1993 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1995 if (aop->size && offset > ( aop->size - 1)) {
1996 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1997 "pic16_aopPut got offset > aop->size");
2001 /* will assign value to value */
2002 /* depending on where it is ofcourse */
2003 switch (aop->type) {
2006 sprintf(d,"(%s + %d)",
2007 aop->aopu.aop_dir,offset);
2008 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2011 sprintf(d,"%s",aop->aopu.aop_dir);
2014 DEBUGpic16_emitcode(";","%d",__LINE__);
2016 pic16_emitcode("movf","%s,w",s);
2017 pic16_emitcode("movwf","%s",d);
2020 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
2021 if(offset >= aop->size) {
2022 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2025 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2028 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2035 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2036 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2039 strcmp(s,"r0") == 0 ||
2040 strcmp(s,"r1") == 0 ||
2041 strcmp(s,"r2") == 0 ||
2042 strcmp(s,"r3") == 0 ||
2043 strcmp(s,"r4") == 0 ||
2044 strcmp(s,"r5") == 0 ||
2045 strcmp(s,"r6") == 0 ||
2046 strcmp(s,"r7") == 0 )
2047 pic16_emitcode("mov","%s,%s ; %d",
2048 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2052 if(strcmp(s,"W")==0 )
2053 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
2055 pic16_emitcode("movwf","%s",
2056 aop->aopu.aop_reg[offset]->name);
2058 if(strcmp(s,zero)==0) {
2059 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2061 } else if(strcmp(s,"W")==0) {
2062 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2063 pcop->type = PO_GPR_REGISTER;
2065 PCOR(pcop)->rIdx = -1;
2066 PCOR(pcop)->r = NULL;
2068 DEBUGpic16_emitcode(";","%d",__LINE__);
2069 pcop->name = Safe_strdup(s);
2070 pic16_emitpcode(POC_MOVFW,pcop);
2071 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2072 } else if(strcmp(s,one)==0) {
2073 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2074 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2076 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2084 if (aop->type == AOP_DPTR2)
2090 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2091 "pic16_aopPut writting to code space");
2095 while (offset > aop->coff) {
2097 pic16_emitcode ("inc","dptr");
2100 while (offset < aop->coff) {
2102 pic16_emitcode("lcall","__decdptr");
2107 /* if not in accumulater */
2110 pic16_emitcode ("movx","@dptr,a");
2112 if (aop->type == AOP_DPTR2)
2120 while (offset > aop->coff) {
2122 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2124 while (offset < aop->coff) {
2126 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2132 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2137 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2139 if (strcmp(s,"r0") == 0 ||
2140 strcmp(s,"r1") == 0 ||
2141 strcmp(s,"r2") == 0 ||
2142 strcmp(s,"r3") == 0 ||
2143 strcmp(s,"r4") == 0 ||
2144 strcmp(s,"r5") == 0 ||
2145 strcmp(s,"r6") == 0 ||
2146 strcmp(s,"r7") == 0 ) {
2148 sprintf(buffer,"a%s",s);
2149 pic16_emitcode("mov","@%s,%s",
2150 aop->aopu.aop_ptr->name,buffer);
2152 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2157 if (strcmp(s,"a") == 0)
2158 pic16_emitcode("push","acc");
2160 pic16_emitcode("push","%s",s);
2165 /* if bit variable */
2166 if (!aop->aopu.aop_dir) {
2167 pic16_emitcode("clr","a");
2168 pic16_emitcode("rlc","a");
2171 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2174 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2177 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2179 lbl = newiTempLabel(NULL);
2181 if (strcmp(s,"a")) {
2184 pic16_emitcode("clr","c");
2185 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2186 pic16_emitcode("cpl","c");
2187 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2188 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2195 if (strcmp(aop->aopu.aop_str[offset],s))
2196 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2201 if (!offset && (strcmp(s,"acc") == 0))
2204 if (strcmp(aop->aopu.aop_str[offset],s))
2205 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2209 fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2210 // werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2211 // "pic16_aopPut got unsupported aop->type");
2217 /*-----------------------------------------------------------------*/
2218 /* mov2w - generate either a MOVLW or MOVFW based operand type */
2219 /*-----------------------------------------------------------------*/
2220 static void mov2w (asmop *aop, int offset)
2222 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2225 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2227 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2230 static void mov2f(asmop *dst, asmop *src, int offset)
2232 if(is_LitAOp(src)) {
2233 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2234 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2236 if(pic16_sameRegsOfs(src, dst, offset))return;
2237 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2238 pic16_popGet(dst, offset)));
2242 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2244 if(is_LitAOp(src)) {
2245 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2246 pic16_emitpcode(POC_MOVWF, dst);
2248 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2252 void pic16_testStackOverflow(void)
2254 #define GSTACK_TEST_NAME "__gstack_test"
2256 pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2261 sym = newSymbol( GSTACK_TEST_NAME , 0 );
2262 strcpy(sym->rname, GSTACK_TEST_NAME);
2263 checkAddSym(&externs, sym);
2268 /* push pcop into stack */
2269 void pic16_pushpCodeOp(pCodeOp *pcop)
2271 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2272 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
2273 if(pic16_options.gstack)
2274 pic16_testStackOverflow();
2278 /* pop pcop from stack */
2279 void pic16_poppCodeOp(pCodeOp *pcop)
2281 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
2282 if(pic16_options.gstack)
2283 pic16_testStackOverflow();
2287 /*-----------------------------------------------------------------*/
2288 /* pushw - pushes wreg to stack */
2289 /*-----------------------------------------------------------------*/
2292 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2293 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
2294 if(pic16_options.gstack)
2295 pic16_testStackOverflow();
2299 /*-----------------------------------------------------------------*/
2300 /* pushaop - pushes aop to stack */
2301 /*-----------------------------------------------------------------*/
2302 void pushaop(asmop *aop, int offset)
2304 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2306 if(is_LitAOp(aop)) {
2307 pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2308 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
2310 pic16_emitpcode(POC_MOVFF,
2311 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg(&pic16_pc_postdec1)));
2314 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
2315 if(pic16_options.gstack)
2316 pic16_testStackOverflow();
2319 /*-----------------------------------------------------------------*/
2320 /* popaop - pops aop from stack */
2321 /*-----------------------------------------------------------------*/
2322 void popaop(asmop *aop, int offset)
2324 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2325 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
2326 if(pic16_options.gstack)
2327 pic16_testStackOverflow();
2330 void popaopidx(asmop *aop, int offset, int index)
2334 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2336 if(STACK_MODEL_LARGE)ofs++;
2338 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2339 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
2340 if(pic16_options.gstack)
2341 pic16_testStackOverflow();
2344 /*-----------------------------------------------------------------*/
2345 /* reAdjustPreg - points a register back to where it should */
2346 /*-----------------------------------------------------------------*/
2347 static void reAdjustPreg (asmop *aop)
2351 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2353 if ((size = aop->size) <= 1)
2356 switch (aop->type) {
2360 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2364 if (aop->type == AOP_DPTR2)
2370 pic16_emitcode("lcall","__decdptr");
2373 if (aop->type == AOP_DPTR2)
2385 /*-----------------------------------------------------------------*/
2386 /* opIsGptr: returns non-zero if the passed operand is */
2387 /* a generic pointer type. */
2388 /*-----------------------------------------------------------------*/
2389 static int opIsGptr(operand *op)
2391 sym_link *type = operandType(op);
2393 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2394 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2402 /*-----------------------------------------------------------------*/
2403 /* pic16_getDataSize - get the operand data size */
2404 /*-----------------------------------------------------------------*/
2405 int pic16_getDataSize(operand *op)
2407 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2410 return AOP_SIZE(op);
2412 // tsd- in the pic port, the genptr size is 1, so this code here
2413 // fails. ( in the 8051 port, the size was 4).
2416 size = AOP_SIZE(op);
2417 if (size == GPTRSIZE)
2419 sym_link *type = operandType(op);
2420 if (IS_GENPTR(type))
2422 /* generic pointer; arithmetic operations
2423 * should ignore the high byte (pointer type).
2426 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2433 /*-----------------------------------------------------------------*/
2434 /* pic16_outAcc - output Acc */
2435 /*-----------------------------------------------------------------*/
2436 void pic16_outAcc(operand *result)
2439 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2440 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2443 size = pic16_getDataSize(result);
2445 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2448 /* unsigned or positive */
2450 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2455 /*-----------------------------------------------------------------*/
2456 /* pic16_outBitC - output a bit C */
2457 /* Move to result the value of Carry flag -- VR */
2458 /*-----------------------------------------------------------------*/
2459 void pic16_outBitC(operand *result)
2463 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2465 /* if the result is bit */
2466 if (AOP_TYPE(result) == AOP_CRY) {
2467 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2468 pic16_aopPut(AOP(result),"c",0);
2471 i = AOP_SIZE(result);
2473 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2475 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2479 /*-----------------------------------------------------------------*/
2480 /* pic16_outBitOp - output a bit from Op */
2481 /* Move to result the value of set/clr op -- VR */
2482 /*-----------------------------------------------------------------*/
2483 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2487 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2489 /* if the result is bit */
2490 if (AOP_TYPE(result) == AOP_CRY) {
2491 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2492 pic16_aopPut(AOP(result),"c",0);
2495 i = AOP_SIZE(result);
2497 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2499 pic16_emitpcode(POC_RRCF, pcop);
2500 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2504 /*-----------------------------------------------------------------*/
2505 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2506 /*-----------------------------------------------------------------*/
2507 void pic16_toBoolean(operand *oper)
2509 int size = AOP_SIZE(oper) - 1;
2512 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2514 if ( AOP_TYPE(oper) != AOP_ACC) {
2515 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2518 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2523 #if !defined(GEN_Not)
2524 /*-----------------------------------------------------------------*/
2525 /* genNot - generate code for ! operation */
2526 /*-----------------------------------------------------------------*/
2527 static void pic16_genNot (iCode *ic)
2533 /* assign asmOps to operand & result */
2534 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2535 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2537 DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2538 /* if in bit space then a special case */
2539 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2540 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2541 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2542 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2544 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2545 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2546 pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2551 size = AOP_SIZE(IC_LEFT(ic));
2553 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2554 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2555 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2558 pic16_toBoolean(IC_LEFT(ic));
2560 tlbl = newiTempLabel(NULL);
2561 pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2562 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2563 pic16_outBitC(IC_RESULT(ic));
2566 /* release the aops */
2567 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2568 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2573 #if !defined(GEN_Cpl)
2574 /*-----------------------------------------------------------------*/
2575 /* genCpl - generate code for complement */
2576 /*-----------------------------------------------------------------*/
2577 static void pic16_genCpl (iCode *ic)
2583 /* assign asmOps to operand & result */
2584 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2585 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2587 /* if both are in bit space then
2589 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2590 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2592 pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
2593 pic16_emitcode("cpl","c");
2594 pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
2598 size = AOP_SIZE(IC_RESULT(ic));
2601 char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2603 pic16_emitcode("cpl","a");
2604 pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2606 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2607 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)), offset));
2609 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2610 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2618 /* release the aops */
2619 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2620 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2624 /*-----------------------------------------------------------------*/
2625 /* genUminusFloat - unary minus for floating points */
2626 /*-----------------------------------------------------------------*/
2627 static void genUminusFloat(operand *op,operand *result)
2629 int size ,offset =0 ;
2632 /* for this we just need to flip the
2633 first it then copy the rest in place */
2634 size = AOP_SIZE(op);
2637 mov2f(AOP(result), AOP(op), offset);
2641 /* toggle the MSB's highest bit */
2642 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2645 /*-----------------------------------------------------------------*/
2646 /* genUminus - unary minus code generation */
2647 /*-----------------------------------------------------------------*/
2648 static void genUminus (iCode *ic)
2651 sym_link *optype, *rtype;
2656 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2657 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2659 /* if both in bit space then special case */
2660 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2661 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2663 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2664 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2665 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2669 optype = operandType(IC_LEFT(ic));
2670 rtype = operandType(IC_RESULT(ic));
2672 /* if float then do float stuff */
2673 if (IS_FLOAT(optype)) {
2674 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2678 /* otherwise subtract from zero by taking the 2's complement */
2679 size = AOP_SIZE(IC_LEFT(ic));
2681 for(i=0; i<size; i++) {
2682 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2683 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)),i));
2685 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2686 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2690 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2691 for(i=1; i<size; i++) {
2693 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2697 /* release the aops */
2698 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2699 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2703 /*-----------------------------------------------------------------*/
2704 /* saveRegisters - will look for a call and save the registers */
2705 /*-----------------------------------------------------------------*/
2706 static void saveRegisters(iCode *lic)
2713 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2715 for (ic = lic ; ic ; ic = ic->next)
2716 if (ic->op == CALL || ic->op == PCALL)
2720 fprintf(stderr,"found parameter push with no function call\n");
2724 /* if the registers have been saved already then
2726 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2729 /* find the registers in use at this time
2730 and push them away to safety */
2731 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2735 if (options.useXstack) {
2736 if (bitVectBitValue(rsave,R0_IDX))
2737 pic16_emitcode("mov","b,r0");
2738 pic16_emitcode("mov","r0,%s",spname);
2739 for (i = 0 ; i < pic16_nRegs ; i++) {
2740 if (bitVectBitValue(rsave,i)) {
2742 pic16_emitcode("mov","a,b");
2744 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2745 pic16_emitcode("movx","@r0,a");
2746 pic16_emitcode("inc","r0");
2749 pic16_emitcode("mov","%s,r0",spname);
2750 if (bitVectBitValue(rsave,R0_IDX))
2751 pic16_emitcode("mov","r0,b");
2753 //for (i = 0 ; i < pic16_nRegs ; i++) {
2754 // if (bitVectBitValue(rsave,i))
2755 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2758 dtype = operandType(IC_LEFT(ic));
2759 if (currFunc && dtype &&
2760 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2761 IFFUNC_ISISR(currFunc->type) &&
2764 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2767 /*-----------------------------------------------------------------*/
2768 /* unsaveRegisters - pop the pushed registers */
2769 /*-----------------------------------------------------------------*/
2770 static void unsaveRegisters (iCode *ic)
2775 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2776 /* find the registers in use at this time
2777 and push them away to safety */
2778 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2781 if (options.useXstack) {
2782 pic16_emitcode("mov","r0,%s",spname);
2783 for (i = pic16_nRegs ; i >= 0 ; i--) {
2784 if (bitVectBitValue(rsave,i)) {
2785 pic16_emitcode("dec","r0");
2786 pic16_emitcode("movx","a,@r0");
2788 pic16_emitcode("mov","b,a");
2790 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2794 pic16_emitcode("mov","%s,r0",spname);
2795 if (bitVectBitValue(rsave,R0_IDX))
2796 pic16_emitcode("mov","r0,b");
2798 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2799 // if (bitVectBitValue(rsave,i))
2800 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2807 /*-----------------------------------------------------------------*/
2809 /*-----------------------------------------------------------------*/
2810 static void pushSide(operand * oper, int size)
2813 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2815 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2816 if (AOP_TYPE(oper) != AOP_REG &&
2817 AOP_TYPE(oper) != AOP_DIR &&
2819 pic16_emitcode("mov","a,%s",l);
2820 pic16_emitcode("push","acc");
2822 pic16_emitcode("push","%s",l);
2827 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2829 if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2830 pic16_emitpcode(POC_MOVFW, src);
2831 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2833 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2834 src, pic16_popGet(AOP(op), offset)));
2839 /*-----------------------------------------------------------------*/
2840 /* assignResultValue - assign results to oper, rescall==1 is */
2841 /* called from genCall() or genPcall() */
2842 /*-----------------------------------------------------------------*/
2843 static void assignResultValue(operand * oper, int rescall)
2845 int size = AOP_SIZE(oper);
2849 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2850 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2853 /* assign result from a call/pcall function() */
2855 /* function results are stored in a special order,
2856 * see top of file with Function return policy, or manual */
2859 /* 8-bits, result in WREG */
2860 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2863 /* 16-bits, result in PRODL:WREG */
2864 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2868 /* 24-bits, result in PRODH:PRODL:WREG */
2869 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2873 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2874 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2878 /* >32-bits, result on stack, and FSR0 points to beginning.
2879 * Fix stack when done */
2881 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2883 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2884 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2886 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2891 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2892 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2893 if(STACK_MODEL_LARGE) {
2895 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2899 int areg = 0; /* matching argument register */
2901 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
2902 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
2905 /* its called from genReceive (probably) -- VR */
2906 if(!GpsuedoStkPtr && _G.useWreg) {
2907 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2909 /* The last byte in the assignment is in W */
2910 if(areg <= GpsuedoStkPtr) {
2912 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
2914 // debugf("receive from WREG\n", 0);
2918 _G.stack_lat = AOP_SIZE(oper)-1;
2923 popaopidx(AOP(oper), offset, GpsuedoStkPtr);
2924 // debugf("receive from STACK\n", 0);
2931 /*-----------------------------------------------------------------*/
2932 /* genIpush - generate code for pushing this gets a little complex */
2933 /*-----------------------------------------------------------------*/
2934 static void genIpush (iCode *ic)
2936 // int size, offset=0;
2939 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2942 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
2944 /* send to stack as normal */
2945 addSet(&_G.sendSet,ic);
2946 // addSetHead(&_G.sendSet,ic);
2947 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2952 int size, offset = 0 ;
2956 /* if this is not a parm push : ie. it is spill push
2957 and spill push is always done on the local stack */
2958 if (!ic->parmPush) {
2960 /* and the item is spilt then do nothing */
2961 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2964 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2965 size = AOP_SIZE(IC_LEFT(ic));
2966 /* push it on the stack */
2968 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2973 pic16_emitcode("push","%s",l);
2978 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2982 /*-----------------------------------------------------------------*/
2983 /* genIpop - recover the registers: can happen only for spilling */
2984 /*-----------------------------------------------------------------*/
2985 static void genIpop (iCode *ic)
2988 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2993 /* if the temp was not pushed then */
2994 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2997 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2998 size = AOP_SIZE(IC_LEFT(ic));
3001 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3004 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3009 /*-----------------------------------------------------------------*/
3010 /* unsaverbank - restores the resgister bank from stack */
3011 /*-----------------------------------------------------------------*/
3012 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3014 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3020 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3022 if (options.useXstack) {
3024 r = getFreePtr(ic,&aop,FALSE);
3027 pic16_emitcode("mov","%s,_spx",r->name);
3028 pic16_emitcode("movx","a,@%s",r->name);
3029 pic16_emitcode("mov","psw,a");
3030 pic16_emitcode("dec","%s",r->name);
3033 pic16_emitcode ("pop","psw");
3036 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3037 if (options.useXstack) {
3038 pic16_emitcode("movx","a,@%s",r->name);
3039 //pic16_emitcode("mov","(%s+%d),a",
3040 // regspic16[i].base,8*bank+regspic16[i].offset);
3041 pic16_emitcode("dec","%s",r->name);
3044 pic16_emitcode("pop",""); //"(%s+%d)",
3045 //regspic16[i].base,8*bank); //+regspic16[i].offset);
3048 if (options.useXstack) {
3050 pic16_emitcode("mov","_spx,%s",r->name);
3051 pic16_freeAsmop(NULL,aop,ic,TRUE);
3057 /*-----------------------------------------------------------------*/
3058 /* saverbank - saves an entire register bank on the stack */
3059 /*-----------------------------------------------------------------*/
3060 static void saverbank (int bank, iCode *ic, bool pushPsw)
3062 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3068 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3069 if (options.useXstack) {
3072 r = getFreePtr(ic,&aop,FALSE);
3073 pic16_emitcode("mov","%s,_spx",r->name);
3077 for (i = 0 ; i < pic16_nRegs ;i++) {
3078 if (options.useXstack) {
3079 pic16_emitcode("inc","%s",r->name);
3080 //pic16_emitcode("mov","a,(%s+%d)",
3081 // regspic16[i].base,8*bank+regspic16[i].offset);
3082 pic16_emitcode("movx","@%s,a",r->name);
3084 pic16_emitcode("push","");// "(%s+%d)",
3085 //regspic16[i].base,8*bank+regspic16[i].offset);
3089 if (options.useXstack) {
3090 pic16_emitcode("mov","a,psw");
3091 pic16_emitcode("movx","@%s,a",r->name);
3092 pic16_emitcode("inc","%s",r->name);
3093 pic16_emitcode("mov","_spx,%s",r->name);
3094 pic16_freeAsmop (NULL,aop,ic,TRUE);
3097 pic16_emitcode("push","psw");
3099 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3107 static int wparamCmp(void *p1, void *p2)
3109 return (!strcmp((char *)p1, (char *)p2));
3112 int inWparamList(char *s)
3114 return isinSetWith(wparamList, s, wparamCmp);
3118 /*-----------------------------------------------------------------*/
3119 /* genCall - generates a call statement */
3120 /*-----------------------------------------------------------------*/
3121 static void genCall (iCode *ic)
3131 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3132 /* if caller saves & we have not saved then */
3133 // if (!ic->regsSaved)
3134 // saveRegisters(ic);
3136 /* initialise stackParms for IPUSH pushes */
3137 // stackParms = psuedoStkPtr;
3138 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3139 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3140 inwparam = inWparamList(OP_SYMBOL(IC_LEFT(ic))->name);
3143 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3146 /* if send set is not empty the assign */
3149 int psuedoStkPtr=-1;
3150 int firstTimeThruLoop = 1;
3153 /* reverse sendSet if function is not reentrant */
3154 if(!IFFUNC_ISREENT(ftype))
3155 _G.sendSet = reverseSet(_G.sendSet);
3157 /* First figure how many parameters are getting passed */
3161 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3165 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3166 size = AOP_SIZE(IC_LEFT(sic));
3170 /* pass the last byte through WREG */
3174 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3175 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3176 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3178 if(!firstTimeThruLoop) {
3179 /* If this is not the first time we've been through the loop
3180 * then we need to save the parameter in a temporary
3181 * register. The last byte of the last parameter is
3185 // --psuedoStkPtr; // sanity check
3189 firstTimeThruLoop=0;
3191 mov2w (AOP(IC_LEFT(sic)), size);
3196 /* all arguments are passed via stack */
3200 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3201 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3202 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3204 // pushaop(AOP(IC_LEFT(sic)), size);
3205 mov2w (AOP(IC_LEFT(sic)), size);
3210 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3214 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3215 pushw(); /* save last parameter to stack if functions has varargs */
3219 } else use_wreg = 0;
3221 _G.stackRegSet = _G.sendSet;
3226 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3230 /* if we need to assign a result value */
3231 if ((IS_ITEMP(IC_RESULT(ic))
3232 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3233 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3234 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3237 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3240 assignResultValue(IC_RESULT(ic), 1);
3242 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3243 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3245 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3248 if(!stackParms && ic->parmBytes) {
3249 stackParms = ic->parmBytes;
3252 stackParms -= use_wreg;
3255 if(stackParms == 1) {
3256 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1l));
3258 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3259 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3261 if(STACK_MODEL_LARGE) {
3263 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3268 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3271 /* adjust the stack for parameters if required */
3272 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3275 /* if register bank was saved then pop them */
3277 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3279 /* if we hade saved some registers then unsave them */
3280 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3281 unsaveRegisters (ic);
3287 /*-----------------------------------------------------------------*/
3288 /* genPcall - generates a call by pointer statement */
3289 /* new version, created from genCall - HJD */
3290 /*-----------------------------------------------------------------*/
3291 static void genPcall (iCode *ic)
3293 sym_link *ftype, *fntype;
3295 symbol *retlbl = newiTempLabel(NULL);
3296 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3300 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3301 fntype = operandType( IC_LEFT(ic) )->next;
3303 /* if send set is not empty the assign */
3306 int psuedoStkPtr=-1;
3308 /* reverse sendSet if function is not reentrant */
3309 if(!IFFUNC_ISREENT(fntype))
3310 _G.sendSet = reverseSet(_G.sendSet);
3314 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3317 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3318 size = AOP_SIZE(IC_LEFT(sic));
3321 /* all parameters are passed via stack, since WREG is clobbered
3322 * by the calling sequence */
3324 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3325 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3326 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3328 mov2w (AOP(IC_LEFT(sic)), size);
3332 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3335 _G.stackRegSet = _G.sendSet;
3339 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3341 // push return address
3342 // push $ on return stack, then replace with retlbl
3344 pic16_emitpcodeNULLop(POC_PUSH);
3346 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3347 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3348 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3349 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3350 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3351 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3353 /* make the call by writing the pointer into pc */
3354 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3355 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3357 // note: MOVFF to PCL not allowed
3358 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3359 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3362 /* return address is here: (X) */
3363 pic16_emitpLabelFORCE(retlbl->key);
3365 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3368 /* if we need assign a result value */
3369 if ((IS_ITEMP(IC_RESULT(ic))
3370 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3371 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3372 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3375 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3378 assignResultValue(IC_RESULT(ic), 1);
3380 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3381 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3383 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3386 // stackParms -= use_wreg;
3389 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3390 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3391 if(STACK_MODEL_LARGE) {
3392 /* this implies that stackParms < 256 !!! -- VR */
3394 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3399 /*-----------------------------------------------------------------*/
3400 /* resultRemat - result is rematerializable */
3401 /*-----------------------------------------------------------------*/
3402 static int resultRemat (iCode *ic)
3404 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3405 if (SKIP_IC(ic) || ic->op == IFX)
3408 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3409 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3410 if (sym->remat && !POINTER_SET(ic))
3417 #if defined(__BORLANDC__) || defined(_MSC_VER)
3418 #define STRCASECMP stricmp
3420 #define STRCASECMP strcasecmp
3424 /*-----------------------------------------------------------------*/
3425 /* inExcludeList - return 1 if the string is in exclude Reg list */
3426 /*-----------------------------------------------------------------*/
3427 static bool inExcludeList(char *s)
3429 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3432 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3433 if (options.excludeRegs[i] &&
3434 STRCASECMP(options.excludeRegs[i],"none") == 0)
3437 for ( i = 0 ; options.excludeRegs[i]; i++) {
3438 if (options.excludeRegs[i] &&
3439 STRCASECMP(s,options.excludeRegs[i]) == 0)
3446 /*-----------------------------------------------------------------*/
3447 /* genFunction - generated code for function entry */
3448 /*-----------------------------------------------------------------*/
3449 static void genFunction (iCode *ic)
3455 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3457 pic16_labelOffset += (max_key+4);
3462 ftype = operandType(IC_LEFT(ic));
3463 sym = OP_SYMBOL(IC_LEFT(ic));
3465 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3466 /* create an absolute section at the interrupt vector:
3467 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3475 sym = OP_SYMBOL( IC_LEFT(ic));
3477 if(interrupts[i]->name
3478 && !STRCASECMP(interrupts[i]->name, sym->name)) {
3485 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3486 __FILE__, __LINE__, sym->name);
3489 _G.interruptvector = found;
3492 sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3493 asym = newSymbol(asymname, 0);
3495 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3496 pic16_addpBlock( apb );
3498 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3499 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3500 pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3502 /* mark the end of this tiny function */
3503 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3508 abSym = Safe_calloc(1, sizeof(absSym));
3509 strcpy(abSym->name, asymname);
3511 switch( _G.interruptvector ) {
3512 case 0: abSym->address = 0x000000; break;
3513 case 1: abSym->address = 0x000008; break;
3514 case 2: abSym->address = 0x000018; break;
3517 /* relocate interrupt vectors if needed */
3518 abSym->address += pic16_options.ivt_loc;
3520 addSet(&absSymSet, abSym);
3524 /* create the function header */
3525 pic16_emitcode(";","-----------------------------------------");
3526 pic16_emitcode(";"," function %s",sym->name);
3527 pic16_emitcode(";","-----------------------------------------");
3529 pic16_emitcode("","%s:",sym->rname);
3530 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3536 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3537 if(!strcmp(ab->name, sym->rname)) {
3538 pic16_pBlockConvert2Absolute(pb);
3545 if(IFFUNC_ISNAKED(ftype)) {
3546 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3550 /* if critical function then turn interrupts off */
3551 if (IFFUNC_ISCRITICAL(ftype)) {
3552 //pic16_emitcode("clr","ea");
3555 _G.fregsUsed = sym->regsUsed;
3557 /* if this is an interrupt service routine then
3558 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3559 if (IFFUNC_ISISR(sym->type)) {
3560 _G.usefastretfie = 1; /* use shadow registers by default */
3562 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3563 if(!(_G.interruptvector == 1)) {
3564 /* do not save WREG,STATUS,BSR for high priority interrupts
3565 * because they are stored in the hardware shadow registers already */
3566 _G.usefastretfie = 0;
3567 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3568 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3569 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3572 /* these should really be optimized somehow, because not all
3573 * interrupt handlers modify them */
3574 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3575 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3576 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3577 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3579 // pic16_pBlockConvert2ISR(pb);
3583 /* emit code to setup stack frame if user enabled,
3584 * and function is not main() */
3586 //fprintf(stderr, "function name: %s\n", sym->name);
3587 if(strcmp(sym->name, "main")) {
3588 if(1 /*!options.ommitFramePtr || sym->regsUsed*/) {
3589 /* setup the stack frame */
3590 if(STACK_MODEL_LARGE)
3591 pic16_pushpCodeOp(pic16_popCopyReg(&pic16_pc_fsr2h));
3592 pic16_pushpCodeOp(pic16_popCopyReg(&pic16_pc_fsr2l));
3593 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3594 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3595 if(STACK_MODEL_LARGE)
3596 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3600 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3603 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3605 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3606 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(&pic16_pc_fsr1l));
3608 pic16_emitpcode(POC_DECF, pic16_popCopyReg(&pic16_pc_fsr1h));
3611 if(inWparamList(sym->name)) {
3612 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3619 /* if callee-save to be used for this function
3620 * then save the registers being used in this function */
3621 // if (IFFUNC_CALLEESAVES(sym->type))
3625 /* if any registers used */
3626 if (sym->regsUsed) {
3627 /* save the registers used */
3628 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3629 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3630 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3631 if (bitVectBitValue(sym->regsUsed,i)) {
3632 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3635 if(!pic16_regWithIdx(i)->wasUsed) {
3636 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3637 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3638 pic16_regWithIdx(i)->wasUsed = 1;
3642 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3646 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3647 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3650 /*-----------------------------------------------------------------*/
3651 /* genEndFunction - generates epilogue for functions */
3652 /*-----------------------------------------------------------------*/
3653 static void genEndFunction (iCode *ic)
3655 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3659 if(IFFUNC_ISNAKED(sym->type)) {
3660 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3666 /* add code for ISCRITICAL */
3667 if(IFFUNC_ISCRITICAL(sym->type)) {
3668 /* if critical function, turn on interrupts */
3670 /* TODO: add code here -- VR */
3673 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3675 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3676 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg(&pic16_pc_fsr1l));
3678 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1h));
3681 // sym->regsUsed = _G.fregsUsed;
3683 /* now we need to restore the registers */
3684 /* if any registers used */
3685 if (sym->regsUsed) {
3688 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3689 /* restore registers used */
3690 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3691 for ( i = sym->regsUsed->size; i >= 0; i--) {
3692 if (bitVectBitValue(sym->regsUsed,i)) {
3693 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3697 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3701 if(strcmp(sym->name, "main")) {
3702 if(1/*!options.ommitFramePtr ||*/ /*sym->regsUsed*/) {
3703 /* restore stack frame */
3704 if(STACK_MODEL_LARGE)
3705 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr2h ));
3706 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3707 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr2l ));
3708 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3714 if (IFFUNC_ISISR(sym->type)) {
3715 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3716 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3717 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3718 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3720 if(!(_G.interruptvector == 1)) {
3721 /* do not restore interrupt vector for WREG,STATUS,BSR
3722 * for high priority interrupt, see genFunction */
3723 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3724 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3725 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3727 _G.interruptvector = 0; /* sanity check */
3730 /* if debug then send end of function */
3731 /* if (options.debug && currFunc) */
3733 debugFile->writeEndFunction (currFunc, ic, 1);
3736 if(_G.usefastretfie)
3737 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3739 pic16_emitpcodeNULLop(POC_RETFIE);
3741 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3743 _G.usefastretfie = 0;
3747 if (IFFUNC_ISCRITICAL(sym->type)) {
3748 pic16_emitcode("setb","ea");
3751 /* if debug then send end of function */
3753 debugFile->writeEndFunction (currFunc, ic, 1);
3756 /* insert code to restore stack frame, if user enabled it
3757 * and function is not main() */
3760 pic16_emitpcodeNULLop(POC_RETURN);
3762 /* Mark the end of a function */
3763 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3767 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3770 unsigned long lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3772 pic16_emitpcode(POC_CLRF, dest);
3774 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
3775 if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
3778 if(dest->type == PO_WREG && (offset == 0)) {
3779 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3782 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3786 /*-----------------------------------------------------------------*/
3787 /* genRet - generate code for return statement */
3788 /*-----------------------------------------------------------------*/
3789 static void genRet (iCode *ic)
3795 /* if we have no return value then
3796 * just generate the "ret" */
3801 /* we have something to return then
3802 * move the return value into place */
3803 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3804 size = AOP_SIZE(IC_LEFT(ic));
3808 pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3809 // pic16_emitpcode(POC_MOVFF,
3810 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3813 pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3814 // pic16_emitpcode(POC_MOVFF,
3815 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3818 pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3819 // pic16_emitpcode(POC_MOVFF,
3820 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3823 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0)); // patch 12
3825 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg)); // patch 12
3826 // pic16_emitpcode(POC_MOVFF,
3827 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3830 /* >32-bits, setup stack and FSR0 */
3832 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3833 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3835 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3837 // popaopidx(AOP(oper), size, GpseudoStkPtr);
3842 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3843 pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3845 if(STACK_MODEL_LARGE) {
3846 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3847 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3849 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3854 /* old code, left here for reference -- VR */
3858 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3860 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3861 pic16_emitpcomment("push %s",l);
3864 DEBUGpic16_emitcode(";", "%d", __LINE__);
3865 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3866 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
3868 if (strcmp(fReturn[offset],l)) {
3869 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3870 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3871 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3873 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3877 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3887 if (strcmp(fReturn[pushed],"a"))
3888 pic16_emitcode("pop",fReturn[pushed]);
3890 pic16_emitcode("pop","acc");
3896 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3899 /* generate a jump to the return label
3900 * if the next is not the return statement */
3901 if (!(ic->next && ic->next->op == LABEL
3902 && IC_LABEL(ic->next) == returnLabel)) {
3904 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3905 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3909 /*-----------------------------------------------------------------*/
3910 /* genLabel - generates a label */
3911 /*-----------------------------------------------------------------*/
3912 static void genLabel (iCode *ic)
3916 /* special case never generate */
3917 if (IC_LABEL(ic) == entryLabel)
3920 pic16_emitpLabel(IC_LABEL(ic)->key);
3921 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3924 /*-----------------------------------------------------------------*/
3925 /* genGoto - generates a goto */
3926 /*-----------------------------------------------------------------*/
3928 static void genGoto (iCode *ic)
3931 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3932 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3936 /*-----------------------------------------------------------------*/
3937 /* genMultbits :- multiplication of bits */
3938 /*-----------------------------------------------------------------*/
3939 static void genMultbits (operand *left,
3945 if(!pic16_sameRegs(AOP(result),AOP(right)))
3946 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
3948 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3949 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3950 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
3955 /*-----------------------------------------------------------------*/
3956 /* genMultOneByte : 8 bit multiplication & division */
3957 /*-----------------------------------------------------------------*/
3958 static void genMultOneByte (operand *left,
3964 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3965 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3967 /* (if two literals, the value is computed before) */
3968 /* if one literal, literal on the right */
3969 if (AOP_TYPE(left) == AOP_LIT){
3975 /* size is already checked in genMult == 1 */
3976 // size = AOP_SIZE(result);
3978 if (AOP_TYPE(right) == AOP_LIT){
3979 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3980 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3981 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3982 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3984 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3985 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3986 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3987 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3990 pic16_genMult8X8_8 (left, right,result);
3993 /*-----------------------------------------------------------------*/
3994 /* genMultOneWord : 16 bit multiplication */
3995 /*-----------------------------------------------------------------*/
3996 static void genMultOneWord (operand *left,
4001 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4002 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4004 /* (if two literals, the value is computed before)
4005 * if one literal, literal on the right */
4006 if (AOP_TYPE(left) == AOP_LIT){
4012 /* size is checked already == 2 */
4013 // size = AOP_SIZE(result);
4015 if (AOP_TYPE(right) == AOP_LIT) {
4016 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4017 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4018 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4019 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4021 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4022 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4023 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4024 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4027 pic16_genMult16X16_16(left, right,result);
4030 /*-----------------------------------------------------------------*/
4031 /* genMultOneLong : 32 bit multiplication */
4032 /*-----------------------------------------------------------------*/
4033 static void genMultOneLong (operand *left,
4038 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4039 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4041 /* (if two literals, the value is computed before)
4042 * if one literal, literal on the right */
4043 if (AOP_TYPE(left) == AOP_LIT){
4049 /* size is checked already == 4 */
4050 // size = AOP_SIZE(result);
4052 if (AOP_TYPE(right) == AOP_LIT) {
4053 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4054 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4055 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4056 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4058 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4059 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4060 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4061 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4064 pic16_genMult32X32_32(left, right,result);
4069 /*-----------------------------------------------------------------*/
4070 /* genMult - generates code for multiplication */
4071 /*-----------------------------------------------------------------*/
4072 static void genMult (iCode *ic)
4074 operand *left = IC_LEFT(ic);
4075 operand *right = IC_RIGHT(ic);
4076 operand *result= IC_RESULT(ic);
4079 /* assign the amsops */
4080 pic16_aopOp (left,ic,FALSE);
4081 pic16_aopOp (right,ic,FALSE);
4082 pic16_aopOp (result,ic,TRUE);
4084 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4086 /* special cases first *
4088 if (AOP_TYPE(left) == AOP_CRY
4089 && AOP_TYPE(right)== AOP_CRY) {
4090 genMultbits(left,right,result);
4094 /* if both are of size == 1 */
4095 if(AOP_SIZE(left) == 1
4096 && AOP_SIZE(right) == 1) {
4097 genMultOneByte(left,right,result);
4101 /* if both are of size == 2 */
4102 if(AOP_SIZE(left) == 2
4103 && AOP_SIZE(right) == 2) {
4104 genMultOneWord(left, right, result);
4108 /* if both are of size == 4 */
4109 if(AOP_SIZE(left) == 4
4110 && AOP_SIZE(right) == 4) {
4111 genMultOneLong(left, right, result);
4115 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4118 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4119 /* should have been converted to function call */
4123 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4124 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4125 pic16_freeAsmop(result,NULL,ic,TRUE);
4128 /*-----------------------------------------------------------------*/
4129 /* genDivbits :- division of bits */
4130 /*-----------------------------------------------------------------*/
4131 static void genDivbits (operand *left,
4138 /* the result must be bit */
4139 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4140 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4144 pic16_emitcode("div","ab");
4145 pic16_emitcode("rrc","a");
4146 pic16_aopPut(AOP(result),"c",0);
4149 /*-----------------------------------------------------------------*/
4150 /* genDivOneByte : 8 bit division */
4151 /*-----------------------------------------------------------------*/
4152 static void genDivOneByte (operand *left,
4156 sym_link *opetype = operandType(result);
4161 /* result = divident / divisor
4162 * - divident may be a register or a literal,
4163 * - divisor may be a register or a literal,
4164 * so there are 3 cases (literal / literal is optimized
4165 * by the front-end) to handle.
4166 * In addition we must handle signed and unsigned, which
4167 * result in 6 final different cases -- VR */
4171 size = AOP_SIZE(result) - 1;
4173 /* signed or unsigned */
4174 if (SPEC_USIGN(opetype)) {
4175 pCodeOp *pct1, /* count */
4178 symbol *label1, *label2, *label3;;
4181 /* unsigned is easy */
4183 pct1 = pic16_popGetTempReg(1);
4184 pct2 = pic16_popGetTempReg(1);
4185 pct3 = pic16_popGetTempReg(1);
4187 label1 = newiTempLabel(NULL);
4188 label2 = newiTempLabel(NULL);
4189 label3 = newiTempLabel(NULL);
4191 /* the following algorithm is extracted from divuint.c */
4193 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4194 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4196 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4198 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4200 pic16_emitpLabel(label1->key);
4203 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4207 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4211 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4213 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4214 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4216 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4217 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4218 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4220 pic16_emitpLabel( label3->key );
4221 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4222 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4226 pic16_emitpLabel(label2->key);
4227 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4228 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4229 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4231 /* result is in wreg */
4232 if(AOP_TYPE(result) != AOP_ACC)
4233 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4235 pic16_popReleaseTempReg( pct3, 1);
4236 pic16_popReleaseTempReg( pct2, 1);
4237 pic16_popReleaseTempReg( pct1, 1);
4242 /* signed is a little bit more difficult */
4244 /* save the signs of the operands */
4245 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4247 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4248 pic16_emitcode("push","acc"); /* save it on the stack */
4250 /* now sign adjust for both left & right */
4251 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4253 lbl = newiTempLabel(NULL);
4254 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4255 pic16_emitcode("cpl","a");
4256 pic16_emitcode("inc","a");
4257 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4258 pic16_emitcode("mov","b,a");
4260 /* sign adjust left side */
4261 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4264 lbl = newiTempLabel(NULL);
4265 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4266 pic16_emitcode("cpl","a");
4267 pic16_emitcode("inc","a");
4268 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4270 /* now the division */
4271 pic16_emitcode("div","ab");
4272 /* we are interested in the lower order
4274 pic16_emitcode("mov","b,a");
4275 lbl = newiTempLabel(NULL);
4276 pic16_emitcode("pop","acc");
4277 /* if there was an over flow we don't
4278 adjust the sign of the result */
4279 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4280 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4282 pic16_emitcode("clr","a");
4283 pic16_emitcode("subb","a,b");
4284 pic16_emitcode("mov","b,a");
4285 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4287 /* now we are done */
4288 pic16_aopPut(AOP(result),"b",0);
4290 pic16_emitcode("mov","c,b.7");
4291 pic16_emitcode("subb","a,acc");
4294 pic16_aopPut(AOP(result),"a",offset++);
4298 /*-----------------------------------------------------------------*/
4299 /* genDiv - generates code for division */
4300 /*-----------------------------------------------------------------*/
4301 static void genDiv (iCode *ic)
4303 operand *left = IC_LEFT(ic);
4304 operand *right = IC_RIGHT(ic);
4305 operand *result= IC_RESULT(ic);
4308 /* Division is a very lengthy algorithm, so it is better
4309 * to call support routines than inlining algorithm.
4310 * Division functions written here just in case someone
4311 * wants to inline and not use the support libraries -- VR */
4315 /* assign the amsops */
4316 pic16_aopOp (left,ic,FALSE);
4317 pic16_aopOp (right,ic,FALSE);
4318 pic16_aopOp (result,ic,TRUE);
4320 /* special cases first */
4322 if (AOP_TYPE(left) == AOP_CRY &&
4323 AOP_TYPE(right)== AOP_CRY) {
4324 genDivbits(left,right,result);
4328 /* if both are of size == 1 */
4329 if (AOP_SIZE(left) == 1 &&
4330 AOP_SIZE(right) == 1 ) {
4331 genDivOneByte(left,right,result);
4335 /* should have been converted to function call */
4338 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4339 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4340 pic16_freeAsmop(result,NULL,ic,TRUE);
4343 /*-----------------------------------------------------------------*/
4344 /* genModbits :- modulus of bits */
4345 /*-----------------------------------------------------------------*/
4346 static void genModbits (operand *left,
4354 werror(W_POSSBUG2, __FILE__, __LINE__);
4355 /* the result must be bit */
4356 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4357 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4361 pic16_emitcode("div","ab");
4362 pic16_emitcode("mov","a,b");
4363 pic16_emitcode("rrc","a");
4364 pic16_aopPut(AOP(result),"c",0);
4367 /*-----------------------------------------------------------------*/
4368 /* genModOneByte : 8 bit modulus */
4369 /*-----------------------------------------------------------------*/
4370 static void genModOneByte (operand *left,
4374 sym_link *opetype = operandType(result);
4379 werror(W_POSSBUG2, __FILE__, __LINE__);
4381 /* signed or unsigned */
4382 if (SPEC_USIGN(opetype)) {
4383 /* unsigned is easy */
4384 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4385 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4387 pic16_emitcode("div","ab");
4388 pic16_aopPut(AOP(result),"b",0);
4392 /* signed is a little bit more difficult */
4394 /* save the signs of the operands */
4395 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4398 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4399 pic16_emitcode("push","acc"); /* save it on the stack */
4401 /* now sign adjust for both left & right */
4402 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 multiplication */
4423 pic16_emitcode("div","ab");
4424 /* we are interested in the lower order
4426 lbl = newiTempLabel(NULL);
4427 pic16_emitcode("pop","acc");
4428 /* if there was an over flow we don't
4429 adjust the sign of the result */
4430 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4431 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4433 pic16_emitcode("clr","a");
4434 pic16_emitcode("subb","a,b");
4435 pic16_emitcode("mov","b,a");
4436 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4438 /* now we are done */
4439 pic16_aopPut(AOP(result),"b",0);
4443 /*-----------------------------------------------------------------*/
4444 /* genMod - generates code for division */
4445 /*-----------------------------------------------------------------*/
4446 static void genMod (iCode *ic)
4448 operand *left = IC_LEFT(ic);
4449 operand *right = IC_RIGHT(ic);
4450 operand *result= IC_RESULT(ic);
4454 /* assign the amsops */
4455 pic16_aopOp (left,ic,FALSE);
4456 pic16_aopOp (right,ic,FALSE);
4457 pic16_aopOp (result,ic,TRUE);
4459 /* special cases first */
4461 if (AOP_TYPE(left) == AOP_CRY &&
4462 AOP_TYPE(right)== AOP_CRY) {
4463 genModbits(left,right,result);
4467 /* if both are of size == 1 */
4468 if (AOP_SIZE(left) == 1 &&
4469 AOP_SIZE(right) == 1 ) {
4470 genModOneByte(left,right,result);
4474 /* should have been converted to function call */
4478 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4479 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4480 pic16_freeAsmop(result,NULL,ic,TRUE);
4483 /*-----------------------------------------------------------------*/
4484 /* genIfxJump :- will create a jump depending on the ifx */
4485 /*-----------------------------------------------------------------*/
4487 note: May need to add parameter to indicate when a variable is in bit space.
4489 static void genIfxJump (iCode *ic, char *jval)
4493 /* if true label then we jump if condition
4495 if ( IC_TRUE(ic) ) {
4497 if(strcmp(jval,"a") == 0)
4499 else if (strcmp(jval,"c") == 0)
4502 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4503 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4506 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4507 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4511 /* false label is present */
4512 if(strcmp(jval,"a") == 0)
4514 else if (strcmp(jval,"c") == 0)
4517 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4518 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4521 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4522 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4527 /* mark the icode as generated */
4534 /*-----------------------------------------------------------------*/
4536 /*-----------------------------------------------------------------*/
4537 static void genSkip(iCode *ifx,int status_bit)
4539 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4543 if ( IC_TRUE(ifx) ) {
4544 switch(status_bit) {
4559 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4560 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4564 switch(status_bit) {
4578 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4579 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4586 /*-----------------------------------------------------------------*/
4588 /*-----------------------------------------------------------------*/
4589 static void genSkipc(resolvedIfx *rifx)
4591 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4601 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4602 rifx->generated = 1;
4605 /*-----------------------------------------------------------------*/
4607 /*-----------------------------------------------------------------*/
4608 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4610 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4615 if( (rifx->condition ^ invert_condition) & 1)
4620 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4621 rifx->generated = 1;
4625 /*-----------------------------------------------------------------*/
4627 /*-----------------------------------------------------------------*/
4628 static void genSkipz(iCode *ifx, int condition)
4639 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4641 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4644 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4646 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4651 /*-----------------------------------------------------------------*/
4653 /*-----------------------------------------------------------------*/
4654 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4660 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4662 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4665 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4666 rifx->generated = 1;
4670 /*-----------------------------------------------------------------*/
4671 /* genChkZeroes :- greater or less than comparison */
4672 /* For each byte in a literal that is zero, inclusive or the */
4673 /* the corresponding byte in the operand with W */
4674 /* returns true if any of the bytes are zero */
4675 /*-----------------------------------------------------------------*/
4676 static int genChkZeroes(operand *op, int lit, int size)
4683 i = (lit >> (size*8)) & 0xff;
4687 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4689 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4698 /*-----------------------------------------------------------------*/
4699 /* genCmp :- greater or less than comparison */
4700 /*-----------------------------------------------------------------*/
4704 static void genCmp (operand *left,operand *right,
4705 operand *result, iCode *ifx, int sign)
4707 int size; //, offset = 0 ;
4708 unsigned long lit = 0L,i = 0;
4709 resolvedIfx rFalseIfx;
4710 // resolvedIfx rTrueIfx;
4712 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4715 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4716 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4722 resolveIfx(&rFalseIfx,ifx);
4723 truelbl = newiTempLabel(NULL);
4724 size = max(AOP_SIZE(left),AOP_SIZE(right));
4726 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4730 /* if literal is on the right then swap with left */
4731 if ((AOP_TYPE(right) == AOP_LIT)) {
4732 operand *tmp = right ;
4733 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4734 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4737 lit = (lit - 1) & mask;
4740 rFalseIfx.condition ^= 1;
4743 } else if ((AOP_TYPE(left) == AOP_LIT)) {
4744 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4748 //if(IC_TRUE(ifx) == NULL)
4749 /* if left & right are bit variables */
4750 if (AOP_TYPE(left) == AOP_CRY &&
4751 AOP_TYPE(right) == AOP_CRY ) {
4752 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4753 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4755 /* subtract right from left if at the
4756 end the carry flag is set then we know that
4757 left is greater than right */
4759 symbol *lbl = newiTempLabel(NULL);
4762 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
4763 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
4767 if(AOP_TYPE(right) == AOP_LIT) {
4769 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4771 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
4778 genSkipCond(&rFalseIfx,left,size-1,7);
4780 /* no need to compare to 0...*/
4781 /* NOTE: this is a de-generate compare that most certainly
4782 * creates some dead code. */
4783 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4785 if(ifx) ifx->generated = 1;
4792 //i = (lit >> (size*8)) & 0xff;
4793 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4795 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4797 i = ((0-lit) & 0xff);
4800 /* lit is 0x7f, all signed chars are less than
4801 * this except for 0x7f itself */
4802 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4803 genSkipz2(&rFalseIfx,0);
4805 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4806 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4807 genSkipc(&rFalseIfx);
4812 genSkipz2(&rFalseIfx,1);
4814 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4815 genSkipc(&rFalseIfx);
4819 if(ifx) ifx->generated = 1;
4823 /* chars are out of the way. now do ints and longs */
4826 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4833 genSkipCond(&rFalseIfx,left,size,7);
4834 if(ifx) ifx->generated = 1;
4839 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4841 //rFalseIfx.condition ^= 1;
4842 //genSkipCond(&rFalseIfx,left,size,7);
4843 //rFalseIfx.condition ^= 1;
4845 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4846 if(rFalseIfx.condition)
4847 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4849 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4851 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4852 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4853 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4856 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4858 if(rFalseIfx.condition) {
4860 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4866 genSkipc(&rFalseIfx);
4867 pic16_emitpLabel(truelbl->key);
4868 if(ifx) ifx->generated = 1;
4875 if( (lit & 0xff) == 0) {
4876 /* lower byte is zero */
4877 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4878 i = ((lit >> 8) & 0xff) ^0x80;
4879 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4880 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4881 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4882 genSkipc(&rFalseIfx);
4885 if(ifx) ifx->generated = 1;
4890 /* Special cases for signed longs */
4891 if( (lit & 0xffffff) == 0) {
4892 /* lower byte is zero */
4893 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4894 i = ((lit >> 8*3) & 0xff) ^0x80;
4895 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4896 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4897 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4898 genSkipc(&rFalseIfx);
4901 if(ifx) ifx->generated = 1;
4909 if(lit & (0x80 << (size*8))) {
4910 /* lit is negative */
4911 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4913 //genSkipCond(&rFalseIfx,left,size,7);
4915 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4917 if(rFalseIfx.condition)
4918 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4920 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4924 /* lit is positive */
4925 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4926 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4927 if(rFalseIfx.condition)
4928 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4930 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4935 This works, but is only good for ints.
4936 It also requires a "known zero" register.
4937 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4938 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4939 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
4940 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4941 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4942 genSkipc(&rFalseIfx);
4944 pic16_emitpLabel(truelbl->key);
4945 if(ifx) ifx->generated = 1;
4949 /* There are no more special cases, so perform a general compare */
4951 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4952 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4956 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4958 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4960 //rFalseIfx.condition ^= 1;
4961 genSkipc(&rFalseIfx);
4963 pic16_emitpLabel(truelbl->key);
4965 if(ifx) ifx->generated = 1;
4972 /* sign is out of the way. So now do an unsigned compare */
4973 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4976 /* General case - compare to an unsigned literal on the right.*/
4978 i = (lit >> (size*8)) & 0xff;
4979 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4980 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4982 i = (lit >> (size*8)) & 0xff;
4985 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4987 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4989 /* this byte of the lit is zero,
4990 *if it's not the last then OR in the variable */
4992 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4997 pic16_emitpLabel(lbl->key);
4998 // pic16_emitpLabel(truelbl->key);
4999 //if(emitFinalCheck)
5000 genSkipc(&rFalseIfx);
5002 pic16_emitpLabel(truelbl->key);
5004 if(ifx) ifx->generated = 1;
5011 if(AOP_TYPE(left) == AOP_LIT) {
5012 //symbol *lbl = newiTempLabel(NULL);
5014 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5017 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5020 if((lit == 0) && (sign == 0)){
5023 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5025 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5027 genSkipz2(&rFalseIfx,0);
5028 if(ifx) ifx->generated = 1;
5035 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5036 /* degenerate compare can never be true */
5037 if(rFalseIfx.condition == 0)
5038 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5040 if(ifx) ifx->generated = 1;
5045 /* signed comparisons to a literal byte */
5047 int lp1 = (lit+1) & 0xff;
5049 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5052 rFalseIfx.condition ^= 1;
5053 genSkipCond(&rFalseIfx,right,0,7);
5056 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5057 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5058 genSkipz2(&rFalseIfx,1);
5061 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5062 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5063 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5064 rFalseIfx.condition ^= 1;
5065 genSkipc(&rFalseIfx);
5069 /* unsigned comparisons to a literal byte */
5071 switch(lit & 0xff ) {
5073 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5074 genSkipz2(&rFalseIfx,0);
5077 rFalseIfx.condition ^= 1;
5078 genSkipCond(&rFalseIfx,right,0,7);
5082 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5083 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5084 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5085 rFalseIfx.condition ^= 1;
5086 if (AOP_TYPE(result) == AOP_CRY)
5087 genSkipc(&rFalseIfx);
5089 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5090 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5096 if(ifx) ifx->generated = 1;
5097 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5103 /* Size is greater than 1 */
5111 /* this means lit = 0xffffffff, or -1 */
5114 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5115 rFalseIfx.condition ^= 1;
5116 genSkipCond(&rFalseIfx,right,size,7);
5117 if(ifx) ifx->generated = 1;
5119 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5128 if(rFalseIfx.condition) {
5129 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5130 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5133 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5135 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5139 if(rFalseIfx.condition) {
5140 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5141 pic16_emitpLabel(truelbl->key);
5143 rFalseIfx.condition ^= 1;
5144 genSkipCond(&rFalseIfx,right,s,7);
5147 if(ifx) ifx->generated = 1;
5149 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5155 if((size == 1) && (0 == (lp1&0xff))) {
5156 /* lower byte of signed word is zero */
5157 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5158 i = ((lp1 >> 8) & 0xff) ^0x80;
5159 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5160 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5161 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5162 rFalseIfx.condition ^= 1;
5163 genSkipc(&rFalseIfx);
5166 if(ifx) ifx->generated = 1;
5168 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5174 if(lit & (0x80 << (size*8))) {
5175 /* Lit is less than zero */
5176 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5177 //rFalseIfx.condition ^= 1;
5178 //genSkipCond(&rFalseIfx,left,size,7);
5179 //rFalseIfx.condition ^= 1;
5180 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5181 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5183 if(rFalseIfx.condition)
5184 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5186 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5190 /* Lit is greater than or equal to zero */
5191 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5192 //rFalseIfx.condition ^= 1;
5193 //genSkipCond(&rFalseIfx,right,size,7);
5194 //rFalseIfx.condition ^= 1;
5196 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5197 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5199 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5200 if(rFalseIfx.condition)
5201 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5203 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5207 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5208 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5212 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5214 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5216 rFalseIfx.condition ^= 1;
5217 //rFalseIfx.condition = 1;
5218 genSkipc(&rFalseIfx);
5220 pic16_emitpLabel(truelbl->key);
5222 if(ifx) ifx->generated = 1;
5225 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5232 /* compare word or long to an unsigned literal on the right.*/
5237 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5240 break; /* handled above */
5243 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5245 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5246 genSkipz2(&rFalseIfx,0);
5250 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5252 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5255 if(rFalseIfx.condition)
5256 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5258 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5261 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5262 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5264 rFalseIfx.condition ^= 1;
5265 genSkipc(&rFalseIfx);
5268 pic16_emitpLabel(truelbl->key);
5270 if(ifx) ifx->generated = 1;
5272 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5280 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5281 i = (lit >> (size*8)) & 0xff;
5283 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5284 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5287 i = (lit >> (size*8)) & 0xff;
5290 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5292 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5294 /* this byte of the lit is zero,
5295 * if it's not the last then OR in the variable */
5297 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5302 pic16_emitpLabel(lbl->key);
5304 rFalseIfx.condition ^= 1;
5306 genSkipc(&rFalseIfx);
5310 pic16_emitpLabel(truelbl->key);
5311 if(ifx) ifx->generated = 1;
5313 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5319 /* Compare two variables */
5321 DEBUGpic16_emitcode(";sign","%d",sign);
5325 /* Sigh. thus sucks... */
5329 pctemp = pic16_popGetTempReg(1);
5330 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5331 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5332 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5333 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5334 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5335 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5336 pic16_popReleaseTempReg(pctemp, 1);
5338 /* Signed char comparison */
5339 /* Special thanks to Nikolai Golovchenko for this snippet */
5340 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5341 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5342 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5343 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5344 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5345 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5347 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5348 genSkipc(&rFalseIfx);
5350 if(ifx) ifx->generated = 1;
5352 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5360 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5361 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5365 /* The rest of the bytes of a multi-byte compare */
5369 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5372 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5373 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5378 pic16_emitpLabel(lbl->key);
5380 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5381 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5382 (AOP_TYPE(result) == AOP_REG)) {
5383 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5384 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5386 genSkipc(&rFalseIfx);
5388 //genSkipc(&rFalseIfx);
5389 if(ifx) ifx->generated = 1;
5392 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5400 if ((AOP_TYPE(result) != AOP_CRY)
5401 && AOP_SIZE(result)) {
5402 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5404 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5406 pic16_outBitC(result);
5408 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5409 /* if the result is used in the next
5410 ifx conditional branch then generate
5411 code a little differently */
5413 genIfxJump (ifx,"c");
5415 pic16_outBitC(result);
5416 /* leave the result in acc */
5421 #else /* old version of genCmp() */ /* } else { */
5423 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5424 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5425 operand *result, int offset, int invert_op)
5429 /* check condition, > or < ?? */
5430 if(rIfx->condition != 0)invert_op ^= 1;
5432 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5434 if(!ifx)invert_op ^= 1;
5436 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5437 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5440 if(!invert_op)return POC_CPFSGT;
5441 else return POC_CPFSLT;
5444 static int compareAopfirstpass=1;
5446 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5447 operand *oper, int offset, operand *result,
5448 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5454 /* invert if there is a result to be loaded, in order to fit,
5455 * SETC/CLRC sequence */
5456 if(AOP_SIZE(result))invert_op ^= 1;
5458 // if(sign && !offset)invert_op ^= 1;
5460 // if(sign)invert_op ^= 1;
5462 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5464 if(AOP_SIZE(result) && compareAopfirstpass) {
5467 pic16_emitpcode(POC_SETF, pcop2);
5472 pic16_emitpcode(POC_CLRF, pcop2);
5478 compareAopfirstpass = 0;
5480 /* there is a bug when comparing operands with size > 1,
5481 * because higher bytes can be equal and test should be performed
5482 * to the next lower byte, current algorithm, considers operands
5483 * inequal in these cases! -- VR 20041107 */
5487 pic16_emitpcode(op, pcop);
5489 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5492 if((!sign || !offset) && AOP_SIZE(result)) {
5495 pic16_emitpcode(POC_CLRF, pcop2);
5500 pic16_emitpcode(POC_SETF, pcop2);
5505 /* don't emit final branch (offset == 0) */
5509 pic16_emitpcode(POC_RRCF, pcop2);
5511 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5514 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5515 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5516 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5518 truelbl = newiTempLabel( NULL );
5519 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5520 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5521 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5523 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5524 pic16_emitpLabel(truelbl->key);
5526 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5535 static void genCmp (operand *left, operand *right,
5536 operand *result, iCode *ifx, int sign)
5540 resolvedIfx rFalseIfx;
5541 symbol *falselbl, *tlbl;
5545 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5547 resolveIfx(&rFalseIfx, ifx);
5548 size = max(AOP_SIZE(left), AOP_SIZE(right));
5550 /* if left & right are bit variables */
5551 if(AOP_TYPE(left) == AOP_CRY
5552 && AOP_TYPE(right) == AOP_CRY ) {
5554 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5555 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5557 werror(W_POSSBUG2, __FILE__, __LINE__);
5561 /* if literal is on the right then swap with left */
5562 if((AOP_TYPE(right) == AOP_LIT)) {
5563 operand *tmp = right ;
5564 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
5566 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5568 // lit = (lit - 1) & mask;
5571 rFalseIfx.condition ^= 1; /* reverse compare */
5573 if ((AOP_TYPE(left) == AOP_LIT)) {
5574 /* float compares are handled by support functions */
5575 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
5578 /* actual comparing algorithm */
5579 // size = AOP_SIZE( right );
5581 falselbl = newiTempLabel( NULL );
5582 if(AOP_TYPE(left) == AOP_LIT) {
5583 /* compare to literal */
5584 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
5587 pCodeOp *pct, *pct2;
5590 /* signed compare */
5591 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
5593 pct = pic16_popCopyReg(&pic16_pc_prodl);
5594 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
5595 tlbl = newiTempLabel( NULL );
5597 /* first compare signs:
5598 * a. if both are positive, compare just like unsigned
5599 * b. if both are negative, invert cmpop, compare just like unsigned
5600 * c. if different signs, determine the result directly */
5606 tlbl1 = newiTempLabel( NULL );
5607 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
5611 /* literal is zero or positive:
5612 * a. if carry is zero, too, continue compare,
5613 * b. if carry is set, then continue depending on cmpop ^ condition:
5614 * 1. '<' return false (literal < variable),
5615 * 2. '>' return true (literal > variable) */
5616 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
5617 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5620 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5621 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
5625 /* literal is negative:
5626 * a. if carry is set, too, continue compare,
5627 * b. if carry is zero, then continue depending on cmpop ^ condition:
5628 * 1. '<' return true (literal < variable),
5629 * 2. '>' return false (literal > variable) */
5630 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
5631 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5633 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5634 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
5639 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5641 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5642 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
5647 pic16_emitpLabel( tlbl1->key );
5650 compareAopfirstpass=1;
5651 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5652 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
5653 // pic16_emitpcode(POC_MOVWF, pct);
5655 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
5656 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
5657 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5658 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
5662 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5663 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
5664 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
5665 // pic16_emitpcode(POC_MOVWF, pct);
5667 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
5668 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
5669 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
5670 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5671 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
5675 if(ifx)ifx->generated = 1;
5677 if(AOP_SIZE(result)) {
5678 pic16_emitpLabel(tlbl->key);
5679 pic16_emitpLabel(falselbl->key);
5680 pic16_outBitOp( result, pct2 );
5682 pic16_emitpLabel(tlbl->key);
5687 /* unsigned compare */
5688 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
5690 compareAopfirstpass=1;
5693 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
5694 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
5698 if(ifx)ifx->generated = 1;
5701 if(AOP_SIZE(result)) {
5702 pic16_emitpLabel(falselbl->key);
5703 pic16_outBitC( result );
5708 /* compare registers */
5709 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
5713 pCodeOp *pct, *pct2;
5715 /* signed compare */
5716 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
5718 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
5719 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
5720 tlbl = newiTempLabel( NULL );
5722 compareAopfirstpass=1;
5725 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
5726 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5727 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
5728 pic16_emitpcode(POC_MOVWF, pct);
5730 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
5731 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5732 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
5734 /* WREG already holds left + 0x80 */
5735 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5738 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
5739 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5740 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
5741 pic16_emitpcode(POC_MOVWF, pct);
5743 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
5744 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5745 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
5747 /* WREG already holds left + 0x80 */
5748 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5749 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
5752 if(ifx)ifx->generated = 1;
5754 if(AOP_SIZE(result)) {
5755 pic16_emitpLabel(tlbl->key);
5756 pic16_emitpLabel(falselbl->key);
5757 pic16_outBitOp( result, pct2 );
5759 pic16_emitpLabel(tlbl->key);
5763 /* unsigned compare */
5764 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
5766 compareAopfirstpass=1;
5769 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
5770 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
5774 if(ifx)ifx->generated = 1;
5775 if(AOP_SIZE(result)) {
5777 pic16_emitpLabel(falselbl->key);
5778 pic16_outBitC( result );
5785 #else /* } else { */
5787 /* new version of genCmp -- VR 20041012 */
5788 static void genCmp (operand *left,operand *right,
5789 operand *result, iCode *ifx, int sign)
5791 int size; //, offset = 0 ;
5792 unsigned long lit = 0L,i = 0;
5793 resolvedIfx rFalseIfx;
5794 int willCheckCarry=0;
5795 // resolvedIfx rTrueIfx;
5801 * subtract right from left if at the end the carry flag is set then we
5802 * know that left is greater than right */
5804 resolveIfx(&rFalseIfx,ifx);
5805 truelbl = newiTempLabel(NULL);
5806 size = max(AOP_SIZE(left),AOP_SIZE(right));
5808 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5810 /* POC_CPFSGT compare f, wreg, skip if f greater than wreg
5811 * POC_CPFSLT compare f, wreg, skip if f less then wreg */
5814 /* if literal is on the right then swap with left */
5815 if ((AOP_TYPE(right) == AOP_LIT)) {
5816 operand *tmp = right ;
5817 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5819 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5821 // lit = (lit - 1) & mask;
5824 rFalseIfx.condition ^= 1; /* reverse compare */
5826 if ((AOP_TYPE(left) == AOP_LIT)) {
5827 /* float compares are handled by support functions */
5828 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5832 //if(IC_TRUE(ifx) == NULL)
5833 /* if left & right are bit variables */
5834 if (AOP_TYPE(left) == AOP_CRY &&
5835 AOP_TYPE(right) == AOP_CRY ) {
5837 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5838 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5841 symbol *lbl = newiTempLabel(NULL);
5843 if(AOP_TYPE(left) == AOP_LIT) {
5844 DEBUGpic16_emitcode(";left lit","lit = 0x%x, sign=%d",lit,sign);
5846 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5848 else willCheckCarry = 0;
5851 if((lit == 0) && (sign == 0)) {
5852 /* unsigned compare to 0 */
5853 DEBUGpic16_emitcode("; unsigned compare to 0","lit = 0x%x, sign=%d",lit,sign);
5856 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5858 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5860 genSkipz2(&rFalseIfx,0);
5861 if(ifx)ifx->generated = 1;
5868 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5869 /* degenerate compare can never be true */
5870 if(rFalseIfx.condition == 0)
5871 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5873 if(ifx) ifx->generated = 1;
5878 /* signed comparisons to a literal byte */
5879 DEBUGpic16_emitcode(";signed compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
5881 int lp1 = (lit+1) & 0xff;
5883 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x condition = %d lp1 = %i",__LINE__,lit, rFalseIfx.condition, lp1);
5886 rFalseIfx.condition ^= 1;
5887 genSkipCond(&rFalseIfx,right,0,7);
5890 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5891 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5892 genSkipz2(&rFalseIfx,1);
5895 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit ));
5897 if(rFalseIfx.condition)
5898 pic16_emitpcode(POC_CPFSLT, pic16_popGet(AOP(right), 0));
5900 pic16_emitpcode(POC_CPFSGT, pic16_popGet(AOP(right), 0));
5902 if(willCheckCarry) {
5903 if(!rFalseIfx.condition) { emitCLRC; emitSETC; }
5904 else { emitSETC; emitCLRC; }
5907 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5910 /* pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5911 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5912 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5913 rFalseIfx.condition ^= 1;
5914 genSkipc(&rFalseIfx);
5919 /* unsigned comparisons to a literal byte */
5920 DEBUGpic16_emitcode("; unsigned compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
5922 switch(lit & 0xff ) {
5925 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5926 genSkipz2(&rFalseIfx,0);
5929 rFalseIfx.condition ^= 1;
5930 genSkipCond(&rFalseIfx,right,0,7);
5933 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5934 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5935 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5936 rFalseIfx.condition ^= 1;
5937 if (AOP_TYPE(result) == AOP_CRY)
5938 genSkipc(&rFalseIfx);
5940 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5941 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5947 if(ifx) ifx->generated = 1;
5948 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5954 /* Size is greater than 1 */
5962 /* this means lit = 0xffffffff, or -1 */
5965 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5966 rFalseIfx.condition ^= 1;
5967 genSkipCond(&rFalseIfx,right,size,7);
5968 if(ifx) ifx->generated = 1;
5975 if(rFalseIfx.condition) {
5976 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5977 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5980 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5982 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5986 if(rFalseIfx.condition) {
5987 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5988 pic16_emitpLabel(truelbl->key);
5990 rFalseIfx.condition ^= 1;
5991 genSkipCond(&rFalseIfx,right,s,7);
5994 if(ifx) ifx->generated = 1;
5998 if((size == 1) && (0 == (lp1&0xff))) {
5999 /* lower byte of signed word is zero */
6000 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
6001 i = ((lp1 >> 8) & 0xff) ^0x80;
6002 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6003 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
6004 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
6005 rFalseIfx.condition ^= 1;
6006 genSkipc(&rFalseIfx);
6009 if(ifx) ifx->generated = 1;
6013 if(lit & (0x80 << (size*8))) {
6014 /* Lit is less than zero */
6015 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
6016 //rFalseIfx.condition ^= 1;
6017 //genSkipCond(&rFalseIfx,left,size,7);
6018 //rFalseIfx.condition ^= 1;
6019 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6020 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6022 if(rFalseIfx.condition)
6023 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6025 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6029 /* Lit is greater than or equal to zero */
6030 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
6031 //rFalseIfx.condition ^= 1;
6032 //genSkipCond(&rFalseIfx,right,size,7);
6033 //rFalseIfx.condition ^= 1;
6035 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
6036 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6038 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6039 if(rFalseIfx.condition)
6040 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6042 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6047 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6048 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6052 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6054 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6056 rFalseIfx.condition ^= 1;
6057 //rFalseIfx.condition = 1;
6058 genSkipc(&rFalseIfx);
6060 pic16_emitpLabel(truelbl->key);
6062 if(ifx) ifx->generated = 1;
6067 /* compare word or long to an unsigned literal on the right.*/
6072 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
6075 break; /* handled above */
6078 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6080 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6081 genSkipz2(&rFalseIfx,0);
6085 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6087 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6090 if(rFalseIfx.condition)
6091 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6093 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6096 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6097 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6099 rFalseIfx.condition ^= 1;
6100 genSkipc(&rFalseIfx);
6103 pic16_emitpLabel(truelbl->key);
6105 if(ifx) ifx->generated = 1;
6111 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6112 i = (lit >> (size*8)) & 0xff;
6114 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6115 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6118 i = (lit >> (size*8)) & 0xff;
6121 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6123 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6125 /* this byte of the lit is zero,
6126 * if it's not the last then OR in the variable */
6128 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6133 pic16_emitpLabel(lbl->key);
6135 rFalseIfx.condition ^= 1;
6137 genSkipc(&rFalseIfx);
6141 pic16_emitpLabel(truelbl->key);
6142 if(ifx) ifx->generated = 1;
6146 /* Compare two variables */
6148 DEBUGpic16_emitcode(";sign","%d",sign);
6152 /* Sigh. thus sucks... */
6156 pctemp = pic16_popGetTempReg(1);
6157 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6158 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
6159 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6160 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6161 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6162 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6163 pic16_popReleaseTempReg(pctemp, 1);
6165 /* Signed char comparison */
6166 /* Special thanks to Nikolai Golovchenko for this snippet */
6167 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6168 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6169 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
6170 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6171 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6172 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6174 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6175 genSkipc(&rFalseIfx);
6177 if(ifx) ifx->generated = 1;
6183 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6184 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6188 /* The rest of the bytes of a multi-byte compare */
6192 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
6195 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6196 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6201 pic16_emitpLabel(lbl->key);
6203 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6204 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
6205 (AOP_TYPE(result) == AOP_REG)) {
6206 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6207 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6209 genSkipc(&rFalseIfx);
6211 //genSkipc(&rFalseIfx);
6212 if(ifx) ifx->generated = 1;
6219 if ((AOP_TYPE(result) != AOP_CRY)
6220 && AOP_SIZE(result)) {
6221 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6223 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6225 pic16_outBitC(result);
6227 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6228 /* if the result is used in the next
6229 ifx conditional branch then generate
6230 code a little differently */
6232 genIfxJump (ifx,"c");
6234 pic16_outBitC(result);
6235 /* leave the result in acc */
6246 /*-----------------------------------------------------------------*/
6247 /* genCmpGt :- greater than comparison */
6248 /*-----------------------------------------------------------------*/
6249 static void genCmpGt (iCode *ic, iCode *ifx)
6251 operand *left, *right, *result;
6252 sym_link *letype , *retype;
6258 right= IC_RIGHT(ic);
6259 result = IC_RESULT(ic);
6261 letype = getSpec(operandType(left));
6262 retype =getSpec(operandType(right));
6263 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6264 /* assign the amsops */
6265 pic16_aopOp (left,ic,FALSE);
6266 pic16_aopOp (right,ic,FALSE);
6267 pic16_aopOp (result,ic,TRUE);
6269 genCmp(right, left, result, ifx, sign);
6271 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6272 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6273 pic16_freeAsmop(result,NULL,ic,TRUE);
6276 /*-----------------------------------------------------------------*/
6277 /* genCmpLt - less than comparisons */
6278 /*-----------------------------------------------------------------*/
6279 static void genCmpLt (iCode *ic, iCode *ifx)
6281 operand *left, *right, *result;
6282 sym_link *letype , *retype;
6288 right= IC_RIGHT(ic);
6289 result = IC_RESULT(ic);
6291 letype = getSpec(operandType(left));
6292 retype =getSpec(operandType(right));
6293 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6295 /* assign the amsops */
6296 pic16_aopOp (left,ic,FALSE);
6297 pic16_aopOp (right,ic,FALSE);
6298 pic16_aopOp (result,ic,TRUE);
6300 genCmp(left, right, result, ifx, sign);
6302 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6303 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6304 pic16_freeAsmop(result,NULL,ic,TRUE);
6309 // FIXME reenable literal optimisation when the pic16 port is stable
6311 /*-----------------------------------------------------------------*/
6312 /* genc16bit2lit - compare a 16 bit value to a literal */
6313 /*-----------------------------------------------------------------*/
6314 static void genc16bit2lit(operand *op, int lit, int offset)
6318 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6319 if( (lit&0xff) == 0)
6324 switch( BYTEofLONG(lit,i)) {
6326 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6329 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6332 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6335 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6336 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6341 switch( BYTEofLONG(lit,i)) {
6343 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6347 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6351 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6354 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6356 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6365 /*-----------------------------------------------------------------*/
6366 /* gencjneshort - compare and jump if not equal */
6367 /*-----------------------------------------------------------------*/
6368 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6370 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6372 int res_offset = 0; /* the result may be a different size then left or right */
6373 int res_size = AOP_SIZE(result);
6375 symbol *lbl, *lbl_done;
6377 unsigned long lit = 0L;
6378 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6380 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6381 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6383 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6384 resolveIfx(&rIfx,ifx);
6385 lbl = newiTempLabel(NULL);
6386 lbl_done = newiTempLabel(NULL);
6389 /* if the left side is a literal or
6390 if the right is in a pointer register and left
6392 if ((AOP_TYPE(left) == AOP_LIT) ||
6393 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6398 if(AOP_TYPE(right) == AOP_LIT)
6399 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6401 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6402 preserve_result = 1;
6404 if(result && !preserve_result)
6407 for(i = 0; i < AOP_SIZE(result); i++)
6408 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6412 /* if the right side is a literal then anything goes */
6413 if (AOP_TYPE(right) == AOP_LIT &&
6414 AOP_TYPE(left) != AOP_DIR ) {
6417 genc16bit2lit(left, lit, 0);
6419 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6422 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6425 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6426 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6428 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6432 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6434 if(res_offset < res_size-1)
6442 /* if the right side is in a register or in direct space or
6443 if the left is a pointer register & right is not */
6444 else if (AOP_TYPE(right) == AOP_REG ||
6445 AOP_TYPE(right) == AOP_DIR ||
6446 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6447 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6448 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6449 int lbl_key = lbl->key;
6452 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6453 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6455 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6456 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6457 __FUNCTION__,__LINE__);
6461 /* switch(size) { */
6463 /* genc16bit2lit(left, lit, 0); */
6465 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6470 if((AOP_TYPE(left) == AOP_DIR) &&
6471 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6473 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6474 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6476 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6478 switch (lit & 0xff) {
6480 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6483 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6484 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6485 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6489 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6490 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6491 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6492 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6496 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6497 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6502 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6505 if(AOP_TYPE(result) == AOP_CRY) {
6506 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6511 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6513 /* fix me. probably need to check result size too */
6514 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6519 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6520 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6527 if(res_offset < res_size-1)
6532 } else if(AOP_TYPE(right) == AOP_REG &&
6533 AOP_TYPE(left) != AOP_DIR){
6536 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6537 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6538 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6543 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6545 if(res_offset < res_size-1)
6550 /* right is a pointer reg need both a & b */
6552 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6554 pic16_emitcode("mov","b,%s",l);
6555 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6556 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6561 if(result && preserve_result)
6564 for(i = 0; i < AOP_SIZE(result); i++)
6565 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6568 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6570 if(result && preserve_result)
6571 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6574 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6576 pic16_emitpLabel(lbl->key);
6578 if(result && preserve_result)
6581 for(i = 0; i < AOP_SIZE(result); i++)
6582 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6584 pic16_emitpLabel(lbl_done->key);
6587 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6595 /*-----------------------------------------------------------------*/
6596 /* gencjne - compare and jump if not equal */
6597 /*-----------------------------------------------------------------*/
6598 static void gencjne(operand *left, operand *right, iCode *ifx)
6600 symbol *tlbl = newiTempLabel(NULL);
6602 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6603 gencjneshort(left, right, lbl);
6605 pic16_emitcode("mov","a,%s",one);
6606 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6607 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6608 pic16_emitcode("clr","a");
6609 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6611 pic16_emitpLabel(lbl->key);
6612 pic16_emitpLabel(tlbl->key);
6618 /*-----------------------------------------------------------------*/
6619 /* is_LitOp - check if operand has to be treated as literal */
6620 /*-----------------------------------------------------------------*/
6621 static bool is_LitOp(operand *op)
6623 return ((AOP_TYPE(op) == AOP_LIT)
6624 || ( (AOP_TYPE(op) == AOP_PCODE)
6625 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6626 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6629 /*-----------------------------------------------------------------*/
6630 /* is_LitAOp - check if operand has to be treated as literal */
6631 /*-----------------------------------------------------------------*/
6632 static bool is_LitAOp(asmop *aop)
6634 return ((aop->type == AOP_LIT)
6635 || ( (aop->type == AOP_PCODE)
6636 && ( (aop->aopu.pcop->type == PO_LITERAL)
6637 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6642 /*-----------------------------------------------------------------*/
6643 /* genCmpEq - generates code for equal to */
6644 /*-----------------------------------------------------------------*/
6645 static void genCmpEq (iCode *ic, iCode *ifx)
6647 operand *left, *right, *result;
6648 symbol *falselbl = newiTempLabel(NULL);
6649 symbol *donelbl = newiTempLabel(NULL);
6651 int preserve_result = 0;
6652 int generate_result = 0;
6657 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6658 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6659 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6661 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6663 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6665 werror(W_POSSBUG2, __FILE__, __LINE__);
6666 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6667 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6671 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6673 operand *tmp = right ;
6678 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6679 preserve_result = 1;
6681 if(result && AOP_SIZE(result))
6682 generate_result = 1;
6684 if(generate_result && !preserve_result)
6686 for(i = 0; i < AOP_SIZE(result); i++)
6687 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6690 for(i=0; i < AOP_SIZE(left); i++)
6692 if(AOP_TYPE(left) != AOP_ACC)
6695 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6697 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6700 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6702 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
6704 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6709 if(generate_result && preserve_result)
6711 for(i = 0; i < AOP_SIZE(result); i++)
6712 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6716 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6718 if(generate_result && preserve_result)
6719 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6721 if(ifx && IC_TRUE(ifx))
6722 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6724 if(ifx && IC_FALSE(ifx))
6725 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6727 pic16_emitpLabel(falselbl->key);
6731 if(ifx && IC_FALSE(ifx))
6732 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6734 if(generate_result && preserve_result)
6736 for(i = 0; i < AOP_SIZE(result); i++)
6737 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6740 pic16_emitpLabel(donelbl->key);
6746 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6747 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6748 pic16_freeAsmop(result,NULL,ic,TRUE);
6754 // old version kept for reference
6756 /*-----------------------------------------------------------------*/
6757 /* genCmpEq - generates code for equal to */
6758 /*-----------------------------------------------------------------*/
6759 static void genCmpEq (iCode *ic, iCode *ifx)
6761 operand *left, *right, *result;
6762 unsigned long lit = 0L;
6764 symbol *falselbl = newiTempLabel(NULL);
6767 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6770 DEBUGpic16_emitcode ("; ifx is non-null","");
6772 DEBUGpic16_emitcode ("; ifx is null","");
6774 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6775 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6776 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6778 size = max(AOP_SIZE(left),AOP_SIZE(right));
6780 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6782 /* if literal, literal on the right or
6783 if the right is in a pointer register and left
6785 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
6786 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6787 operand *tmp = right ;
6793 if(ifx && !AOP_SIZE(result)){
6795 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
6796 /* if they are both bit variables */
6797 if (AOP_TYPE(left) == AOP_CRY &&
6798 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6799 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
6800 if(AOP_TYPE(right) == AOP_LIT){
6801 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6803 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6804 pic16_emitcode("cpl","c");
6805 } else if(lit == 1L) {
6806 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6808 pic16_emitcode("clr","c");
6810 /* AOP_TYPE(right) == AOP_CRY */
6812 symbol *lbl = newiTempLabel(NULL);
6813 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6814 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6815 pic16_emitcode("cpl","c");
6816 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6818 /* if true label then we jump if condition
6820 tlbl = newiTempLabel(NULL);
6821 if ( IC_TRUE(ifx) ) {
6822 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6823 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6825 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6826 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6828 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6831 /* left and right are both bit variables, result is carry */
6834 resolveIfx(&rIfx,ifx);
6836 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6837 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6838 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6839 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6844 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
6846 /* They're not both bit variables. Is the right a literal? */
6847 if(AOP_TYPE(right) == AOP_LIT) {
6848 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6853 switch(lit & 0xff) {
6855 if ( IC_TRUE(ifx) ) {
6856 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6858 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6860 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6861 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6865 if ( IC_TRUE(ifx) ) {
6866 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6868 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6870 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6871 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6875 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6877 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6882 /* end of size == 1 */
6886 genc16bit2lit(left,lit,offset);
6889 /* end of size == 2 */
6894 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6895 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6896 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6897 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6900 /* search for patterns that can be optimized */
6902 genc16bit2lit(left,lit,0);
6906 emitSKPZ; // if hi word unequal
6908 emitSKPNZ; // if hi word equal
6910 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6911 genc16bit2lit(left,lit,2);
6914 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6915 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6919 pic16_emitpLabel(falselbl->key);
6928 } else if(AOP_TYPE(right) == AOP_CRY ) {
6929 /* we know the left is not a bit, but that the right is */
6930 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6931 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6932 pic16_popGet(AOP(right),offset));
6933 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6935 /* if the two are equal, then W will be 0 and the Z bit is set
6936 * we could test Z now, or go ahead and check the high order bytes if
6937 * the variable we're comparing is larger than a byte. */
6940 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6942 if ( IC_TRUE(ifx) ) {
6944 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6945 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6948 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6949 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6953 /* They're both variables that are larger than bits */
6956 tlbl = newiTempLabel(NULL);
6959 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6960 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6962 if ( IC_TRUE(ifx) ) {
6966 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6968 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6969 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6973 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6976 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6977 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6982 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
6984 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6985 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6989 if(s>1 && IC_TRUE(ifx)) {
6990 pic16_emitpLabel(tlbl->key);
6991 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6995 /* mark the icode as generated */
7000 /* if they are both bit variables */
7001 if (AOP_TYPE(left) == AOP_CRY &&
7002 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7003 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7004 if(AOP_TYPE(right) == AOP_LIT){
7005 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7007 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7008 pic16_emitcode("cpl","c");
7009 } else if(lit == 1L) {
7010 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7012 pic16_emitcode("clr","c");
7014 /* AOP_TYPE(right) == AOP_CRY */
7016 symbol *lbl = newiTempLabel(NULL);
7017 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7018 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7019 pic16_emitcode("cpl","c");
7020 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7023 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7024 pic16_outBitC(result);
7028 genIfxJump (ifx,"c");
7031 /* if the result is used in an arithmetic operation
7032 then put the result in place */
7033 pic16_outBitC(result);
7036 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7037 gencjne(left,right,result,ifx);
7040 gencjne(left,right,newiTempLabel(NULL));
7042 if(IC_TRUE(ifx)->key)
7043 gencjne(left,right,IC_TRUE(ifx)->key);
7045 gencjne(left,right,IC_FALSE(ifx)->key);
7049 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7050 pic16_aopPut(AOP(result),"a",0);
7055 genIfxJump (ifx,"a");
7059 /* if the result is used in an arithmetic operation
7060 then put the result in place */
7062 if (AOP_TYPE(result) != AOP_CRY)
7063 pic16_outAcc(result);
7065 /* leave the result in acc */
7069 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7070 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7071 pic16_freeAsmop(result,NULL,ic,TRUE);
7075 /*-----------------------------------------------------------------*/
7076 /* ifxForOp - returns the icode containing the ifx for operand */
7077 /*-----------------------------------------------------------------*/
7078 static iCode *ifxForOp ( operand *op, iCode *ic )
7082 /* if true symbol then needs to be assigned */
7083 if (IS_TRUE_SYMOP(op))
7086 /* if this has register type condition and
7087 the next instruction is ifx with the same operand
7088 and live to of the operand is upto the ifx only then */
7090 && ic->next->op == IFX
7091 && IC_COND(ic->next)->key == op->key
7092 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7094 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7099 ic->next->op == IFX &&
7100 IC_COND(ic->next)->key == op->key) {
7101 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7105 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7107 ic->next->op == IFX)
7108 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7111 ic->next->op == IFX &&
7112 IC_COND(ic->next)->key == op->key) {
7113 DEBUGpic16_emitcode ("; "," key is okay");
7114 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7115 OP_SYMBOL(op)->liveTo,
7120 /* the code below is completely untested
7121 * it just allows ulong2fs.c compile -- VR */
7124 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7125 __FILE__, __FUNCTION__, __LINE__);
7127 /* if this has register type condition and
7128 the next instruction is ifx with the same operand
7129 and live to of the operand is upto the ifx only then */
7131 ic->next->op == IFX &&
7132 IC_COND(ic->next)->key == op->key &&
7133 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7137 ic->next->op == IFX &&
7138 IC_COND(ic->next)->key == op->key) {
7139 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7143 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7144 __FILE__, __FUNCTION__, __LINE__);
7146 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7151 /*-----------------------------------------------------------------*/
7152 /* genAndOp - for && operation */
7153 /*-----------------------------------------------------------------*/
7154 static void genAndOp (iCode *ic)
7156 operand *left,*right, *result;
7161 /* note here that && operations that are in an
7162 if statement are taken away by backPatchLabels
7163 only those used in arthmetic operations remain */
7164 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7165 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7166 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7168 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7170 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7171 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7172 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7174 /* if both are bit variables */
7175 /* if (AOP_TYPE(left) == AOP_CRY && */
7176 /* AOP_TYPE(right) == AOP_CRY ) { */
7177 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7178 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7179 /* pic16_outBitC(result); */
7181 /* tlbl = newiTempLabel(NULL); */
7182 /* pic16_toBoolean(left); */
7183 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7184 /* pic16_toBoolean(right); */
7185 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7186 /* pic16_outBitAcc(result); */
7189 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7190 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7191 pic16_freeAsmop(result,NULL,ic,TRUE);
7195 /*-----------------------------------------------------------------*/
7196 /* genOrOp - for || operation */
7197 /*-----------------------------------------------------------------*/
7200 modified this code, but it doesn't appear to ever get called
7203 static void genOrOp (iCode *ic)
7205 operand *left,*right, *result;
7210 /* note here that || operations that are in an
7211 if statement are taken away by backPatchLabels
7212 only those used in arthmetic operations remain */
7213 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7214 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7215 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7217 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7219 /* if both are bit variables */
7220 if (AOP_TYPE(left) == AOP_CRY &&
7221 AOP_TYPE(right) == AOP_CRY ) {
7222 pic16_emitcode("clrc","");
7223 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7224 AOP(left)->aopu.aop_dir,
7225 AOP(left)->aopu.aop_dir);
7226 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7227 AOP(right)->aopu.aop_dir,
7228 AOP(right)->aopu.aop_dir);
7229 pic16_emitcode("setc","");
7232 tlbl = newiTempLabel(NULL);
7233 pic16_toBoolean(left);
7235 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7236 pic16_toBoolean(right);
7237 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7239 pic16_outBitAcc(result);
7242 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7243 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7244 pic16_freeAsmop(result,NULL,ic,TRUE);
7247 /*-----------------------------------------------------------------*/
7248 /* isLiteralBit - test if lit == 2^n */
7249 /*-----------------------------------------------------------------*/
7250 static int isLiteralBit(unsigned long lit)
7252 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7253 0x100L,0x200L,0x400L,0x800L,
7254 0x1000L,0x2000L,0x4000L,0x8000L,
7255 0x10000L,0x20000L,0x40000L,0x80000L,
7256 0x100000L,0x200000L,0x400000L,0x800000L,
7257 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7258 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7261 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7262 for(idx = 0; idx < 32; idx++)
7268 /*-----------------------------------------------------------------*/
7269 /* continueIfTrue - */
7270 /*-----------------------------------------------------------------*/
7271 static void continueIfTrue (iCode *ic)
7275 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7279 /*-----------------------------------------------------------------*/
7281 /*-----------------------------------------------------------------*/
7282 static void jumpIfTrue (iCode *ic)
7286 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7290 /*-----------------------------------------------------------------*/
7291 /* jmpTrueOrFalse - */
7292 /*-----------------------------------------------------------------*/
7293 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7295 // ugly but optimized by peephole
7298 symbol *nlbl = newiTempLabel(NULL);
7299 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7300 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7301 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7302 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7304 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7305 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7310 /*-----------------------------------------------------------------*/
7311 /* genAnd - code for and */
7312 /*-----------------------------------------------------------------*/
7313 static void genAnd (iCode *ic, iCode *ifx)
7315 operand *left, *right, *result;
7317 unsigned long lit = 0L;
7323 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7324 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7325 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7327 resolveIfx(&rIfx,ifx);
7329 /* if left is a literal & right is not then exchange them */
7330 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7331 AOP_NEEDSACC(left)) {
7332 operand *tmp = right ;
7337 /* if result = right then exchange them */
7338 if(pic16_sameRegs(AOP(result),AOP(right))){
7339 operand *tmp = right ;
7344 /* if right is bit then exchange them */
7345 if (AOP_TYPE(right) == AOP_CRY &&
7346 AOP_TYPE(left) != AOP_CRY){
7347 operand *tmp = right ;
7351 if(AOP_TYPE(right) == AOP_LIT)
7352 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7354 size = AOP_SIZE(result);
7356 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7359 // result = bit & yy;
7360 if (AOP_TYPE(left) == AOP_CRY){
7361 // c = bit & literal;
7362 if(AOP_TYPE(right) == AOP_LIT){
7364 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7367 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7370 if(size && (AOP_TYPE(result) == AOP_CRY)){
7371 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7374 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7378 pic16_emitcode("clr","c");
7381 if (AOP_TYPE(right) == AOP_CRY){
7383 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7384 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7387 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7389 pic16_emitcode("rrc","a");
7390 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7396 pic16_outBitC(result);
7398 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7399 genIfxJump(ifx, "c");
7403 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7404 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7405 if((AOP_TYPE(right) == AOP_LIT) &&
7406 (AOP_TYPE(result) == AOP_CRY) &&
7407 (AOP_TYPE(left) != AOP_CRY)){
7408 int posbit = isLiteralBit(lit);
7412 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7415 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7421 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7422 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7424 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7425 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7428 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7429 size = AOP_SIZE(left);
7432 int bp = posbit, ofs=0;
7439 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7440 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7444 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7445 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7447 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7454 symbol *tlbl = newiTempLabel(NULL);
7455 int sizel = AOP_SIZE(left);
7461 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7463 /* patch provided by Aaron Colwell */
7464 if((posbit = isLiteralBit(bytelit)) != 0) {
7465 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7466 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7467 (posbit-1),0, PO_GPR_REGISTER));
7469 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7470 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7472 if (bytelit == 0xff) {
7473 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7474 * a peephole could optimize it out -- VR */
7475 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7477 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7478 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7481 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7482 pic16_popGetLabel(tlbl->key));
7486 /* old code, left here for reference -- VR 09/2004 */
7487 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7489 if((posbit = isLiteralBit(bytelit)) != 0)
7490 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7492 if(bytelit != 0x0FFL)
7493 pic16_emitcode("anl","a,%s",
7494 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7495 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7501 // bit = left & literal
7504 pic16_emitpLabel(tlbl->key);
7506 // if(left & literal)
7509 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7510 pic16_emitpLabel(tlbl->key);
7517 pic16_outBitC(result);
7521 /* if left is same as result */
7522 if(pic16_sameRegs(AOP(result),AOP(left))){
7524 for(;size--; offset++,lit>>=8) {
7525 if(AOP_TYPE(right) == AOP_LIT){
7526 switch(lit & 0xff) {
7528 /* and'ing with 0 has clears the result */
7529 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7530 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7533 /* and'ing with 0xff is a nop when the result and left are the same */
7538 int p = pic16_my_powof2( (~lit) & 0xff );
7540 /* only one bit is set in the literal, so use a bcf instruction */
7541 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7542 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7545 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7546 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7547 if(know_W != (lit&0xff))
7548 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7550 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7555 if (AOP_TYPE(left) == AOP_ACC) {
7556 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7558 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7559 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7566 // left & result in different registers
7567 if(AOP_TYPE(result) == AOP_CRY){
7569 // if(size), result in bit
7570 // if(!size && ifx), conditional oper: if(left & right)
7571 symbol *tlbl = newiTempLabel(NULL);
7572 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7574 pic16_emitcode("setb","c");
7576 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7577 pic16_emitcode("anl","a,%s",
7578 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7579 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7584 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7585 pic16_outBitC(result);
7587 jmpTrueOrFalse(ifx, tlbl);
7589 for(;(size--);offset++) {
7591 // result = left & right
7592 if(AOP_TYPE(right) == AOP_LIT){
7593 int t = (lit >> (offset*8)) & 0x0FFL;
7596 pic16_emitcode("clrf","%s",
7597 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7598 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7601 pic16_emitcode("movf","%s,w",
7602 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7603 pic16_emitcode("movwf","%s",
7604 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7605 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7606 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7609 pic16_emitcode("movlw","0x%x",t);
7610 pic16_emitcode("andwf","%s,w",
7611 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7612 pic16_emitcode("movwf","%s",
7613 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7615 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7616 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7617 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7622 if (AOP_TYPE(left) == AOP_ACC) {
7623 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7624 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7626 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7627 pic16_emitcode("andwf","%s,w",
7628 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7629 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7630 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7632 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7633 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7639 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7640 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7641 pic16_freeAsmop(result,NULL,ic,TRUE);
7644 /*-----------------------------------------------------------------*/
7645 /* genOr - code for or */
7646 /*-----------------------------------------------------------------*/
7647 static void genOr (iCode *ic, iCode *ifx)
7649 operand *left, *right, *result;
7651 unsigned long lit = 0L;
7653 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7655 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7656 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7657 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7659 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7661 /* if left is a literal & right is not then exchange them */
7662 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7663 AOP_NEEDSACC(left)) {
7664 operand *tmp = right ;
7669 /* if result = right then exchange them */
7670 if(pic16_sameRegs(AOP(result),AOP(right))){
7671 operand *tmp = right ;
7676 /* if right is bit then exchange them */
7677 if (AOP_TYPE(right) == AOP_CRY &&
7678 AOP_TYPE(left) != AOP_CRY){
7679 operand *tmp = right ;
7684 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7686 if(AOP_TYPE(right) == AOP_LIT)
7687 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7689 size = AOP_SIZE(result);
7693 if (AOP_TYPE(left) == AOP_CRY){
7694 if(AOP_TYPE(right) == AOP_LIT){
7695 // c = bit & literal;
7697 // lit != 0 => result = 1
7698 if(AOP_TYPE(result) == AOP_CRY){
7700 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7701 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7702 // AOP(result)->aopu.aop_dir,
7703 // AOP(result)->aopu.aop_dir);
7705 continueIfTrue(ifx);
7709 // lit == 0 => result = left
7710 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7712 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7715 if (AOP_TYPE(right) == AOP_CRY){
7716 if(pic16_sameRegs(AOP(result),AOP(left))){
7718 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7719 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7720 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7722 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7723 AOP(result)->aopu.aop_dir,
7724 AOP(result)->aopu.aop_dir);
7725 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7726 AOP(right)->aopu.aop_dir,
7727 AOP(right)->aopu.aop_dir);
7728 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7729 AOP(result)->aopu.aop_dir,
7730 AOP(result)->aopu.aop_dir);
7732 if( AOP_TYPE(result) == AOP_ACC) {
7733 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7734 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7735 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7736 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7740 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7741 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7742 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7743 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7745 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7746 AOP(result)->aopu.aop_dir,
7747 AOP(result)->aopu.aop_dir);
7748 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7749 AOP(right)->aopu.aop_dir,
7750 AOP(right)->aopu.aop_dir);
7751 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7752 AOP(left)->aopu.aop_dir,
7753 AOP(left)->aopu.aop_dir);
7754 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7755 AOP(result)->aopu.aop_dir,
7756 AOP(result)->aopu.aop_dir);
7761 symbol *tlbl = newiTempLabel(NULL);
7762 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7765 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7766 if( AOP_TYPE(right) == AOP_ACC) {
7767 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7769 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7770 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7775 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7776 pic16_emitcode(";XXX setb","c");
7777 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7778 AOP(left)->aopu.aop_dir,tlbl->key+100);
7779 pic16_toBoolean(right);
7780 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7781 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7782 jmpTrueOrFalse(ifx, tlbl);
7786 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7793 pic16_outBitC(result);
7795 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7796 genIfxJump(ifx, "c");
7800 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7801 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7802 if((AOP_TYPE(right) == AOP_LIT) &&
7803 (AOP_TYPE(result) == AOP_CRY) &&
7804 (AOP_TYPE(left) != AOP_CRY)){
7806 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7809 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7811 continueIfTrue(ifx);
7814 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7815 // lit = 0, result = boolean(left)
7817 pic16_emitcode(";XXX setb","c");
7818 pic16_toBoolean(right);
7820 symbol *tlbl = newiTempLabel(NULL);
7821 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7823 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7825 genIfxJump (ifx,"a");
7829 pic16_outBitC(result);
7833 /* if left is same as result */
7834 if(pic16_sameRegs(AOP(result),AOP(left))){
7836 for(;size--; offset++,lit>>=8) {
7837 if(AOP_TYPE(right) == AOP_LIT){
7838 if((lit & 0xff) == 0)
7839 /* or'ing with 0 has no effect */
7842 int p = pic16_my_powof2(lit & 0xff);
7844 /* only one bit is set in the literal, so use a bsf instruction */
7845 pic16_emitpcode(POC_BSF,
7846 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7848 if(know_W != (lit & 0xff))
7849 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7850 know_W = lit & 0xff;
7851 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7856 if (AOP_TYPE(left) == AOP_ACC) {
7857 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
7858 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7860 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7861 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7863 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7864 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7870 // left & result in different registers
7871 if(AOP_TYPE(result) == AOP_CRY){
7873 // if(size), result in bit
7874 // if(!size && ifx), conditional oper: if(left | right)
7875 symbol *tlbl = newiTempLabel(NULL);
7876 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7877 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7881 pic16_emitcode(";XXX setb","c");
7883 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7884 pic16_emitcode(";XXX orl","a,%s",
7885 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7886 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7891 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7892 pic16_outBitC(result);
7894 jmpTrueOrFalse(ifx, tlbl);
7895 } else for(;(size--);offset++){
7897 // result = left & right
7898 if(AOP_TYPE(right) == AOP_LIT){
7899 int t = (lit >> (offset*8)) & 0x0FFL;
7902 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
7903 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7905 pic16_emitcode("movf","%s,w",
7906 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7907 pic16_emitcode("movwf","%s",
7908 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7911 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7912 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7913 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7915 pic16_emitcode("movlw","0x%x",t);
7916 pic16_emitcode("iorwf","%s,w",
7917 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7918 pic16_emitcode("movwf","%s",
7919 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7925 // faster than result <- left, anl result,right
7926 // and better if result is SFR
7927 if (AOP_TYPE(left) == AOP_ACC) {
7928 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
7929 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7931 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7932 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7934 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7935 pic16_emitcode("iorwf","%s,w",
7936 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7938 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7939 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7944 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7945 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7946 pic16_freeAsmop(result,NULL,ic,TRUE);
7949 /*-----------------------------------------------------------------*/
7950 /* genXor - code for xclusive or */
7951 /*-----------------------------------------------------------------*/
7952 static void genXor (iCode *ic, iCode *ifx)
7954 operand *left, *right, *result;
7956 unsigned long lit = 0L;
7958 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7960 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7961 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7962 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7964 /* if left is a literal & right is not ||
7965 if left needs acc & right does not */
7966 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7967 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7968 operand *tmp = right ;
7973 /* if result = right then exchange them */
7974 if(pic16_sameRegs(AOP(result),AOP(right))){
7975 operand *tmp = right ;
7980 /* if right is bit then exchange them */
7981 if (AOP_TYPE(right) == AOP_CRY &&
7982 AOP_TYPE(left) != AOP_CRY){
7983 operand *tmp = right ;
7987 if(AOP_TYPE(right) == AOP_LIT)
7988 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7990 size = AOP_SIZE(result);
7994 if (AOP_TYPE(left) == AOP_CRY){
7995 if(AOP_TYPE(right) == AOP_LIT){
7996 // c = bit & literal;
7998 // lit>>1 != 0 => result = 1
7999 if(AOP_TYPE(result) == AOP_CRY){
8001 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
8002 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8004 continueIfTrue(ifx);
8007 pic16_emitcode("setb","c");
8011 // lit == 0, result = left
8012 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8014 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8016 // lit == 1, result = not(left)
8017 if(size && pic16_sameRegs(AOP(result),AOP(left))){
8018 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
8019 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
8020 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8023 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8024 pic16_emitcode("cpl","c");
8031 symbol *tlbl = newiTempLabel(NULL);
8032 if (AOP_TYPE(right) == AOP_CRY){
8034 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8037 int sizer = AOP_SIZE(right);
8039 // if val>>1 != 0, result = 1
8040 pic16_emitcode("setb","c");
8042 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8044 // test the msb of the lsb
8045 pic16_emitcode("anl","a,#0xfe");
8046 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8050 pic16_emitcode("rrc","a");
8052 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8053 pic16_emitcode("cpl","c");
8054 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8059 pic16_outBitC(result);
8061 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8062 genIfxJump(ifx, "c");
8066 if(pic16_sameRegs(AOP(result),AOP(left))){
8067 /* if left is same as result */
8068 for(;size--; offset++) {
8069 if(AOP_TYPE(right) == AOP_LIT){
8070 int t = (lit >> (offset*8)) & 0x0FFL;
8074 if (IS_AOP_PREG(left)) {
8075 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8076 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8077 pic16_aopPut(AOP(result),"a",offset);
8079 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8080 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8081 pic16_emitcode("xrl","%s,%s",
8082 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8083 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8086 if (AOP_TYPE(left) == AOP_ACC)
8087 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8089 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8090 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8092 if (IS_AOP_PREG(left)) {
8093 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8094 pic16_aopPut(AOP(result),"a",offset);
8096 pic16_emitcode("xrl","%s,a",
8097 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8103 // left & result in different registers
8104 if(AOP_TYPE(result) == AOP_CRY){
8106 // if(size), result in bit
8107 // if(!size && ifx), conditional oper: if(left ^ right)
8108 symbol *tlbl = newiTempLabel(NULL);
8109 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8111 pic16_emitcode("setb","c");
8113 if((AOP_TYPE(right) == AOP_LIT) &&
8114 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8115 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8117 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8118 pic16_emitcode("xrl","a,%s",
8119 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8121 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8126 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8127 pic16_outBitC(result);
8129 jmpTrueOrFalse(ifx, tlbl);
8130 } else for(;(size--);offset++){
8132 // result = left & right
8133 if(AOP_TYPE(right) == AOP_LIT){
8134 int t = (lit >> (offset*8)) & 0x0FFL;
8137 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8138 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8139 pic16_emitcode("movf","%s,w",
8140 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8141 pic16_emitcode("movwf","%s",
8142 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8145 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8146 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8147 pic16_emitcode("comf","%s,w",
8148 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8149 pic16_emitcode("movwf","%s",
8150 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8153 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8154 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8155 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8156 pic16_emitcode("movlw","0x%x",t);
8157 pic16_emitcode("xorwf","%s,w",
8158 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8159 pic16_emitcode("movwf","%s",
8160 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8166 // faster than result <- left, anl result,right
8167 // and better if result is SFR
8168 if (AOP_TYPE(left) == AOP_ACC) {
8169 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8170 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8172 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8173 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8174 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8175 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8177 if ( AOP_TYPE(result) != AOP_ACC){
8178 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8179 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8185 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8186 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8187 pic16_freeAsmop(result,NULL,ic,TRUE);
8190 /*-----------------------------------------------------------------*/
8191 /* genInline - write the inline code out */
8192 /*-----------------------------------------------------------------*/
8193 static void genInline (iCode *ic)
8195 char *buffer, *bp, *bp1;
8197 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8199 _G.inLine += (!options.asmpeep);
8201 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8202 strcpy(buffer,IC_INLINE(ic));
8204 // fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
8206 /* emit each line as a code */
8212 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8220 /* print label, use this special format with NULL directive
8221 * to denote that the argument should not be indented with tab */
8222 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8229 if ((bp1 != bp) && *bp1)
8230 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8235 _G.inLine -= (!options.asmpeep);
8238 /*-----------------------------------------------------------------*/
8239 /* genRRC - rotate right with carry */
8240 /*-----------------------------------------------------------------*/
8241 static void genRRC (iCode *ic)
8243 operand *left , *result ;
8244 int size, offset = 0, same;
8246 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8248 /* rotate right with carry */
8250 result=IC_RESULT(ic);
8251 pic16_aopOp (left,ic,FALSE);
8252 pic16_aopOp (result,ic,FALSE);
8254 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8256 same = pic16_sameRegs(AOP(result),AOP(left));
8258 size = AOP_SIZE(result);
8260 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8262 /* get the lsb and put it into the carry */
8263 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8270 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8272 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8273 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8279 pic16_freeAsmop(left,NULL,ic,TRUE);
8280 pic16_freeAsmop(result,NULL,ic,TRUE);
8283 /*-----------------------------------------------------------------*/
8284 /* genRLC - generate code for rotate left with carry */
8285 /*-----------------------------------------------------------------*/
8286 static void genRLC (iCode *ic)
8288 operand *left , *result ;
8289 int size, offset = 0;
8292 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8293 /* rotate right with carry */
8295 result=IC_RESULT(ic);
8296 pic16_aopOp (left,ic,FALSE);
8297 pic16_aopOp (result,ic,FALSE);
8299 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8301 same = pic16_sameRegs(AOP(result),AOP(left));
8303 /* move it to the result */
8304 size = AOP_SIZE(result);
8306 /* get the msb and put it into the carry */
8307 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8314 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8316 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8317 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8324 pic16_freeAsmop(left,NULL,ic,TRUE);
8325 pic16_freeAsmop(result,NULL,ic,TRUE);
8329 /* gpasm can get the highest order bit with HIGH/UPPER
8330 * so the following probably is not needed -- VR */
8332 /*-----------------------------------------------------------------*/
8333 /* genGetHbit - generates code get highest order bit */
8334 /*-----------------------------------------------------------------*/
8335 static void genGetHbit (iCode *ic)
8337 operand *left, *result;
8339 result=IC_RESULT(ic);
8340 pic16_aopOp (left,ic,FALSE);
8341 pic16_aopOp (result,ic,FALSE);
8343 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8344 /* get the highest order byte into a */
8345 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8346 if(AOP_TYPE(result) == AOP_CRY){
8347 pic16_emitcode("rlc","a");
8348 pic16_outBitC(result);
8351 pic16_emitcode("rl","a");
8352 pic16_emitcode("anl","a,#0x01");
8353 pic16_outAcc(result);
8357 pic16_freeAsmop(left,NULL,ic,TRUE);
8358 pic16_freeAsmop(result,NULL,ic,TRUE);
8362 /*-----------------------------------------------------------------*/
8363 /* AccRol - rotate left accumulator by known count */
8364 /*-----------------------------------------------------------------*/
8365 static void AccRol (int shCount)
8367 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8368 shCount &= 0x0007; // shCount : 0..7
8373 pic16_emitcode("rl","a");
8376 pic16_emitcode("rl","a");
8377 pic16_emitcode("rl","a");
8380 pic16_emitcode("swap","a");
8381 pic16_emitcode("rr","a");
8384 pic16_emitcode("swap","a");
8387 pic16_emitcode("swap","a");
8388 pic16_emitcode("rl","a");
8391 pic16_emitcode("rr","a");
8392 pic16_emitcode("rr","a");
8395 pic16_emitcode("rr","a");
8401 /*-----------------------------------------------------------------*/
8402 /* AccLsh - left shift accumulator by known count */
8403 /*-----------------------------------------------------------------*/
8404 static void AccLsh (int shCount)
8406 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8412 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8415 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8416 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8419 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8420 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8423 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8426 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8427 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8430 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8431 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8434 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8438 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8441 /*-----------------------------------------------------------------*/
8442 /* AccRsh - right shift accumulator by known count */
8443 /*-----------------------------------------------------------------*/
8444 static void AccRsh (int shCount, int andmask)
8446 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8451 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8454 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8455 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8458 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8459 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8462 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8465 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8466 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8469 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8470 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8473 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8478 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8480 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8484 /*-----------------------------------------------------------------*/
8485 /* AccSRsh - signed right shift accumulator by known count */
8486 /*-----------------------------------------------------------------*/
8487 static void AccSRsh (int shCount)
8490 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8493 pic16_emitcode("mov","c,acc.7");
8494 pic16_emitcode("rrc","a");
8495 } else if(shCount == 2){
8496 pic16_emitcode("mov","c,acc.7");
8497 pic16_emitcode("rrc","a");
8498 pic16_emitcode("mov","c,acc.7");
8499 pic16_emitcode("rrc","a");
8501 tlbl = newiTempLabel(NULL);
8502 /* rotate right accumulator */
8503 AccRol(8 - shCount);
8504 /* and kill the higher order bits */
8505 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8506 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8507 pic16_emitcode("orl","a,#0x%02x",
8508 (unsigned char)~SRMask[shCount]);
8509 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8515 /*-----------------------------------------------------------------*/
8516 /* shiftR1Left2Result - shift right one byte from left to result */
8517 /*-----------------------------------------------------------------*/
8518 static void shiftR1Left2ResultSigned (operand *left, int offl,
8519 operand *result, int offr,
8524 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8526 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8530 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8532 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8534 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8535 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8541 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8543 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8545 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8546 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8548 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8549 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8555 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8557 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8558 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8561 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8562 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8563 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8565 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8566 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8568 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8572 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8573 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8574 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8575 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8576 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8580 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8582 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8583 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8585 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8586 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8587 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8588 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8589 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8594 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8595 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8596 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8597 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8598 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8599 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8601 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8602 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8603 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
8604 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8605 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8611 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8612 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8613 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8614 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8616 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8617 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8618 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
8626 /*-----------------------------------------------------------------*/
8627 /* shiftR1Left2Result - shift right one byte from left to result */
8628 /*-----------------------------------------------------------------*/
8629 static void shiftR1Left2Result (operand *left, int offl,
8630 operand *result, int offr,
8631 int shCount, int sign)
8635 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8637 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8639 /* Copy the msb into the carry if signed. */
8641 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8651 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8653 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8654 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8660 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8662 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8663 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8666 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8671 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8673 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8674 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8677 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8678 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8679 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8680 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8684 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8685 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8686 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8690 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8691 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8692 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8694 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8699 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
8700 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8701 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8702 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8703 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
8708 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8709 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8710 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8719 /*-----------------------------------------------------------------*/
8720 /* shiftL1Left2Result - shift left one byte from left to result */
8721 /*-----------------------------------------------------------------*/
8722 static void shiftL1Left2Result (operand *left, int offl,
8723 operand *result, int offr, int shCount)
8728 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8730 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8731 DEBUGpic16_emitcode ("; ***","same = %d",same);
8732 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8734 /* shift left accumulator */
8735 //AccLsh(shCount); // don't comment out just yet...
8736 // pic16_aopPut(AOP(result),"a",offr);
8740 /* Shift left 1 bit position */
8741 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8743 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8745 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8746 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8750 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8751 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8752 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8753 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8756 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8757 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8758 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8759 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8760 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8763 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8764 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8765 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8768 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8769 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8770 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8771 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8774 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8775 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8776 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8777 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8778 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8781 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8782 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8783 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8787 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8792 /*-----------------------------------------------------------------*/
8793 /* movLeft2Result - move byte from left to result */
8794 /*-----------------------------------------------------------------*/
8795 static void movLeft2Result (operand *left, int offl,
8796 operand *result, int offr)
8799 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8800 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8801 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8803 if (*l == '@' && (IS_AOP_PREG(result))) {
8804 pic16_emitcode("mov","a,%s",l);
8805 pic16_aopPut(AOP(result),"a",offr);
8807 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8808 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8813 /*-----------------------------------------------------------------*/
8814 /* shiftL2Left2Result - shift left two bytes from left to result */
8815 /*-----------------------------------------------------------------*/
8816 static void shiftL2Left2Result (operand *left, int offl,
8817 operand *result, int offr, int shCount)
8819 int same = pic16_sameRegs(AOP(result), AOP(left));
8822 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8824 if (same && (offl != offr)) { // shift bytes
8827 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8828 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8830 } else { // just treat as different later on
8843 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8844 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8845 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8849 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8850 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8856 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8857 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8858 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8859 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8860 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8861 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8862 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8864 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8865 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8869 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8870 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8871 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8872 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8873 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8874 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8875 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8876 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8877 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8878 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8881 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8882 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8883 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8884 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8885 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8895 /* note, use a mov/add for the shift since the mov has a
8896 chance of getting optimized out */
8897 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8898 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8899 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8900 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8901 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8905 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8906 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8912 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8913 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8914 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8915 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8916 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8917 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
8918 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8919 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8923 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8924 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8928 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8929 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8930 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8931 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8933 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8934 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8935 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8936 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8937 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8938 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8939 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8940 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8943 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8944 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8945 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8946 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8947 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8952 /*-----------------------------------------------------------------*/
8953 /* shiftR2Left2Result - shift right two bytes from left to result */
8954 /*-----------------------------------------------------------------*/
8955 static void shiftR2Left2Result (operand *left, int offl,
8956 operand *result, int offr,
8957 int shCount, int sign)
8959 int same = pic16_sameRegs(AOP(result), AOP(left));
8961 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8963 if (same && (offl != offr)) { // shift right bytes
8966 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8967 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8969 } else { // just treat as different later on
8981 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8986 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8987 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8989 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8990 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8991 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8992 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8997 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9000 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9001 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9008 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9009 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9010 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9012 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9013 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9014 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9015 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9017 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9018 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9019 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9021 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9022 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9023 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9024 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9025 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9029 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9030 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9034 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9035 pic16_emitpcode(POC_BTFSC,
9036 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9037 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9045 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9046 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9048 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9049 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9050 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9051 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9053 pic16_emitpcode(POC_BTFSC,
9054 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9055 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9057 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9058 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9059 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9060 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9062 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9063 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9064 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9065 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9066 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9067 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9068 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9069 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9071 pic16_emitpcode(POC_BTFSC,
9072 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9073 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9075 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9076 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9083 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9084 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9085 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9086 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9089 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9091 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9096 /*-----------------------------------------------------------------*/
9097 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9098 /*-----------------------------------------------------------------*/
9099 static void shiftLLeftOrResult (operand *left, int offl,
9100 operand *result, int offr, int shCount)
9102 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9104 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9105 /* shift left accumulator */
9107 /* or with result */
9108 /* back to result */
9109 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9112 /*-----------------------------------------------------------------*/
9113 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9114 /*-----------------------------------------------------------------*/
9115 static void shiftRLeftOrResult (operand *left, int offl,
9116 operand *result, int offr, int shCount)
9118 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9120 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9121 /* shift right accumulator */
9123 /* or with result */
9124 /* back to result */
9125 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9128 /*-----------------------------------------------------------------*/
9129 /* genlshOne - left shift a one byte quantity by known count */
9130 /*-----------------------------------------------------------------*/
9131 static void genlshOne (operand *result, operand *left, int shCount)
9133 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9134 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9137 /*-----------------------------------------------------------------*/
9138 /* genlshTwo - left shift two bytes by known amount != 0 */
9139 /*-----------------------------------------------------------------*/
9140 static void genlshTwo (operand *result,operand *left, int shCount)
9144 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9145 size = pic16_getDataSize(result);
9147 /* if shCount >= 8 */
9153 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9155 movLeft2Result(left, LSB, result, MSB16);
9157 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9160 /* 1 <= shCount <= 7 */
9163 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9165 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9169 /*-----------------------------------------------------------------*/
9170 /* shiftLLong - shift left one long from left to result */
9171 /* offr = LSB or MSB16 */
9172 /*-----------------------------------------------------------------*/
9173 static void shiftLLong (operand *left, operand *result, int offr )
9175 int size = AOP_SIZE(result);
9176 int same = pic16_sameRegs(AOP(left),AOP(result));
9179 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9181 if (same && (offr == MSB16)) { //shift one byte
9182 for(i=size-1;i>=MSB16;i--) {
9183 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9184 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9187 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9190 if (size > LSB+offr ){
9192 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9194 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9195 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9199 if(size > MSB16+offr){
9201 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9203 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9204 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9208 if(size > MSB24+offr){
9210 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9212 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9213 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9217 if(size > MSB32+offr){
9219 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9221 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9222 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9226 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9230 /*-----------------------------------------------------------------*/
9231 /* genlshFour - shift four byte by a known amount != 0 */
9232 /*-----------------------------------------------------------------*/
9233 static void genlshFour (operand *result, operand *left, int shCount)
9237 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9238 size = AOP_SIZE(result);
9240 /* if shifting more that 3 bytes */
9241 if (shCount >= 24 ) {
9244 /* lowest order of left goes to the highest
9245 order of the destination */
9246 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9248 movLeft2Result(left, LSB, result, MSB32);
9250 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9251 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9252 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9257 /* more than two bytes */
9258 else if ( shCount >= 16 ) {
9259 /* lower order two bytes goes to higher order two bytes */
9261 /* if some more remaining */
9263 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9265 movLeft2Result(left, MSB16, result, MSB32);
9266 movLeft2Result(left, LSB, result, MSB24);
9268 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9269 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9273 /* if more than 1 byte */
9274 else if ( shCount >= 8 ) {
9275 /* lower order three bytes goes to higher order three bytes */
9279 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9281 movLeft2Result(left, LSB, result, MSB16);
9283 else{ /* size = 4 */
9285 movLeft2Result(left, MSB24, result, MSB32);
9286 movLeft2Result(left, MSB16, result, MSB24);
9287 movLeft2Result(left, LSB, result, MSB16);
9288 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9290 else if(shCount == 1)
9291 shiftLLong(left, result, MSB16);
9293 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9294 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9295 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9296 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9301 /* 1 <= shCount <= 7 */
9302 else if(shCount <= 3)
9304 shiftLLong(left, result, LSB);
9305 while(--shCount >= 1)
9306 shiftLLong(result, result, LSB);
9308 /* 3 <= shCount <= 7, optimize */
9310 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9311 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9312 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9316 /*-----------------------------------------------------------------*/
9317 /* genLeftShiftLiteral - left shifting by known count */
9318 /*-----------------------------------------------------------------*/
9319 void pic16_genLeftShiftLiteral (operand *left,
9324 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
9328 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9329 pic16_freeAsmop(right,NULL,ic,TRUE);
9331 pic16_aopOp(left,ic,FALSE);
9332 pic16_aopOp(result,ic,FALSE);
9334 size = getSize(operandType(result));
9337 pic16_emitcode("; shift left ","result %d, left %d",size,
9341 /* I suppose that the left size >= result size */
9344 movLeft2Result(left, size, result, size);
9348 else if(shCount >= (size * 8))
9350 pic16_aopPut(AOP(result),zero,size);
9354 genlshOne (result,left,shCount);
9359 genlshTwo (result,left,shCount);
9363 genlshFour (result,left,shCount);
9367 pic16_freeAsmop(left,NULL,ic,TRUE);
9368 pic16_freeAsmop(result,NULL,ic,TRUE);
9371 /*-----------------------------------------------------------------*
9372 * genMultiAsm - repeat assembly instruction for size of register.
9373 * if endian == 1, then the high byte (i.e base address + size of
9374 * register) is used first else the low byte is used first;
9375 *-----------------------------------------------------------------*/
9376 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9381 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9394 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9399 /*-----------------------------------------------------------------*/
9400 /* genLeftShift - generates code for left shifting */
9401 /*-----------------------------------------------------------------*/
9402 static void genLeftShift (iCode *ic)
9404 operand *left,*right, *result;
9407 symbol *tlbl , *tlbl1;
9410 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9412 right = IC_RIGHT(ic);
9414 result = IC_RESULT(ic);
9416 pic16_aopOp(right,ic,FALSE);
9418 /* if the shift count is known then do it
9419 as efficiently as possible */
9420 if (AOP_TYPE(right) == AOP_LIT) {
9421 pic16_genLeftShiftLiteral (left,right,result,ic);
9425 /* shift count is unknown then we have to form
9426 * a loop. Get the loop count in WREG : Note: we take
9427 * only the lower order byte since shifting
9428 * more than 32 bits make no sense anyway, ( the
9429 * largest size of an object can be only 32 bits ) */
9431 pic16_aopOp(left,ic,FALSE);
9432 pic16_aopOp(result,ic,FALSE);
9434 /* now move the left to the result if they are not the
9435 * same, and if size > 1,
9436 * and if right is not same to result (!!!) -- VR */
9437 if (!pic16_sameRegs(AOP(left),AOP(result))
9438 && (AOP_SIZE(result) > 1)) {
9440 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9442 size = AOP_SIZE(result);
9447 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9448 if (*l == '@' && (IS_AOP_PREG(result))) {
9450 pic16_emitcode("mov","a,%s",l);
9451 pic16_aopPut(AOP(result),"a",offset);
9455 /* we don't know if left is a literal or a register, take care -- VR */
9456 mov2f(AOP(result), AOP(left), offset);
9462 size = AOP_SIZE(result);
9464 /* if it is only one byte then */
9466 if(optimized_for_speed) {
9467 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9468 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9469 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9470 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9471 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9472 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9473 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9474 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9475 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9476 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9477 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9478 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9481 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9483 tlbl = newiTempLabel(NULL);
9486 /* this is already done, why change it? */
9487 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9488 mov2f(AOP(result), AOP(left), 0);
9492 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9493 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9494 pic16_emitpLabel(tlbl->key);
9495 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9496 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9498 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9503 if (pic16_sameRegs(AOP(left),AOP(result))) {
9505 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9507 tlbl = newiTempLabel(NULL);
9508 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9509 genMultiAsm(POC_RRCF, result, size,1);
9510 pic16_emitpLabel(tlbl->key);
9511 genMultiAsm(POC_RLCF, result, size,0);
9512 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9514 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9518 //tlbl = newiTempLabel(NULL);
9520 //tlbl1 = newiTempLabel(NULL);
9522 //reAdjustPreg(AOP(result));
9524 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9525 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9526 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9528 //pic16_emitcode("add","a,acc");
9529 //pic16_aopPut(AOP(result),"a",offset++);
9531 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9533 // pic16_emitcode("rlc","a");
9534 // pic16_aopPut(AOP(result),"a",offset++);
9536 //reAdjustPreg(AOP(result));
9538 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9539 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9542 tlbl = newiTempLabel(NULL);
9543 tlbl1= newiTempLabel(NULL);
9545 size = AOP_SIZE(result);
9548 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9550 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9552 /* offset should be 0, 1 or 3 */
9554 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9556 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9558 pic16_emitpcode(POC_MOVWF, pctemp);
9561 pic16_emitpLabel(tlbl->key);
9564 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9566 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9568 pic16_emitpcode(POC_DECFSZ, pctemp);
9569 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9570 pic16_emitpLabel(tlbl1->key);
9572 pic16_popReleaseTempReg(pctemp,1);
9576 pic16_freeAsmop (right,NULL,ic,TRUE);
9577 pic16_freeAsmop(left,NULL,ic,TRUE);
9578 pic16_freeAsmop(result,NULL,ic,TRUE);
9584 #error old code (left here for reference)
9585 /*-----------------------------------------------------------------*/
9586 /* genLeftShift - generates code for left shifting */
9587 /*-----------------------------------------------------------------*/
9588 static void genLeftShift (iCode *ic)
9590 operand *left,*right, *result;
9593 symbol *tlbl , *tlbl1;
9596 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9598 right = IC_RIGHT(ic);
9600 result = IC_RESULT(ic);
9602 pic16_aopOp(right,ic,FALSE);
9604 /* if the shift count is known then do it
9605 as efficiently as possible */
9606 if (AOP_TYPE(right) == AOP_LIT) {
9607 pic16_genLeftShiftLiteral (left,right,result,ic);
9611 /* shift count is unknown then we have to form
9612 a loop get the loop count in B : Note: we take
9613 only the lower order byte since shifting
9614 more that 32 bits make no sense anyway, ( the
9615 largest size of an object can be only 32 bits ) */
9618 pic16_aopOp(left,ic,FALSE);
9619 pic16_aopOp(result,ic,FALSE);
9621 /* now move the left to the result if they are not the
9623 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9624 AOP_SIZE(result) > 1) {
9626 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9628 size = AOP_SIZE(result);
9631 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9632 if (*l == '@' && (IS_AOP_PREG(result))) {
9634 pic16_emitcode("mov","a,%s",l);
9635 pic16_aopPut(AOP(result),"a",offset);
9638 /* we don't know if left is a literal or a register, take care -- VR */
9639 mov2f(AOP(result), AOP(left), offset);
9645 size = AOP_SIZE(result);
9647 /* if it is only one byte then */
9649 if(optimized_for_speed) {
9650 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9651 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9652 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9653 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9654 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9655 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9656 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9657 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9658 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9659 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9660 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9661 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9664 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9666 tlbl = newiTempLabel(NULL);
9667 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9668 mov2f(AOP(result), AOP(left), 0);
9670 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9671 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9674 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9675 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9676 pic16_emitpLabel(tlbl->key);
9677 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9678 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9680 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9685 if (pic16_sameRegs(AOP(left),AOP(result))) {
9687 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9689 tlbl = newiTempLabel(NULL);
9690 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9691 genMultiAsm(POC_RRCF, result, size,1);
9692 pic16_emitpLabel(tlbl->key);
9693 genMultiAsm(POC_RLCF, result, size,0);
9694 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9696 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9700 //tlbl = newiTempLabel(NULL);
9702 //tlbl1 = newiTempLabel(NULL);
9704 //reAdjustPreg(AOP(result));
9706 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9707 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9708 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9710 //pic16_emitcode("add","a,acc");
9711 //pic16_aopPut(AOP(result),"a",offset++);
9713 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9715 // pic16_emitcode("rlc","a");
9716 // pic16_aopPut(AOP(result),"a",offset++);
9718 //reAdjustPreg(AOP(result));
9720 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9721 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9724 tlbl = newiTempLabel(NULL);
9725 tlbl1= newiTempLabel(NULL);
9727 size = AOP_SIZE(result);
9730 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9732 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9734 /* offset should be 0, 1 or 3 */
9736 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9738 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9740 pic16_emitpcode(POC_MOVWF, pctemp);
9743 pic16_emitpLabel(tlbl->key);
9746 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9748 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9750 pic16_emitpcode(POC_DECFSZ, pctemp);
9751 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9752 pic16_emitpLabel(tlbl1->key);
9754 pic16_popReleaseTempReg(pctemp,1);
9758 pic16_freeAsmop (right,NULL,ic,TRUE);
9759 pic16_freeAsmop(left,NULL,ic,TRUE);
9760 pic16_freeAsmop(result,NULL,ic,TRUE);
9764 /*-----------------------------------------------------------------*/
9765 /* genrshOne - right shift a one byte quantity by known count */
9766 /*-----------------------------------------------------------------*/
9767 static void genrshOne (operand *result, operand *left,
9768 int shCount, int sign)
9770 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9771 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9774 /*-----------------------------------------------------------------*/
9775 /* genrshTwo - right shift two bytes by known amount != 0 */
9776 /*-----------------------------------------------------------------*/
9777 static void genrshTwo (operand *result,operand *left,
9778 int shCount, int sign)
9780 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9781 /* if shCount >= 8 */
9785 shiftR1Left2Result(left, MSB16, result, LSB,
9788 movLeft2Result(left, MSB16, result, LSB);
9790 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9793 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9794 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
9798 /* 1 <= shCount <= 7 */
9800 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
9803 /*-----------------------------------------------------------------*/
9804 /* shiftRLong - shift right one long from left to result */
9805 /* offl = LSB or MSB16 */
9806 /*-----------------------------------------------------------------*/
9807 static void shiftRLong (operand *left, int offl,
9808 operand *result, int sign)
9810 int size = AOP_SIZE(result);
9811 int same = pic16_sameRegs(AOP(left),AOP(result));
9813 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9815 if (same && (offl == MSB16)) { //shift one byte right
9816 for(i=MSB16;i<size;i++) {
9817 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9818 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9823 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9829 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9831 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9832 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9836 /* add sign of "a" */
9837 pic16_addSign(result, MSB32, sign);
9841 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9843 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9844 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9848 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9850 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9851 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9855 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9858 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9859 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9864 /*-----------------------------------------------------------------*/
9865 /* genrshFour - shift four byte by a known amount != 0 */
9866 /*-----------------------------------------------------------------*/
9867 static void genrshFour (operand *result, operand *left,
9868 int shCount, int sign)
9870 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9871 /* if shifting more that 3 bytes */
9872 if(shCount >= 24 ) {
9875 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9877 movLeft2Result(left, MSB32, result, LSB);
9879 pic16_addSign(result, MSB16, sign);
9881 else if(shCount >= 16){
9884 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9886 movLeft2Result(left, MSB24, result, LSB);
9887 movLeft2Result(left, MSB32, result, MSB16);
9889 pic16_addSign(result, MSB24, sign);
9891 else if(shCount >= 8){
9894 shiftRLong(left, MSB16, result, sign);
9895 else if(shCount == 0){
9896 movLeft2Result(left, MSB16, result, LSB);
9897 movLeft2Result(left, MSB24, result, MSB16);
9898 movLeft2Result(left, MSB32, result, MSB24);
9899 pic16_addSign(result, MSB32, sign);
9901 else{ //shcount >= 2
9902 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9903 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9904 /* the last shift is signed */
9905 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9906 pic16_addSign(result, MSB32, sign);
9909 else{ /* 1 <= shCount <= 7 */
9911 shiftRLong(left, LSB, result, sign);
9913 shiftRLong(result, LSB, result, sign);
9916 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
9917 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
9918 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
9923 /*-----------------------------------------------------------------*/
9924 /* genRightShiftLiteral - right shifting by known count */
9925 /*-----------------------------------------------------------------*/
9926 static void genRightShiftLiteral (operand *left,
9932 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
9935 pic16_freeAsmop(right,NULL,ic,TRUE);
9937 pic16_aopOp(left,ic,FALSE);
9938 pic16_aopOp(result,ic,FALSE);
9940 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
9943 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
9947 lsize = pic16_getDataSize(left);
9948 res_size = pic16_getDataSize(result);
9949 /* test the LEFT size !!! */
9951 /* I suppose that the left size >= result size */
9954 movLeft2Result(left, lsize, result, res_size);
9957 else if(shCount >= (lsize * 8)){
9960 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
9962 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9963 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
9968 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
9969 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9970 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9972 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
9977 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
9984 genrshOne (result,left,shCount,sign);
9988 genrshTwo (result,left,shCount,sign);
9992 genrshFour (result,left,shCount,sign);
10000 pic16_freeAsmop(left,NULL,ic,TRUE);
10001 pic16_freeAsmop(result,NULL,ic,TRUE);
10004 /*-----------------------------------------------------------------*/
10005 /* genSignedRightShift - right shift of signed number */
10006 /*-----------------------------------------------------------------*/
10007 static void genSignedRightShift (iCode *ic)
10009 operand *right, *left, *result;
10012 symbol *tlbl, *tlbl1 ;
10015 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10017 /* we do it the hard way put the shift count in b
10018 and loop thru preserving the sign */
10019 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10021 right = IC_RIGHT(ic);
10022 left = IC_LEFT(ic);
10023 result = IC_RESULT(ic);
10025 pic16_aopOp(right,ic,FALSE);
10026 pic16_aopOp(left,ic,FALSE);
10027 pic16_aopOp(result,ic,FALSE);
10030 if ( AOP_TYPE(right) == AOP_LIT) {
10031 genRightShiftLiteral (left,right,result,ic,1);
10034 /* shift count is unknown then we have to form
10035 a loop get the loop count in B : Note: we take
10036 only the lower order byte since shifting
10037 more that 32 bits make no sense anyway, ( the
10038 largest size of an object can be only 32 bits ) */
10040 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10041 //pic16_emitcode("inc","b");
10042 //pic16_freeAsmop (right,NULL,ic,TRUE);
10043 //pic16_aopOp(left,ic,FALSE);
10044 //pic16_aopOp(result,ic,FALSE);
10046 /* now move the left to the result if they are not the
10048 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10049 AOP_SIZE(result) > 1) {
10051 size = AOP_SIZE(result);
10055 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10056 if (*l == '@' && IS_AOP_PREG(result)) {
10058 pic16_emitcode("mov","a,%s",l);
10059 pic16_aopPut(AOP(result),"a",offset);
10061 pic16_aopPut(AOP(result),l,offset);
10063 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10064 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10070 /* mov the highest order bit to OVR */
10071 tlbl = newiTempLabel(NULL);
10072 tlbl1= newiTempLabel(NULL);
10074 size = AOP_SIZE(result);
10077 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10079 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10081 /* offset should be 0, 1 or 3 */
10082 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10084 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10086 pic16_emitpcode(POC_MOVWF, pctemp);
10089 pic16_emitpLabel(tlbl->key);
10091 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10092 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10095 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10098 pic16_emitpcode(POC_DECFSZ, pctemp);
10099 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10100 pic16_emitpLabel(tlbl1->key);
10102 pic16_popReleaseTempReg(pctemp,1);
10104 size = AOP_SIZE(result);
10106 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10107 pic16_emitcode("rlc","a");
10108 pic16_emitcode("mov","ov,c");
10109 /* if it is only one byte then */
10111 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10113 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10114 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10115 pic16_emitcode("mov","c,ov");
10116 pic16_emitcode("rrc","a");
10117 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10118 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10119 pic16_aopPut(AOP(result),"a",0);
10123 reAdjustPreg(AOP(result));
10124 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10125 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10126 pic16_emitcode("mov","c,ov");
10128 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10130 pic16_emitcode("rrc","a");
10131 pic16_aopPut(AOP(result),"a",offset--);
10133 reAdjustPreg(AOP(result));
10134 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10135 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10140 pic16_freeAsmop(left,NULL,ic,TRUE);
10141 pic16_freeAsmop(result,NULL,ic,TRUE);
10142 pic16_freeAsmop(right,NULL,ic,TRUE);
10145 /*-----------------------------------------------------------------*/
10146 /* genRightShift - generate code for right shifting */
10147 /*-----------------------------------------------------------------*/
10148 static void genRightShift (iCode *ic)
10150 operand *right, *left, *result;
10154 symbol *tlbl, *tlbl1 ;
10156 /* if signed then we do it the hard way preserve the
10157 sign bit moving it inwards */
10158 letype = getSpec(operandType(IC_LEFT(ic)));
10159 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10161 if (!SPEC_USIGN(letype)) {
10162 genSignedRightShift (ic);
10166 /* signed & unsigned types are treated the same : i.e. the
10167 signed is NOT propagated inwards : quoting from the
10168 ANSI - standard : "for E1 >> E2, is equivalent to division
10169 by 2**E2 if unsigned or if it has a non-negative value,
10170 otherwise the result is implementation defined ", MY definition
10171 is that the sign does not get propagated */
10173 right = IC_RIGHT(ic);
10174 left = IC_LEFT(ic);
10175 result = IC_RESULT(ic);
10177 pic16_aopOp(right,ic,FALSE);
10179 /* if the shift count is known then do it
10180 as efficiently as possible */
10181 if (AOP_TYPE(right) == AOP_LIT) {
10182 genRightShiftLiteral (left,right,result,ic, 0);
10186 /* shift count is unknown then we have to form
10187 a loop get the loop count in B : Note: we take
10188 only the lower order byte since shifting
10189 more that 32 bits make no sense anyway, ( the
10190 largest size of an object can be only 32 bits ) */
10192 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10193 pic16_emitcode("inc","b");
10194 pic16_aopOp(left,ic,FALSE);
10195 pic16_aopOp(result,ic,FALSE);
10197 /* now move the left to the result if they are not the
10199 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10200 AOP_SIZE(result) > 1) {
10202 size = AOP_SIZE(result);
10205 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10206 if (*l == '@' && IS_AOP_PREG(result)) {
10208 pic16_emitcode("mov","a,%s",l);
10209 pic16_aopPut(AOP(result),"a",offset);
10211 pic16_aopPut(AOP(result),l,offset);
10216 tlbl = newiTempLabel(NULL);
10217 tlbl1= newiTempLabel(NULL);
10218 size = AOP_SIZE(result);
10221 /* if it is only one byte then */
10224 tlbl = newiTempLabel(NULL);
10225 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10226 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10227 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10230 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10231 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10232 pic16_emitpLabel(tlbl->key);
10233 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10234 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10236 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10241 reAdjustPreg(AOP(result));
10242 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10243 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10246 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10248 pic16_emitcode("rrc","a");
10249 pic16_aopPut(AOP(result),"a",offset--);
10251 reAdjustPreg(AOP(result));
10253 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10254 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10257 pic16_freeAsmop(left,NULL,ic,TRUE);
10258 pic16_freeAsmop (right,NULL,ic,TRUE);
10259 pic16_freeAsmop(result,NULL,ic,TRUE);
10263 void pic16_loadFSR0(operand *op)
10265 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10268 /*-----------------------------------------------------------------*/
10269 /* genUnpackBits - generates code for unpacking bits */
10270 /*-----------------------------------------------------------------*/
10271 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10275 sym_link *etype, *letype;
10276 int blen=0, bstr=0;
10280 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10281 etype = getSpec(operandType(result));
10282 letype = getSpec(operandType(left));
10284 // if(IS_BITFIELD(etype)) {
10285 blen = SPEC_BLEN(etype);
10286 bstr = SPEC_BSTR(etype);
10289 lbstr = SPEC_BSTR( letype );
10292 if((blen == 1) && (bstr < 8)) {
10293 /* it is a single bit, so use the appropriate bit instructions */
10294 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10296 if(IS_BITFIELD(etype)/* && !IS_ITEMP(left)*/) {
10297 pic16_emitpcode(POC_MOVFW, pic16_popGet( AOP(result), 0 ));
10298 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
10300 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10303 if((ptype == POINTER) && (result)) {
10304 /* workaround to reduce the extra lfsr instruction */
10305 pic16_emitpcode(POC_BTFSC,
10306 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10308 pic16_emitpcode(POC_BTFSC,
10309 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10313 if(IS_BITFIELD(etype)) {
10314 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
10316 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10319 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10325 /* the following call to pic16_loadFSR0 is temporary until
10326 * optimization to handle single bit assignments is added
10327 * to the function. Until then use the old safe way! -- VR */
10328 pic16_loadFSR0( left );
10330 /* read the first byte */
10337 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10340 pic16_emitcode("clr","a");
10341 pic16_emitcode("movc","a","@a+dptr");
10346 /* if we have bitdisplacement then it fits */
10347 /* into this byte completely or if length is */
10348 /* less than a byte */
10349 if ((shCnt = SPEC_BSTR(etype)) ||
10350 (SPEC_BLEN(etype) <= 8)) {
10352 /* shift right acc */
10355 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10356 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10358 /* VR -- normally I would use the following, but since we use the hack,
10359 * to avoid the masking from AccRsh, why not mask it right now? */
10362 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10365 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10371 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10372 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10375 /* bit field did not fit in a byte */
10376 rlen = SPEC_BLEN(etype) - 8;
10377 pic16_aopPut(AOP(result),"a",offset++);
10384 pic16_emitcode("inc","%s",rname);
10385 pic16_emitcode("mov","a,@%s",rname);
10389 pic16_emitcode("inc","%s",rname);
10390 pic16_emitcode("movx","a,@%s",rname);
10394 pic16_emitcode("inc","dptr");
10395 pic16_emitcode("movx","a,@dptr");
10399 pic16_emitcode("clr","a");
10400 pic16_emitcode("inc","dptr");
10401 pic16_emitcode("movc","a","@a+dptr");
10405 pic16_emitcode("inc","dptr");
10406 pic16_emitcode("lcall","__gptrget");
10411 /* if we are done */
10415 pic16_aopPut(AOP(result),"a",offset++);
10420 pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
10421 pic16_aopPut(AOP(result),"a",offset);
10428 static void genDataPointerGet(operand *left,
10432 int size, offset = 0, leoffset=0 ;
10434 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10435 pic16_aopOp(result, ic, FALSE);
10437 size = AOP_SIZE(result);
10438 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10442 /* The following tests may save a redudant movff instruction when
10443 * accessing unions */
10445 /* if they are the same */
10446 if (operandsEqu (left, result)) {
10447 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10453 /* if they are the same registers */
10454 if (pic16_sameRegs(AOP(left),AOP(result))) {
10455 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10461 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10462 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10463 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10470 if ( AOP_TYPE(left) == AOP_PCODE) {
10471 fprintf(stderr,"genDataPointerGet %s, %d\n",
10472 AOP(left)->aopu.pcop->name,
10473 (AOP(left)->aopu.pcop->type == PO_DIR)?
10474 PCOR(AOP(left)->aopu.pcop)->instance:
10475 PCOI(AOP(left)->aopu.pcop)->offset);
10479 if(AOP(left)->aopu.pcop->type == PO_DIR)
10480 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10482 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10485 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10487 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
10488 || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
10489 mov2w(AOP(left), offset); // patch 8
10490 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10492 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10493 pic16_popGet(AOP(left), offset), //patch 8
10494 pic16_popGet(AOP(result), offset)));
10502 pic16_freeAsmop(result,NULL,ic,TRUE);
10507 /*-----------------------------------------------------------------*/
10508 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
10509 /*-----------------------------------------------------------------*/
10510 static void genNearPointerGet (operand *left,
10515 //regs *preg = NULL ;
10516 sym_link *rtype, *retype;
10517 sym_link *ltype = operandType(left);
10521 rtype = operandType(result);
10522 retype= getSpec(rtype);
10524 pic16_aopOp(left,ic,FALSE);
10526 // pic16_DumpOp("(left)",left);
10527 // pic16_DumpOp("(result)",result);
10529 /* if left is rematerialisable and
10530 * result is not bit variable type and
10531 * the left is pointer to data space i.e
10532 * lower 128 bytes of space */
10534 if (AOP_TYPE(left) == AOP_PCODE
10535 && !IS_BITFIELD(retype)
10536 && DCL_TYPE(ltype) == POINTER) {
10538 genDataPointerGet (left,result,ic);
10539 pic16_freeAsmop(left, NULL, ic, TRUE);
10543 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10545 /* if the value is already in a pointer register
10546 * then don't need anything more */
10547 if (!AOP_INPREG(AOP(left))) {
10548 /* otherwise get a free pointer register */
10549 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10551 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
10552 /* bitfields will be handled by genUnpackBits */
10553 if(!IS_BITFIELD(retype)) {
10555 if(is_LitAOp( AOP(left) )) {
10556 pic16_loadFSR0( left );
10558 // set up FSR0 with address from left
10559 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
10560 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
10565 // rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10567 pic16_aopOp (result,ic,FALSE);
10569 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10571 /* if bitfield then unpack the bits */
10572 if (IS_BITFIELD(retype))
10573 genUnpackBits (result, left, NULL, POINTER);
10575 /* we have can just get the values */
10576 int size = AOP_SIZE(result);
10579 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10581 /* fsr0 is loaded already -- VR */
10582 // pic16_loadFSR0( left );
10584 // pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
10585 // pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
10588 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10589 pic16_popGet(AOP(result), offset++)));
10591 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10592 pic16_popGet(AOP(result), offset++)));
10596 // pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
10597 // pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
10599 pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
10603 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
10605 pic16_emitcode("mov","a,@%s",rname);
10606 pic16_aopPut(AOP(result),"a",offset);
10608 sprintf(buffer,"@%s",rname);
10609 pic16_aopPut(AOP(result),buffer,offset);
10613 pic16_emitcode("inc","%s",rname);
10618 /* now some housekeeping stuff */
10620 /* we had to allocate for this iCode */
10621 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10622 pic16_freeAsmop(NULL,aop,ic,TRUE);
10624 /* we did not allocate which means left
10625 * already in a pointer register, then
10626 * if size > 0 && this could be used again
10627 * we have to point it back to where it
10629 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10630 if (AOP_SIZE(result) > 1
10631 && !OP_SYMBOL(left)->remat
10632 && ( OP_SYMBOL(left)->liveTo > ic->seq
10634 // int size = AOP_SIZE(result) - 1;
10636 // pic16_emitcode("dec","%s",rname);
10641 pic16_freeAsmop(left,NULL,ic,TRUE);
10642 pic16_freeAsmop(result,NULL,ic,TRUE);
10645 /*-----------------------------------------------------------------*/
10646 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
10647 /*-----------------------------------------------------------------*/
10648 static void genPagedPointerGet (operand *left,
10653 regs *preg = NULL ;
10655 sym_link *rtype, *retype;
10657 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10659 rtype = operandType(result);
10660 retype= getSpec(rtype);
10662 pic16_aopOp(left,ic,FALSE);
10664 /* if the value is already in a pointer register
10665 then don't need anything more */
10666 if (!AOP_INPREG(AOP(left))) {
10667 /* otherwise get a free pointer register */
10669 preg = getFreePtr(ic,&aop,FALSE);
10670 pic16_emitcode("mov","%s,%s",
10672 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10673 rname = preg->name ;
10675 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10677 pic16_freeAsmop(left,NULL,ic,TRUE);
10678 pic16_aopOp (result,ic,FALSE);
10680 /* if bitfield then unpack the bits */
10681 if (IS_BITFIELD(retype))
10682 genUnpackBits (result,left,rname,PPOINTER);
10684 /* we have can just get the values */
10685 int size = AOP_SIZE(result);
10690 pic16_emitcode("movx","a,@%s",rname);
10691 pic16_aopPut(AOP(result),"a",offset);
10696 pic16_emitcode("inc","%s",rname);
10700 /* now some housekeeping stuff */
10702 /* we had to allocate for this iCode */
10703 pic16_freeAsmop(NULL,aop,ic,TRUE);
10705 /* we did not allocate which means left
10706 already in a pointer register, then
10707 if size > 0 && this could be used again
10708 we have to point it back to where it
10710 if (AOP_SIZE(result) > 1 &&
10711 !OP_SYMBOL(left)->remat &&
10712 ( OP_SYMBOL(left)->liveTo > ic->seq ||
10714 int size = AOP_SIZE(result) - 1;
10716 pic16_emitcode("dec","%s",rname);
10721 pic16_freeAsmop(result,NULL,ic,TRUE);
10726 /*-----------------------------------------------------------------*/
10727 /* genFarPointerGet - gget value from far space */
10728 /*-----------------------------------------------------------------*/
10729 static void genFarPointerGet (operand *left,
10730 operand *result, iCode *ic)
10733 sym_link *retype = getSpec(operandType(result));
10735 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10737 pic16_aopOp(left,ic,FALSE);
10739 /* if the operand is already in dptr
10740 then we do nothing else we move the value to dptr */
10741 if (AOP_TYPE(left) != AOP_STR) {
10742 /* if this is remateriazable */
10743 if (AOP_TYPE(left) == AOP_IMMD)
10744 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10745 else { /* we need to get it byte by byte */
10746 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10747 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10748 if (options.model == MODEL_FLAT24)
10750 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10754 /* so dptr know contains the address */
10755 pic16_freeAsmop(left,NULL,ic,TRUE);
10756 pic16_aopOp(result,ic,FALSE);
10758 /* if bit then unpack */
10759 if (IS_BITFIELD(retype))
10760 genUnpackBits(result,left,"dptr",FPOINTER);
10762 size = AOP_SIZE(result);
10766 pic16_emitcode("movx","a,@dptr");
10767 pic16_aopPut(AOP(result),"a",offset++);
10769 pic16_emitcode("inc","dptr");
10773 pic16_freeAsmop(result,NULL,ic,TRUE);
10776 /*-----------------------------------------------------------------*/
10777 /* genCodePointerGet - get value from code space */
10778 /*-----------------------------------------------------------------*/
10779 static void genCodePointerGet (operand *left,
10780 operand *result, iCode *ic)
10783 sym_link *retype = getSpec(operandType(result));
10785 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10787 pic16_aopOp(left,ic,FALSE);
10789 /* if the operand is already in dptr
10790 then we do nothing else we move the value to dptr */
10791 if (AOP_TYPE(left) != AOP_STR) {
10792 /* if this is remateriazable */
10793 if (AOP_TYPE(left) == AOP_IMMD)
10794 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10795 else { /* we need to get it byte by byte */
10796 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10797 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10798 if (options.model == MODEL_FLAT24)
10800 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10804 /* so dptr know contains the address */
10805 pic16_freeAsmop(left,NULL,ic,TRUE);
10806 pic16_aopOp(result,ic,FALSE);
10808 /* if bit then unpack */
10809 if (IS_BITFIELD(retype))
10810 genUnpackBits(result,left,"dptr",CPOINTER);
10812 size = AOP_SIZE(result);
10816 pic16_emitcode("clr","a");
10817 pic16_emitcode("movc","a,@a+dptr");
10818 pic16_aopPut(AOP(result),"a",offset++);
10820 pic16_emitcode("inc","dptr");
10824 pic16_freeAsmop(result,NULL,ic,TRUE);
10828 /*-----------------------------------------------------------------*/
10829 /* genGenPointerGet - gget value from generic pointer space */
10830 /*-----------------------------------------------------------------*/
10831 static void genGenPointerGet (operand *left,
10832 operand *result, iCode *ic)
10834 int size, offset, lit;
10835 sym_link *retype = getSpec(operandType(result));
10837 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10838 pic16_aopOp(left,ic,FALSE);
10839 pic16_aopOp(result,ic,FALSE);
10840 size = AOP_SIZE(result);
10842 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10844 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
10846 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
10847 // load FSR0 from immediate
10848 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10850 // pic16_loadFSR0( left );
10855 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
10857 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
10864 else { /* we need to get it byte by byte */
10865 // set up FSR0 with address from left
10866 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10867 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10873 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
10875 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
10882 /* if bit then unpack */
10883 if (IS_BITFIELD(retype))
10884 genUnpackBits(result,left,"BAD",GPOINTER);
10887 pic16_freeAsmop(left,NULL,ic,TRUE);
10888 pic16_freeAsmop(result,NULL,ic,TRUE);
10894 /*-----------------------------------------------------------------*/
10895 /* genGenPointerGet - gget value from generic pointer space */
10896 /*-----------------------------------------------------------------*/
10897 static void genGenPointerGet (operand *left,
10898 operand *result, iCode *ic)
10900 int size, offset, lit;
10901 sym_link *retype = getSpec(operandType(result));
10904 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10905 pic16_aopOp(left,ic,FALSE);
10906 pic16_aopOp(result,ic,FALSE);
10907 size = AOP_SIZE(result);
10909 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10911 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
10913 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
10914 // load FSR0 from immediate
10915 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10917 werror(W_POSSBUG2, __FILE__, __LINE__);
10922 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
10924 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
10931 } else { /* we need to get it byte by byte */
10933 /* set up WREG:PRODL:FSR0L with address from left */
10934 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10935 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
10936 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
10939 case 1: strcpy(fgptrget, "__gptrget1"); break;
10940 case 2: strcpy(fgptrget, "__gptrget2"); break;
10941 case 3: strcpy(fgptrget, "__gptrget3"); break;
10942 case 4: strcpy(fgptrget, "__gptrget4"); break;
10944 werror(W_POSSBUG2, __FILE__, __LINE__);
10948 pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
10950 assignResultValue(result, 1);
10955 sym = newSymbol( fgptrget, 0 );
10956 strcpy(sym->rname, fgptrget);
10957 checkAddSym(&externs, sym);
10959 // fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
10965 /* if bit then unpack */
10966 if (IS_BITFIELD(retype))
10967 genUnpackBits(result,left,"BAD",GPOINTER);
10970 pic16_freeAsmop(left,NULL,ic,TRUE);
10971 pic16_freeAsmop(result,NULL,ic,TRUE);
10974 /*-----------------------------------------------------------------*/
10975 /* genConstPointerGet - get value from const generic pointer space */
10976 /*-----------------------------------------------------------------*/
10977 static void genConstPointerGet (operand *left,
10978 operand *result, iCode *ic)
10980 //sym_link *retype = getSpec(operandType(result));
10981 // symbol *albl = newiTempLabel(NULL); // patch 15
10982 // symbol *blbl = newiTempLabel(NULL); //
10983 // PIC_OPCODE poc; // patch 15
10987 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10988 pic16_aopOp(left,ic,FALSE);
10989 pic16_aopOp(result,ic,TRUE);
10990 size = AOP_SIZE(result);
10992 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10994 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
10996 pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
10997 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
10998 pic16_emitpLabel(albl->key);
11000 poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
11002 /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
11003 pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
11004 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
11005 pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
11006 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
11008 pic16_emitpLabel(blbl->key);
11010 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
11014 // set up table pointer
11015 if( (AOP_TYPE(left) == AOP_PCODE)
11016 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11017 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 15 ......
11019 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11020 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11021 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11022 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11023 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11024 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11028 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11029 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11030 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11036 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11037 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11041 pic16_freeAsmop(left,NULL,ic,TRUE);
11042 pic16_freeAsmop(result,NULL,ic,TRUE);
11047 /*-----------------------------------------------------------------*/
11048 /* genPointerGet - generate code for pointer get */
11049 /*-----------------------------------------------------------------*/
11050 static void genPointerGet (iCode *ic)
11052 operand *left, *result ;
11053 sym_link *type, *etype;
11058 left = IC_LEFT(ic);
11059 result = IC_RESULT(ic) ;
11061 /* depending on the type of pointer we need to
11062 move it to the correct pointer register */
11063 type = operandType(left);
11064 etype = getSpec(type);
11067 if (IS_PTR_CONST(type))
11069 if (IS_CODEPTR(type))
11071 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11073 /* if left is of type of pointer then it is simple */
11074 if (IS_PTR(type) && !IS_FUNC(type->next))
11075 p_type = DCL_TYPE(type);
11077 /* we have to go by the storage class */
11078 p_type = PTR_TYPE(SPEC_OCLS(etype));
11080 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11082 if (SPEC_OCLS(etype)->codesp ) {
11083 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11084 //p_type = CPOINTER ;
11087 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
11088 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11089 /*p_type = FPOINTER ;*/
11091 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
11092 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11093 /* p_type = PPOINTER; */
11095 if (SPEC_OCLS(etype) == idata )
11096 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11097 /* p_type = IPOINTER; */
11099 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11100 /* p_type = POINTER ; */
11103 /* now that we have the pointer type we assign
11104 the pointer values */
11109 genNearPointerGet (left,result,ic);
11113 genPagedPointerGet(left,result,ic);
11117 genFarPointerGet (left,result,ic);
11121 genConstPointerGet (left,result,ic);
11122 //pic16_emitcodePointerGet (left,result,ic);
11127 if (IS_PTR_CONST(type))
11128 genConstPointerGet (left,result,ic);
11131 genGenPointerGet (left,result,ic);
11135 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11136 "genPointerGet: illegal pointer type");
11142 /*-----------------------------------------------------------------*/
11143 /* genPackBits - generates code for packed bit storage */
11144 /*-----------------------------------------------------------------*/
11145 static void genPackBits (sym_link *etype , operand *result,
11147 char *rname, int p_type)
11156 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11157 blen = SPEC_BLEN(etype);
11158 bstr = SPEC_BSTR(etype);
11160 retype = getSpec(operandType(right));
11162 if(AOP_TYPE(right) == AOP_LIT) {
11163 if((blen == 1) && (bstr < 8)) {
11165 /* it is a single bit, so use the appropriate bit instructions */
11167 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11169 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11170 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11171 if((p_type == POINTER) && (result)) {
11172 /* workaround to reduce the extra lfsr instruction */
11174 pic16_emitpcode(POC_BSF,
11175 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11177 pic16_emitpcode(POC_BCF,
11178 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11181 pic16_loadFSR0( result );
11183 pic16_emitpcode(POC_BSF,
11184 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11186 pic16_emitpcode(POC_BCF,
11187 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11194 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11197 if(IS_BITFIELD(retype)
11198 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11202 rblen = SPEC_BLEN( retype );
11203 rbstr = SPEC_BSTR( retype );
11206 if(IS_BITFIELD(etype)) {
11207 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11208 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11210 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11213 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11215 if(IS_BITFIELD(etype)) {
11216 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11218 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11221 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11225 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11227 /* if the bit lenth is less than or */
11228 /* it exactly fits a byte then */
11229 if((shCnt=SPEC_BSTR(etype))
11230 || SPEC_BLEN(etype) <= 8 ) {
11232 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11234 /* shift left acc */
11237 /* using PRODL as a temporary register here */
11238 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11243 pic16_loadFSR0( result );
11244 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11245 // pic16_emitcode ("mov","b,a");
11246 // pic16_emitcode("mov","a,@%s",rname);
11250 werror(W_POSSBUG2, __FILE__, __LINE__);
11255 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11256 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11257 (unsigned char)(0xff >> (8-bstr))) ));
11258 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
11259 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11266 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11267 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11272 if ( SPEC_BLEN(etype) <= 8 )
11275 pic16_emitcode("inc","%s",rname);
11276 rLen = SPEC_BLEN(etype) ;
11280 /* now generate for lengths greater than one byte */
11283 l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
11293 pic16_emitcode("mov","@%s,a",rname);
11295 pic16_emitcode("mov","@%s,%s",rname,l);
11300 pic16_emitcode("movx","@dptr,a");
11305 DEBUGpic16_emitcode(";lcall","__gptrput");
11308 pic16_emitcode ("inc","%s",rname);
11313 /* last last was not complete */
11315 /* save the byte & read byte */
11318 pic16_emitcode ("mov","b,a");
11319 pic16_emitcode("mov","a,@%s",rname);
11323 pic16_emitcode ("mov","b,a");
11324 pic16_emitcode("movx","a,@dptr");
11328 pic16_emitcode ("push","b");
11329 pic16_emitcode ("push","acc");
11330 pic16_emitcode ("lcall","__gptrget");
11331 pic16_emitcode ("pop","b");
11335 pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11336 pic16_emitcode ("orl","a,b");
11339 if (p_type == GPOINTER)
11340 pic16_emitcode("pop","b");
11345 pic16_emitcode("mov","@%s,a",rname);
11349 pic16_emitcode("movx","@dptr,a");
11353 DEBUGpic16_emitcode(";lcall","__gptrput");
11357 /*-----------------------------------------------------------------*/
11358 /* genDataPointerSet - remat pointer to data space */
11359 /*-----------------------------------------------------------------*/
11360 static void genDataPointerSet(operand *right,
11364 int size, offset = 0, resoffset=0 ;
11366 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11367 pic16_aopOp(right,ic,FALSE);
11369 size = AOP_SIZE(right);
11371 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11374 if ( AOP_TYPE(result) == AOP_PCODE) {
11375 fprintf(stderr,"genDataPointerSet %s, %d\n",
11376 AOP(result)->aopu.pcop->name,
11377 (AOP(result)->aopu.pcop->type == PO_DIR)?
11378 PCOR(AOP(result)->aopu.pcop)->instance:
11379 PCOI(AOP(result)->aopu.pcop)->offset);
11383 if(AOP(result)->aopu.pcop->type == PO_DIR)
11384 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11387 if (AOP_TYPE(right) == AOP_LIT) {
11390 if(!IS_FLOAT(operandType( right )))
11391 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11394 unsigned long lit_int;
11398 /* take care if literal is a float */
11399 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11400 lit = info.lit_int;
11403 lit = lit >> (8*offset);
11405 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11406 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11408 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11411 mov2w(AOP(right), offset);
11412 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11418 pic16_freeAsmop(right,NULL,ic,TRUE);
11423 /*-----------------------------------------------------------------*/
11424 /* genNearPointerSet - pic16_emitcode for near pointer put */
11425 /*-----------------------------------------------------------------*/
11426 static void genNearPointerSet (operand *right,
11433 sym_link *ptype = operandType(result);
11434 sym_link *resetype;
11436 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11437 retype= getSpec(operandType(right));
11438 resetype = getSpec(operandType(result));
11440 pic16_aopOp(result,ic,FALSE);
11442 /* if the result is rematerializable &
11443 * in data space & not a bit variable */
11445 /* and result is not a bit variable */
11446 if (AOP_TYPE(result) == AOP_PCODE
11447 // && AOP_TYPE(result) == AOP_IMMD
11448 && DCL_TYPE(ptype) == POINTER
11449 && !IS_BITFIELD(retype)
11450 && !IS_BITFIELD(resetype)) {
11452 genDataPointerSet (right,result,ic);
11453 pic16_freeAsmop(result,NULL,ic,TRUE);
11457 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11458 pic16_aopOp(right,ic,FALSE);
11459 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11461 /* if the value is already in a pointer register
11462 * then don't need anything more */
11463 if (!AOP_INPREG(AOP(result))) {
11464 /* otherwise get a free pointer register */
11465 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11467 // if( (AOP_TYPE(result) == AOP_PCODE)
11468 // && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
11469 // || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
11470 if(is_LitAOp( AOP(result) ))
11472 if(!IS_BITFIELD(resetype))
11473 pic16_loadFSR0( result ); // patch 10
11475 if(!IS_BITFIELD(resetype)) {
11476 // set up FSR0 with address of result
11477 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
11478 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
11484 // rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11486 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11488 // pic16_loadFSR0( result );
11490 /* if bitfield then unpack the bits */
11491 if (IS_BITFIELD(resetype)) {
11492 genPackBits (resetype, result, right, NULL, POINTER);
11494 /* we have can just get the values */
11495 int size = AOP_SIZE(right);
11498 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11500 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11503 //pic16_emitcode("mov","@%s,a",rname);
11504 pic16_emitcode("movf","indf0,w ;1");
11507 if (AOP_TYPE(right) == AOP_LIT) { // patch 10
11508 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset)); //
11510 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0)); //
11512 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0)); //
11514 } else { // no literal //
11516 pic16_emitpcode(POC_MOVFF, //
11517 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
11518 pic16_popCopyReg(&pic16_pc_postinc0))); //
11520 pic16_emitpcode(POC_MOVFF, //
11521 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
11522 pic16_popCopyReg(&pic16_pc_indf0))); //
11530 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11531 /* now some housekeeping stuff */
11533 /* we had to allocate for this iCode */
11534 pic16_freeAsmop(NULL,aop,ic,TRUE);
11536 /* we did not allocate which means left
11537 * already in a pointer register, then
11538 * if size > 0 && this could be used again
11539 * we have to point it back to where it
11541 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11542 if (AOP_SIZE(right) > 1
11543 && !OP_SYMBOL(result)->remat
11544 && ( OP_SYMBOL(result)->liveTo > ic->seq
11547 int size = AOP_SIZE(right) - 1;
11550 pic16_emitcode("decf","fsr0,f");
11551 //pic16_emitcode("dec","%s",rname);
11555 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11558 pic16_freeAsmop(right,NULL,ic,TRUE);
11559 pic16_freeAsmop(result,NULL,ic,TRUE);
11562 /*-----------------------------------------------------------------*/
11563 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
11564 /*-----------------------------------------------------------------*/
11565 static void genPagedPointerSet (operand *right,
11570 regs *preg = NULL ;
11574 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11576 retype= getSpec(operandType(right));
11578 pic16_aopOp(result,ic,FALSE);
11580 /* if the value is already in a pointer register
11581 then don't need anything more */
11582 if (!AOP_INPREG(AOP(result))) {
11583 /* otherwise get a free pointer register */
11585 preg = getFreePtr(ic,&aop,FALSE);
11586 pic16_emitcode("mov","%s,%s",
11588 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11589 rname = preg->name ;
11591 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11593 pic16_freeAsmop(result,NULL,ic,TRUE);
11594 pic16_aopOp (right,ic,FALSE);
11596 /* if bitfield then unpack the bits */
11597 if (IS_BITFIELD(retype))
11598 genPackBits (retype,result,right,rname,PPOINTER);
11600 /* we have can just get the values */
11601 int size = AOP_SIZE(right);
11605 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11608 pic16_emitcode("movx","@%s,a",rname);
11611 pic16_emitcode("inc","%s",rname);
11617 /* now some housekeeping stuff */
11619 /* we had to allocate for this iCode */
11620 pic16_freeAsmop(NULL,aop,ic,TRUE);
11622 /* we did not allocate which means left
11623 already in a pointer register, then
11624 if size > 0 && this could be used again
11625 we have to point it back to where it
11627 if (AOP_SIZE(right) > 1 &&
11628 !OP_SYMBOL(result)->remat &&
11629 ( OP_SYMBOL(result)->liveTo > ic->seq ||
11631 int size = AOP_SIZE(right) - 1;
11633 pic16_emitcode("dec","%s",rname);
11638 pic16_freeAsmop(right,NULL,ic,TRUE);
11643 /*-----------------------------------------------------------------*/
11644 /* genFarPointerSet - set value from far space */
11645 /*-----------------------------------------------------------------*/
11646 static void genFarPointerSet (operand *right,
11647 operand *result, iCode *ic)
11650 sym_link *retype = getSpec(operandType(right));
11652 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11653 pic16_aopOp(result,ic,FALSE);
11655 /* if the operand is already in dptr
11656 then we do nothing else we move the value to dptr */
11657 if (AOP_TYPE(result) != AOP_STR) {
11658 /* if this is remateriazable */
11659 if (AOP_TYPE(result) == AOP_IMMD)
11660 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11661 else { /* we need to get it byte by byte */
11662 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11663 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11664 if (options.model == MODEL_FLAT24)
11666 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11670 /* so dptr know contains the address */
11671 pic16_freeAsmop(result,NULL,ic,TRUE);
11672 pic16_aopOp(right,ic,FALSE);
11674 /* if bit then unpack */
11675 if (IS_BITFIELD(retype))
11676 genPackBits(retype,result,right,"dptr",FPOINTER);
11678 size = AOP_SIZE(right);
11682 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11684 pic16_emitcode("movx","@dptr,a");
11686 pic16_emitcode("inc","dptr");
11690 pic16_freeAsmop(right,NULL,ic,TRUE);
11693 /*-----------------------------------------------------------------*/
11694 /* genGenPointerSet - set value from generic pointer space */
11695 /*-----------------------------------------------------------------*/
11697 static void genGenPointerSet (operand *right,
11698 operand *result, iCode *ic)
11700 int i, size, offset, lit;
11701 sym_link *retype = getSpec(operandType(right));
11703 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11705 pic16_aopOp(result,ic,FALSE);
11706 pic16_aopOp(right,ic,FALSE);
11707 size = AOP_SIZE(right);
11710 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11712 /* if the operand is already in dptr
11713 then we do nothing else we move the value to dptr */
11714 if (AOP_TYPE(result) != AOP_STR) {
11715 /* if this is remateriazable */
11716 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11717 // WARNING: anythig until "else" is untested!
11718 if (AOP_TYPE(result) == AOP_IMMD) {
11719 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11720 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11721 // load FSR0 from immediate
11722 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11726 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11728 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11734 else { /* we need to get it byte by byte */
11735 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11736 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11738 // set up FSR0 with address of result
11739 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11740 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11742 /* hack hack! see if this the FSR. If so don't load W */
11743 if(AOP_TYPE(right) != AOP_ACC) {
11745 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11747 if(AOP_TYPE(right) == AOP_LIT)
11750 // note: pic16_popGet handles sign extension
11751 for(i=0;i<size;i++) {
11752 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11754 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11756 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11761 for(i=0;i<size;i++) {
11763 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11764 pic16_popCopyReg(&pic16_pc_postinc0)));
11766 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11767 pic16_popCopyReg(&pic16_pc_indf0)));
11773 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11774 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11776 } // if (AOP_TYPE(result) != AOP_IMMD)
11778 } // if (AOP_TYPE(result) != AOP_STR)
11779 /* so dptr know contains the address */
11782 /* if bit then unpack */
11783 if (IS_BITFIELD(retype))
11784 genPackBits(retype,result,right,"dptr",GPOINTER);
11786 size = AOP_SIZE(right);
11789 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
11791 // set up FSR0 with address of result
11792 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11793 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11796 if (AOP_TYPE(right) == AOP_LIT) {
11797 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11799 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11801 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11803 } else { // no literal
11805 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11807 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11815 pic16_freeAsmop(right,NULL,ic,TRUE);
11816 pic16_freeAsmop(result,NULL,ic,TRUE);
11820 static void genGenPointerSet (operand *right,
11821 operand *result, iCode *ic)
11824 sym_link *retype = getSpec(operandType(right));
11827 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11829 pic16_aopOp(result,ic,FALSE);
11830 pic16_aopOp(right,ic,FALSE);
11831 size = AOP_SIZE(right);
11833 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11836 /* if bit then unpack */
11837 if (IS_BITFIELD(retype)) {
11838 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11839 genPackBits(retype,result,right,"dptr",GPOINTER);
11843 size = AOP_SIZE(right);
11845 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
11849 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
11851 /* value of right+0 is placed on stack, which will be retrieved
11852 * by the support function this restoring the stack. The important
11853 * thing is that there is no need to manually restore stack pointer
11855 pushaop(AOP(right), 0);
11856 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
11857 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
11858 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
11859 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
11861 /* load address to write to in WREG:FSR0H:FSR0L */
11862 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
11863 pic16_popCopyReg(&pic16_pc_fsr0l)));
11864 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
11865 pic16_popCopyReg(&pic16_pc_prodl)));
11866 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
11869 /* put code here */
11871 case 1: strcpy(fgptrput, "__gptrput1"); break;
11872 case 2: strcpy(fgptrput, "__gptrput2"); break;
11873 case 3: strcpy(fgptrput, "__gptrput3"); break;
11874 case 4: strcpy(fgptrput, "__gptrput4"); break;
11876 werror(W_POSSBUG2, __FILE__, __LINE__);
11880 pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
11885 sym = newSymbol( fgptrput, 0 );
11886 strcpy(sym->rname, fgptrput);
11887 checkAddSym(&externs, sym);
11891 pic16_freeAsmop(right,NULL,ic,TRUE);
11892 pic16_freeAsmop(result,NULL,ic,TRUE);
11895 /*-----------------------------------------------------------------*/
11896 /* genPointerSet - stores the value into a pointer location */
11897 /*-----------------------------------------------------------------*/
11898 static void genPointerSet (iCode *ic)
11900 operand *right, *result ;
11901 sym_link *type, *etype;
11906 right = IC_RIGHT(ic);
11907 result = IC_RESULT(ic) ;
11909 /* depending on the type of pointer we need to
11910 move it to the correct pointer register */
11911 type = operandType(result);
11912 etype = getSpec(type);
11913 /* if left is of type of pointer then it is simple */
11914 if (IS_PTR(type) && !IS_FUNC(type->next)) {
11915 p_type = DCL_TYPE(type);
11918 /* we have to go by the storage class */
11919 p_type = PTR_TYPE(SPEC_OCLS(etype));
11921 /* if (SPEC_OCLS(etype)->codesp ) { */
11922 /* p_type = CPOINTER ; */
11925 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11926 /* p_type = FPOINTER ; */
11928 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11929 /* p_type = PPOINTER ; */
11931 /* if (SPEC_OCLS(etype) == idata ) */
11932 /* p_type = IPOINTER ; */
11934 /* p_type = POINTER ; */
11937 /* now that we have the pointer type we assign
11938 the pointer values */
11943 genNearPointerSet (right,result,ic);
11947 genPagedPointerSet (right,result,ic);
11951 genFarPointerSet (right,result,ic);
11955 genGenPointerSet (right,result,ic);
11959 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11960 "genPointerSet: illegal pointer type");
11964 /*-----------------------------------------------------------------*/
11965 /* genIfx - generate code for Ifx statement */
11966 /*-----------------------------------------------------------------*/
11967 static void genIfx (iCode *ic, iCode *popIc)
11969 operand *cond = IC_COND(ic);
11974 pic16_aopOp(cond,ic,FALSE);
11976 /* get the value into acc */
11977 if (AOP_TYPE(cond) != AOP_CRY)
11978 pic16_toBoolean(cond);
11981 /* the result is now in the accumulator */
11982 pic16_freeAsmop(cond,NULL,ic,TRUE);
11984 /* if there was something to be popped then do it */
11988 /* if the condition is a bit variable */
11989 if (isbit && IS_ITEMP(cond) &&
11991 genIfxJump(ic,SPIL_LOC(cond)->rname);
11992 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
11994 if (isbit && !IS_ITEMP(cond))
11995 genIfxJump(ic,OP_SYMBOL(cond)->rname);
11997 genIfxJump(ic,"a");
12002 /*-----------------------------------------------------------------*/
12003 /* genAddrOf - generates code for address of */
12004 /*-----------------------------------------------------------------*/
12005 static void genAddrOf (iCode *ic)
12007 operand *result, *left;
12009 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12010 pCodeOp *pcop0, *pcop1, *pcop2;
12014 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12016 sym = OP_SYMBOL( IC_LEFT(ic) );
12019 /* get address of symbol on stack */
12020 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12022 fprintf(stderr, "%s:%d symbol %s on stack offset %d\n", __FILE__, __LINE__,
12023 OP_SYMBOL(left)->name, OP_SYMBOL(left)->stack);
12026 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
12027 pic16_popCopyReg(&pic16_pc_fsr2l),
12028 pic16_popGet(AOP(result), 0)));
12029 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
12030 pic16_popCopyReg(&pic16_pc_fsr2h),
12031 pic16_popGet(AOP(result), 1)));
12033 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( OP_SYMBOL( IC_LEFT(ic))->stack ) /*+ _G.stack_lat*/);
12034 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result), 0));
12036 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 1));
12041 // if(pic16_debug_verbose) {
12042 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12043 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12046 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12047 size = AOP_SIZE(IC_RESULT(ic));
12050 /* Assume that what we want the address of is in data space
12051 * since there is no stack on the PIC, yet! -- VR */
12053 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12054 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12055 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12058 pic16_emitpcode(POC_MOVLW, pcop0);
12059 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12060 pic16_emitpcode(POC_MOVLW, pcop1);
12061 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12062 pic16_emitpcode(POC_MOVLW, pcop2);
12063 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12066 pic16_emitpcode(POC_MOVLW, pcop0);
12067 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12068 pic16_emitpcode(POC_MOVLW, pcop1);
12069 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12071 pic16_emitpcode(POC_MOVLW, pcop0);
12072 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12075 pic16_freeAsmop(left, NULL, ic, FALSE);
12077 pic16_freeAsmop(result,NULL,ic,TRUE);
12082 /*-----------------------------------------------------------------*/
12083 /* genFarFarAssign - assignment when both are in far space */
12084 /*-----------------------------------------------------------------*/
12085 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12087 int size = AOP_SIZE(right);
12090 /* first push the right side on to the stack */
12092 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12094 pic16_emitcode ("push","acc");
12097 pic16_freeAsmop(right,NULL,ic,FALSE);
12098 /* now assign DPTR to result */
12099 pic16_aopOp(result,ic,FALSE);
12100 size = AOP_SIZE(result);
12102 pic16_emitcode ("pop","acc");
12103 pic16_aopPut(AOP(result),"a",--offset);
12105 pic16_freeAsmop(result,NULL,ic,FALSE);
12110 /*-----------------------------------------------------------------*/
12111 /* genAssign - generate code for assignment */
12112 /*-----------------------------------------------------------------*/
12113 static void genAssign (iCode *ic)
12115 operand *result, *right;
12116 int size, offset,know_W;
12117 unsigned long lit = 0L;
12119 result = IC_RESULT(ic);
12120 right = IC_RIGHT(ic) ;
12124 /* if they are the same */
12125 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12128 /* reversed order operands are aopOp'ed so that result operand
12129 * is effective in case right is a stack symbol. This maneauver
12130 * allows to use the _G.resDirect flag later */
12131 pic16_aopOp(result,ic,TRUE);
12132 pic16_aopOp(right,ic,FALSE);
12134 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12136 /* if they are the same registers */
12137 if (pic16_sameRegs(AOP(right),AOP(result)))
12140 /* if the result is a bit */
12141 if (AOP_TYPE(result) == AOP_CRY) {
12142 /* if the right size is a literal then
12143 we know what the value is */
12144 if (AOP_TYPE(right) == AOP_LIT) {
12146 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12147 pic16_popGet(AOP(result),0));
12149 if (((int) operandLitValue(right)))
12150 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12151 AOP(result)->aopu.aop_dir,
12152 AOP(result)->aopu.aop_dir);
12154 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12155 AOP(result)->aopu.aop_dir,
12156 AOP(result)->aopu.aop_dir);
12160 /* the right is also a bit variable */
12161 if (AOP_TYPE(right) == AOP_CRY) {
12162 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12163 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12164 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12166 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12167 AOP(result)->aopu.aop_dir,
12168 AOP(result)->aopu.aop_dir);
12169 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12170 AOP(right)->aopu.aop_dir,
12171 AOP(right)->aopu.aop_dir);
12172 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12173 AOP(result)->aopu.aop_dir,
12174 AOP(result)->aopu.aop_dir);
12178 /* we need to or */
12179 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12180 pic16_toBoolean(right);
12182 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12183 //pic16_aopPut(AOP(result),"a",0);
12187 /* bit variables done */
12189 size = AOP_SIZE(result);
12192 if(AOP_TYPE(right) == AOP_LIT) {
12193 if(!IS_FLOAT(operandType( right )))
12194 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12197 unsigned long lit_int;
12201 /* take care if literal is a float */
12202 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12203 lit = info.lit_int;
12207 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12208 // sizeof(unsigned long int), sizeof(float));
12210 if(AOP_TYPE(right) != AOP_LIT
12211 && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12212 && !IS_FUNC(OP_SYM_TYPE(right))
12214 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12215 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12217 // set up table pointer
12218 if(is_LitOp(right)) {
12219 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12220 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12221 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12222 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12223 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12224 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12225 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12227 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12228 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12229 pic16_popCopyReg(&pic16_pc_tblptrl)));
12230 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12231 pic16_popCopyReg(&pic16_pc_tblptrh)));
12232 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12233 pic16_popCopyReg(&pic16_pc_tblptru)));
12236 size = min(AOP_SIZE(right), AOP_SIZE(result));
12238 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12239 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12240 pic16_popGet(AOP(result),offset)));
12244 if(AOP_SIZE(result) > AOP_SIZE(right)) {
12245 size = AOP_SIZE(result) - AOP_SIZE(right);
12247 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12257 /* VR - What is this?! */
12258 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12259 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12260 if(aopIdx(AOP(result),0) == 4) {
12262 /* this is a workaround to save value of right into wreg too,
12263 * value of wreg is going to be used later */
12264 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12265 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12266 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12270 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12276 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12277 if(AOP_TYPE(right) == AOP_LIT) {
12279 if(know_W != (lit&0xff))
12280 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12282 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12284 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12288 } else if (AOP_TYPE(right) == AOP_CRY) {
12289 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12291 // debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12292 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
12293 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12295 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12296 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12297 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12299 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12301 if(!_G.resDirect) /* use this aopForSym feature */
12302 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12309 pic16_freeAsmop (right,NULL,ic,FALSE);
12310 pic16_freeAsmop (result,NULL,ic,TRUE);
12313 /*-----------------------------------------------------------------*/
12314 /* genJumpTab - generates code for jump table */
12315 /*-----------------------------------------------------------------*/
12316 static void genJumpTab (iCode *ic)
12321 pCodeOp *jt_offs_hi;
12326 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12327 /* get the condition into accumulator */
12328 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12330 /* multiply by three */
12331 pic16_emitcode("add","a,acc");
12332 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12334 jtab = newiTempLabel(NULL);
12335 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12336 pic16_emitcode("jmp","@a+dptr");
12337 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12340 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12341 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12343 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12344 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12345 pic16_emitpLabel(jtab->key);
12349 jt_offs = pic16_popGetTempReg(0);
12350 jt_offs_hi = pic16_popGetTempReg(1);
12351 jt_label = pic16_popGetLabel (jtab->key);
12352 //fprintf (stderr, "Creating jump table...\n");
12354 // calculate offset into jump table (idx * sizeof (GOTO))
12355 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12356 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12357 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12358 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12359 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12360 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12361 pic16_emitpcode(POC_MOVWF , jt_offs);
12363 // prepare PCLATx (set to first entry in jump table)
12364 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12365 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12366 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12367 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12368 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12370 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12371 pic16_emitpcode(POC_ADDWF , jt_offs);
12372 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12373 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12375 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12377 // release temporaries and prepare jump into table (new PCL --> WREG)
12378 pic16_emitpcode(POC_MOVFW , jt_offs);
12379 pic16_popReleaseTempReg (jt_offs_hi, 1);
12380 pic16_popReleaseTempReg (jt_offs, 0);
12382 // jump into the table
12383 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12385 pic16_emitpLabelFORCE(jtab->key);
12388 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12390 /* now generate the jump labels */
12391 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12392 jtab = setNextItem(IC_JTLABELS(ic))) {
12393 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12394 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12400 /*-----------------------------------------------------------------*/
12401 /* genMixedOperation - gen code for operators between mixed types */
12402 /*-----------------------------------------------------------------*/
12404 TSD - Written for the PIC port - but this unfortunately is buggy.
12405 This routine is good in that it is able to efficiently promote
12406 types to different (larger) sizes. Unfortunately, the temporary
12407 variables that are optimized out by this routine are sometimes
12408 used in other places. So until I know how to really parse the
12409 iCode tree, I'm going to not be using this routine :(.
12411 static int genMixedOperation (iCode *ic)
12414 operand *result = IC_RESULT(ic);
12415 sym_link *ctype = operandType(IC_LEFT(ic));
12416 operand *right = IC_RIGHT(ic);
12422 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12424 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12430 nextright = IC_RIGHT(nextic);
12431 nextleft = IC_LEFT(nextic);
12432 nextresult = IC_RESULT(nextic);
12434 pic16_aopOp(right,ic,FALSE);
12435 pic16_aopOp(result,ic,FALSE);
12436 pic16_aopOp(nextright, nextic, FALSE);
12437 pic16_aopOp(nextleft, nextic, FALSE);
12438 pic16_aopOp(nextresult, nextic, FALSE);
12440 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12442 operand *t = right;
12446 pic16_emitcode(";remove right +","");
12448 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12450 operand *t = right;
12454 pic16_emitcode(";remove left +","");
12458 big = AOP_SIZE(nextleft);
12459 small = AOP_SIZE(nextright);
12461 switch(nextic->op) {
12464 pic16_emitcode(";optimize a +","");
12465 /* if unsigned or not an integral type */
12466 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12467 pic16_emitcode(";add a bit to something","");
12470 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12472 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12473 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12474 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12476 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12484 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12485 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12486 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12489 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12491 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12492 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12493 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12494 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12495 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12498 pic16_emitcode("rlf","known_zero,w");
12505 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12506 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12507 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12509 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12519 pic16_freeAsmop(right,NULL,ic,TRUE);
12520 pic16_freeAsmop(result,NULL,ic,TRUE);
12521 pic16_freeAsmop(nextright,NULL,ic,TRUE);
12522 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12524 nextic->generated = 1;
12531 /*-----------------------------------------------------------------*/
12532 /* genCast - gen code for casting */
12533 /*-----------------------------------------------------------------*/
12534 static void genCast (iCode *ic)
12536 operand *result = IC_RESULT(ic);
12537 sym_link *ctype = operandType(IC_LEFT(ic));
12538 sym_link *rtype = operandType(IC_RIGHT(ic));
12539 sym_link *restype = operandType(IC_RESULT(ic));
12540 operand *right = IC_RIGHT(ic);
12546 /* if they are equivalent then do nothing */
12547 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12550 pic16_aopOp(right,ic,FALSE) ;
12551 pic16_aopOp(result,ic,FALSE);
12553 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12556 /* if the result is a bit */
12557 if (AOP_TYPE(result) == AOP_CRY) {
12559 /* if the right size is a literal then
12560 * we know what the value is */
12561 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12563 if (AOP_TYPE(right) == AOP_LIT) {
12564 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12565 pic16_popGet(AOP(result),0));
12567 if (((int) operandLitValue(right)))
12568 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12569 AOP(result)->aopu.aop_dir,
12570 AOP(result)->aopu.aop_dir);
12572 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12573 AOP(result)->aopu.aop_dir,
12574 AOP(result)->aopu.aop_dir);
12578 /* the right is also a bit variable */
12579 if (AOP_TYPE(right) == AOP_CRY) {
12581 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12583 pic16_emitcode("clrc","");
12584 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12585 AOP(right)->aopu.aop_dir,
12586 AOP(right)->aopu.aop_dir);
12587 pic16_aopPut(AOP(result),"c",0);
12591 /* we need to or */
12592 if (AOP_TYPE(right) == AOP_REG) {
12593 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12594 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12595 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12597 pic16_toBoolean(right);
12598 pic16_aopPut(AOP(result),"a",0);
12602 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12605 size = AOP_SIZE(result);
12607 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12609 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
12610 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12611 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12614 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
12619 if(IS_BITFIELD(getSpec(restype))
12620 && IS_BITFIELD(getSpec(rtype))) {
12621 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12624 /* if they are the same size : or less */
12625 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12627 /* if they are in the same place */
12628 if (pic16_sameRegs(AOP(right),AOP(result)))
12631 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12633 if (IS_PTR_CONST(rtype))
12635 if (IS_CODEPTR(rtype))
12637 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12640 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12642 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12644 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12647 if(AOP_TYPE(right) == AOP_IMMD) {
12648 pCodeOp *pcop0, *pcop1, *pcop2;
12649 symbol *sym = OP_SYMBOL( right );
12651 size = AOP_SIZE(result);
12653 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12655 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12657 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12660 pic16_emitpcode(POC_MOVLW, pcop0);
12661 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12662 pic16_emitpcode(POC_MOVLW, pcop1);
12663 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12664 pic16_emitpcode(POC_MOVLW, pcop2);
12665 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12668 pic16_emitpcode(POC_MOVLW, pcop0);
12669 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12670 pic16_emitpcode(POC_MOVLW, pcop1);
12671 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12673 pic16_emitpcode(POC_MOVLW, pcop0);
12674 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12678 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12679 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12680 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12681 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12682 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12683 if(AOP_SIZE(result) <2)
12684 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12686 /* if they in different places then copy */
12687 size = AOP_SIZE(result);
12690 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12691 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12698 /* if the result is of type pointer */
12699 if (IS_PTR(ctype)) {
12701 sym_link *type = operandType(right);
12702 sym_link *etype = getSpec(type);
12704 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
12706 /* pointer to generic pointer */
12707 if (IS_GENPTR(ctype)) {
12711 p_type = DCL_TYPE(type);
12713 /* we have to go by the storage class */
12714 p_type = PTR_TYPE(SPEC_OCLS(etype));
12716 /* if (SPEC_OCLS(etype)->codesp ) */
12717 /* p_type = CPOINTER ; */
12719 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12720 /* p_type = FPOINTER ; */
12722 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12723 /* p_type = PPOINTER; */
12725 /* if (SPEC_OCLS(etype) == idata ) */
12726 /* p_type = IPOINTER ; */
12728 /* p_type = POINTER ; */
12731 /* the first two bytes are known */
12732 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
12733 size = GPTRSIZE - 1;
12736 if(offset < AOP_SIZE(right)) {
12737 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
12738 mov2f(AOP(result), AOP(right), offset);
12740 if ((AOP_TYPE(right) == AOP_PCODE) &&
12741 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12742 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12743 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12746 pic16_aopPut(AOP(result),
12747 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12752 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
12755 /* the last byte depending on type */
12759 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
12760 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
12761 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
12765 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12769 pic16_emitcode(";BUG!? ","%d",__LINE__);
12773 pic16_emitcode(";BUG!? ","%d",__LINE__);
12778 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12782 /* this should never happen */
12783 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
12784 "got unknown pointer type");
12787 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
12791 /* just copy the pointers */
12792 size = AOP_SIZE(result);
12795 pic16_aopPut(AOP(result),
12796 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12805 /* so we now know that the size of destination is greater
12806 than the size of the source.
12807 Now, if the next iCode is an operator then we might be
12808 able to optimize the operation without performing a cast.
12810 if(genMixedOperation(ic))
12813 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12815 /* we move to result for the size of source */
12816 size = AOP_SIZE(right);
12819 mov2f(AOP(result), AOP(right), offset);
12823 /* now depending on the sign of the destination */
12824 size = AOP_SIZE(result) - AOP_SIZE(right);
12825 /* if unsigned or not an integral type */
12826 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
12828 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
12830 /* we need to extend the sign :( */
12833 /* Save one instruction of casting char to int */
12834 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12835 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12836 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset));
12838 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
12841 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12843 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12845 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
12848 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
12853 pic16_freeAsmop(right,NULL,ic,TRUE);
12854 pic16_freeAsmop(result,NULL,ic,TRUE);
12858 /*-----------------------------------------------------------------*/
12859 /* genDjnz - generate decrement & jump if not zero instrucion */
12860 /*-----------------------------------------------------------------*/
12861 static int genDjnz (iCode *ic, iCode *ifx)
12863 symbol *lbl, *lbl1;
12864 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12869 /* if the if condition has a false label
12870 then we cannot save */
12874 /* if the minus is not of the form
12876 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
12877 !IS_OP_LITERAL(IC_RIGHT(ic)))
12880 if (operandLitValue(IC_RIGHT(ic)) != 1)
12883 /* if the size of this greater than one then no
12885 if (getSize(operandType(IC_RESULT(ic))) > 1)
12888 /* otherwise we can save BIG */
12889 lbl = newiTempLabel(NULL);
12890 lbl1= newiTempLabel(NULL);
12892 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
12894 if (IS_AOP_PREG(IC_RESULT(ic))) {
12895 pic16_emitcode("dec","%s",
12896 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
12897 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
12898 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
12902 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
12903 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
12905 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
12906 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
12910 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
12911 ifx->generated = 1;
12915 /*-----------------------------------------------------------------*/
12916 /* genReceive - generate code for a receive iCode */
12917 /*-----------------------------------------------------------------*/
12918 static void genReceive (iCode *ic)
12924 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
12925 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
12927 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
12929 if (isOperandInFarSpace(IC_RESULT(ic))
12930 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
12931 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
12933 int size = getSize(operandType(IC_RESULT(ic)));
12934 int offset = pic16_fReturnSizePic - size;
12938 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
12939 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
12943 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
12945 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
12946 size = AOP_SIZE(IC_RESULT(ic));
12949 pic16_emitcode ("pop","acc");
12950 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
12953 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
12956 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
12958 assignResultValue(IC_RESULT(ic), 0);
12961 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
12964 /*-----------------------------------------------------------------*/
12965 /* genDummyRead - generate code for dummy read of volatiles */
12966 /*-----------------------------------------------------------------*/
12968 genDummyRead (iCode * ic)
12970 pic16_emitcode ("; genDummyRead","");
12971 pic16_emitcode ("; not implemented","");
12976 /*-----------------------------------------------------------------*/
12977 /* genpic16Code - generate code for pic16 based controllers */
12978 /*-----------------------------------------------------------------*/
12980 * At this point, ralloc.c has gone through the iCode and attempted
12981 * to optimize in a way suitable for a PIC. Now we've got to generate
12982 * PIC instructions that correspond to the iCode.
12984 * Once the instructions are generated, we'll pass through both the
12985 * peep hole optimizer and the pCode optimizer.
12986 *-----------------------------------------------------------------*/
12988 void genpic16Code (iCode *lic)
12993 lineHead = lineCurr = NULL;
12995 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
12996 pic16_addpBlock(pb);
12999 /* if debug information required */
13000 if (options.debug && currFunc) {
13002 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13007 for (ic = lic ; ic ; ic = ic->next ) {
13009 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
13010 if ( cln != ic->lineno ) {
13011 if ( options.debug ) {
13012 debugFile->writeCLine (ic);
13015 if(!options.noCcodeInAsm) {
13016 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13017 printCLine(ic->filename, ic->lineno)));
13023 if(options.iCodeInAsm) {
13026 /* insert here code to print iCode as comment */
13027 l = Safe_strdup(printILine(ic));
13028 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13031 /* if the result is marked as
13032 * spilt and rematerializable or code for
13033 * this has already been generated then
13035 if (resultRemat(ic) || ic->generated )
13038 /* depending on the operation */
13057 /* IPOP happens only when trying to restore a
13058 * spilt live range, if there is an ifx statement
13059 * following this pop then the if statement might
13060 * be using some of the registers being popped which
13061 * would destroy the contents of the register so
13062 * we need to check for this condition and handle it */
13064 && ic->next->op == IFX
13065 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13066 genIfx (ic->next,ic);
13084 genEndFunction (ic);
13100 pic16_genPlus (ic) ;
13104 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13105 pic16_genMinus (ic);
13121 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13125 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13131 /* note these two are xlated by algebraic equivalence
13132 * during parsing SDCC.y */
13133 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13134 "got '>=' or '<=' shouldn't have come here");
13138 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13150 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13154 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13158 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13182 genRightShift (ic);
13185 case GET_VALUE_AT_ADDRESS:
13190 if (POINTER_SET(ic))
13217 addSet(&_G.sendSet,ic);
13220 case DUMMY_READ_VOLATILE:
13230 /* now we are ready to call the
13231 peep hole optimizer */
13232 if (!options.nopeep)
13233 peepHole (&lineHead);
13235 /* now do the actual printing */
13236 printLine (lineHead, codeOutFile);
13239 DFPRINTF((stderr,"printing pBlock\n\n"));
13240 pic16_printpBlock(stdout,pb);