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)
10 This program is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the
12 Free Software Foundation; either version 2, or (at your option) any
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 In other words, you are welcome to use, share and improve this program.
25 You are forbidden to forbid anyone else to use, share and improve
26 what you give them. Help stamp out software-hoarding!
29 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
30 Made everything static
31 -------------------------------------------------------------------------*/
37 #include "SDCCglobl.h"
41 #include "SDCCpeeph.h"
49 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
50 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
51 void pic16_genMult8X8_8 (operand *, operand *,operand *);
52 pCode *pic16_AssembleLine(char *line, int peeps);
53 extern void pic16_printpBlock(FILE *of, pBlock *pb);
54 static asmop *newAsmop (short type);
55 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset);
56 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
57 static void mov2w (asmop *aop, int offset);
58 static int aopIdx (asmop *aop, int offset);
60 static int labelOffset=0;
61 extern int pic16_debug_verbose;
62 static int optimized_for_speed = 0;
68 /* max_key keeps track of the largest label number used in
69 a function. This is then used to adjust the label offset
70 for the next function.
73 static int GpsuedoStkPtr=0;
75 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
76 unsigned int pic16aopLiteral (value *val, int offset);
77 const char *pic16_AopType(short type);
78 static iCode *ifxForOp ( operand *op, iCode *ic );
80 void pic16_pushpCodeOp(pCodeOp *pcop);
81 void pic16_poppCodeOp(pCodeOp *pcop);
85 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
87 /* this is the down and dirty file with all kinds of
88 kludgy & hacky stuff. This is what it is all about
89 CODE GENERATION for a specific MCU . some of the
90 routines may be reusable, will have to see */
92 static char *zero = "#0x00";
93 static char *one = "#0x01";
94 static char *spname = "sp";
98 * Function return value policy (MSB-->LSB):
100 * 16 bits -> PRODL:WREG
101 * 24 bits -> PRODH:PRODL:WREG
102 * 32 bits -> FSR0L:PRODH:PRODL:WREG
103 * >32 bits -> on stack, and FSR0 points to the beginning
108 char *fReturnpic16[] = {"temp1","temp2","temp3","temp4" };
109 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
110 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
111 static char **fReturn = fReturnpic16;
113 static char *accUse[] = {"WREG"};
115 //static short rbank = -1;
127 /* Resolved ifx structure. This structure stores information
128 about an iCode ifx that makes it easier to generate code.
130 typedef struct resolvedIfx {
131 symbol *lbl; /* pointer to a label */
132 int condition; /* true or false ifx */
133 int generated; /* set true when the code associated with the ifx
137 extern int pic16_ptrRegReq ;
138 extern int pic16_nRegs;
139 extern FILE *codeOutFile;
140 static void saverbank (int, iCode *,bool);
142 static lineNode *lineHead = NULL;
143 static lineNode *lineCurr = NULL;
145 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
146 0xE0, 0xC0, 0x80, 0x00};
147 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
148 0x07, 0x03, 0x01, 0x00};
152 /*-----------------------------------------------------------------*/
153 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
154 /* exponent of 2 is returned, otherwise -1 is */
156 /* note that this is similar to the function `powof2' in SDCCsymt */
160 /*-----------------------------------------------------------------*/
161 static int my_powof2 (unsigned long num)
164 if( (num & (num-1)) == 0) {
177 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
179 DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
181 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
182 ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
183 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
184 ((left) ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
185 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
186 ((right) ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
187 ((result) ? AOP_SIZE(result) : 0));
190 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
193 DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
195 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
196 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
197 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
198 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
199 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
200 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
204 void pic16_emitpcomment (char *fmt, ...)
207 char lb[INITIAL_INLINEASM];
213 vsprintf(lb+1,fmt,ap);
215 while (isspace(*lbp)) lbp++;
218 lineCurr = (lineCurr ?
219 connectLine(lineCurr,newLineNode(lb)) :
220 (lineHead = newLineNode(lb)));
221 lineCurr->isInline = _G.inLine;
222 lineCurr->isDebug = _G.debugLine;
224 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
227 // fprintf(stderr, "%s\n", lb);
230 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
233 char lb[INITIAL_INLINEASM];
236 if(!pic16_debug_verbose)
243 sprintf(lb,"%s\t",inst);
245 sprintf(lb,"%s",inst);
246 vsprintf(lb+(strlen(lb)),fmt,ap);
250 while (isspace(*lbp)) lbp++;
253 lineCurr = (lineCurr ?
254 connectLine(lineCurr,newLineNode(lb)) :
255 (lineHead = newLineNode(lb)));
256 lineCurr->isInline = _G.inLine;
257 lineCurr->isDebug = _G.debugLine;
259 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
262 // fprintf(stderr, "%s\n", lb);
265 void pic16_emitpLabel(int key)
267 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+labelOffset));
270 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
274 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
276 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
278 // fprintf(stderr, "%s\n", pcop->name);
281 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
284 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
290 #define pic16_emitcode DEBUGpic16_emitcode
292 /*-----------------------------------------------------------------*/
293 /* pic16_emitcode - writes the code into a file : for now it is simple */
294 /*-----------------------------------------------------------------*/
295 void pic16_emitcode (char *inst,char *fmt, ...)
298 char lb[INITIAL_INLINEASM];
305 sprintf(lb,"%s\t",inst);
307 sprintf(lb,"%s",inst);
308 vsprintf(lb+(strlen(lb)),fmt,ap);
312 while (isspace(*lbp)) lbp++;
315 lineCurr = (lineCurr ?
316 connectLine(lineCurr,newLineNode(lb)) :
317 (lineHead = newLineNode(lb)));
318 lineCurr->isInline = _G.inLine;
319 lineCurr->isDebug = _G.debugLine;
321 // VR fprintf(stderr, "lb = <%s>\n", lbp);
323 // if(pic16_debug_verbose)
324 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
331 /*-----------------------------------------------------------------*/
332 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
333 /*-----------------------------------------------------------------*/
334 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
336 bool r0iu = FALSE , r1iu = FALSE;
337 bool r0ou = FALSE , r1ou = FALSE;
339 //fprintf(stderr, "%s:%d: getting free ptr from ic = %c\n", __FUNCTION__, __LINE__, ic->op);
341 /* the logic: if r0 & r1 used in the instruction
342 then we are in trouble otherwise */
344 /* first check if r0 & r1 are used by this
345 instruction, in which case we are in trouble */
346 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
347 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
352 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
353 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
355 /* if no usage of r0 then return it */
356 if (!r0iu && !r0ou) {
357 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
358 (*aopp)->type = AOP_R0;
360 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
363 /* if no usage of r1 then return it */
364 if (!r1iu && !r1ou) {
365 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
366 (*aopp)->type = AOP_R1;
368 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
371 /* now we know they both have usage */
372 /* if r0 not used in this instruction */
374 /* push it if not already pushed */
376 //pic16_emitcode ("push","%s",
377 // pic16_regWithIdx(R0_IDX)->dname);
381 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
382 (*aopp)->type = AOP_R0;
384 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
387 /* if r1 not used then */
390 /* push it if not already pushed */
392 //pic16_emitcode ("push","%s",
393 // pic16_regWithIdx(R1_IDX)->dname);
397 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
398 (*aopp)->type = AOP_R1;
399 return pic16_regWithIdx(R1_IDX);
403 /* I said end of world but not quite end of world yet */
404 /* if this is a result then we can push it on the stack*/
406 (*aopp)->type = AOP_STK;
410 /* other wise this is true end of the world */
411 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
412 "getFreePtr should never reach here");
416 /*-----------------------------------------------------------------*/
417 /* newAsmop - creates a new asmOp */
418 /*-----------------------------------------------------------------*/
419 static asmop *newAsmop (short type)
423 aop = Safe_calloc(1,sizeof(asmop));
428 static void genSetDPTR(int n)
432 pic16_emitcode(";", "Select standard DPTR");
433 pic16_emitcode("mov", "dps, #0x00");
437 pic16_emitcode(";", "Select alternate DPTR");
438 pic16_emitcode("mov", "dps, #0x01");
442 /*-----------------------------------------------------------------*/
443 /* resolveIfx - converts an iCode ifx into a form more useful for */
444 /* generating code */
445 /*-----------------------------------------------------------------*/
446 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
451 // DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
453 resIfx->condition = 1; /* assume that the ifx is true */
454 resIfx->generated = 0; /* indicate that the ifx has not been used */
457 resIfx->lbl = newiTempLabel(NULL); /* oops, there is no ifx. so create a label */
459 DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
460 __FUNCTION__,__LINE__,resIfx->lbl->key);
464 resIfx->lbl = IC_TRUE(ifx);
466 resIfx->lbl = IC_FALSE(ifx);
467 resIfx->condition = 0;
471 DEBUGpic16_emitcode("; ***","ifx true is non-null");
473 DEBUGpic16_emitcode("; ***","ifx false is non-null");
477 // DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
481 /*-----------------------------------------------------------------*/
482 /* pointerCode - returns the code for a pointer type */
483 /*-----------------------------------------------------------------*/
484 static int pointerCode (sym_link *etype)
487 return PTR_TYPE(SPEC_OCLS(etype));
491 /*-----------------------------------------------------------------*/
492 /* aopForSym - for a true symbol */
493 /*-----------------------------------------------------------------*/
494 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
497 memmap *space= SPEC_OCLS(sym->etype);
499 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
500 /* if already has one */
502 DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
506 /* assign depending on the storage class */
507 /* if it is on the stack or indirectly addressable */
508 /* space we need to assign either r0 or r1 to it */
509 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
511 DEBUGpic16_emitcode("; ***", "sum->onStack || sym->iaccess");
513 sym->aop = aop = newAsmop(0);
514 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
515 aop->size = getSize(sym->type);
517 /* now assign the address of the variable to
518 the pointer register */
519 if (aop->type != AOP_STK) {
523 pic16_emitcode("push","acc");
525 pic16_emitcode("mov","a,_bp");
526 pic16_emitcode("add","a,#0x%02x",
528 ((char)(sym->stack - _G.nRegsSaved )) :
529 ((char)sym->stack)) & 0xff);
530 pic16_emitcode("mov","%s,a",
531 aop->aopu.aop_ptr->name);
534 pic16_emitcode("pop","acc");
536 pic16_emitcode("mov","%s,#%s",
537 aop->aopu.aop_ptr->name,
539 aop->paged = space->paged;
541 aop->aopu.aop_stk = sym->stack;
545 if (sym->onStack && options.stack10bit)
547 /* It's on the 10 bit stack, which is located in
551 //DEBUGpic16_emitcode(";","%d",__LINE__);
554 pic16_emitcode("push","acc");
556 pic16_emitcode("mov","a,_bp");
557 pic16_emitcode("add","a,#0x%02x",
559 ((char)(sym->stack - _G.nRegsSaved )) :
560 ((char)sym->stack)) & 0xff);
563 pic16_emitcode ("mov","dpx1,#0x40");
564 pic16_emitcode ("mov","dph1,#0x00");
565 pic16_emitcode ("mov","dpl1, a");
569 pic16_emitcode("pop","acc");
571 sym->aop = aop = newAsmop(AOP_DPTR2);
572 aop->size = getSize(sym->type);
576 //DEBUGpic16_emitcode(";","%d",__LINE__);
577 /* if in bit space */
578 if (IN_BITSPACE(space)) {
579 sym->aop = aop = newAsmop (AOP_CRY);
580 aop->aopu.aop_dir = sym->rname ;
581 aop->size = getSize(sym->type);
582 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
585 /* if it is in direct space */
586 if (IN_DIRSPACE(space)) {
587 sym->aop = aop = newAsmop (AOP_DIR);
588 aop->aopu.aop_dir = sym->rname ;
589 aop->size = getSize(sym->type);
590 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
591 pic16_allocDirReg( IC_LEFT(ic) );
596 /* special case for a function */
597 if (IS_FUNC(sym->type)) {
598 sym->aop = aop = newAsmop(AOP_IMMD);
599 //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
600 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
601 strcpy(aop->aopu.aop_immd,sym->rname);
602 aop->size = FPTRSIZE;
603 DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
609 /* only remaining is far space */
610 /* in which case DPTR gets the address */
611 sym->aop = aop = newAsmop(AOP_PCODE);
613 /* change the next if to 1 to revert to good old immediate code */
614 if(IN_CODESPACE(space)) {
615 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
616 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
617 PCOI(aop->aopu.pcop)->index = 0;
619 /* try to allocate via direct register */
620 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset); // Patch 8
621 // aop->size = getSize( sym->type );
624 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
625 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
628 if(!pic16_allocDirReg (IC_LEFT(ic)))
632 if(IN_DIRSPACE( space ))
634 else if(IN_CODESPACE( space ))
635 aop->size = FPTRSIZE;
636 else if(IC_LEFT(ic)) aop->size = AOP_SIZE( IC_LEFT(ic) );
637 else if(IC_RIGHT(ic)) aop->size = AOP_SIZE( IC_RIGHT(ic) );
642 DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
644 /* if it is in code space */
645 if (IN_CODESPACE(space))
651 /*-----------------------------------------------------------------*/
652 /* aopForRemat - rematerialzes an object */
653 /*-----------------------------------------------------------------*/
654 static asmop *aopForRemat (operand *op) // x symbol *sym)
656 symbol *sym = OP_SYMBOL(op);
657 iCode *ic = NULL, *oldic;
658 asmop *aop = newAsmop(AOP_PCODE);
664 ic = sym->rematiCode;
666 DEBUGpic16_emitcode(";","%s %d",__FUNCTION__,__LINE__);
668 if(IS_OP_POINTER(op)) {
669 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
675 // pic16_emitpcomment("ic: %s\n", printILine(ic));
678 val += (int) operandLitValue(IC_RIGHT(ic));
679 } else if (ic->op == '-') {
680 val -= (int) operandLitValue(IC_RIGHT(ic));
684 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
687 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
689 if(!op->isaddr)viaimmd++; else viaimmd=0;
691 /* set the following if to 1 to revert to good old immediate code */
692 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)))
695 pic16_emitpcomment("%s:%d immediate", __FILE__, __LINE__);
697 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
700 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
702 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
705 PCOI(aop->aopu.pcop)->index = val;
707 pic16_emitpcomment("%s:%d dir", __FILE__, __LINE__);
709 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname, getSize( OP_SYMBOL( IC_LEFT(ic))->type), val);
710 // aop->size = AOP_SIZE( IC_LEFT(ic) );
714 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
715 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
717 val, IS_PTR_CONST(operandType(op)));
719 val, IS_CODEPTR(operandType(op)));
722 // DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
724 pic16_allocDirReg (IC_LEFT(ic));
726 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
732 static int aopIdx (asmop *aop, int offset)
737 if(aop->type != AOP_REG)
740 return aop->aopu.aop_reg[offset]->rIdx;
743 /*-----------------------------------------------------------------*/
744 /* regsInCommon - two operands have some registers in common */
745 /*-----------------------------------------------------------------*/
746 static bool regsInCommon (operand *op1, operand *op2)
751 /* if they have registers in common */
752 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
755 sym1 = OP_SYMBOL(op1);
756 sym2 = OP_SYMBOL(op2);
758 if (sym1->nRegs == 0 || sym2->nRegs == 0)
761 for (i = 0 ; i < sym1->nRegs ; i++) {
766 for (j = 0 ; j < sym2->nRegs ;j++ ) {
770 if (sym2->regs[j] == sym1->regs[i])
778 /*-----------------------------------------------------------------*/
779 /* operandsEqu - equivalent */
780 /*-----------------------------------------------------------------*/
781 static bool operandsEqu ( operand *op1, operand *op2)
785 /* if they not symbols */
786 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
789 sym1 = OP_SYMBOL(op1);
790 sym2 = OP_SYMBOL(op2);
792 /* if both are itemps & one is spilt
793 and the other is not then false */
794 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
795 sym1->isspilt != sym2->isspilt )
798 /* if they are the same */
802 if (strcmp(sym1->rname,sym2->rname) == 0)
806 /* if left is a tmp & right is not */
810 (sym1->usl.spillLoc == sym2))
817 (sym2->usl.spillLoc == sym1))
823 /*-----------------------------------------------------------------*/
824 /* pic16_sameRegs - two asmops have the same registers */
825 /*-----------------------------------------------------------------*/
826 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
833 if (aop1->type != AOP_REG ||
834 aop2->type != AOP_REG )
837 if (aop1->size != aop2->size )
840 for (i = 0 ; i < aop1->size ; i++ )
841 if (aop1->aopu.aop_reg[i] !=
842 aop2->aopu.aop_reg[i] )
848 /*-----------------------------------------------------------------*/
849 /* pic16_aopOp - allocates an asmop for an operand : */
850 /*-----------------------------------------------------------------*/
851 void pic16_aopOp (operand *op, iCode *ic, bool result)
860 // DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
862 /* if this a literal */
863 if (IS_OP_LITERAL(op)) {
864 op->aop = aop = newAsmop(AOP_LIT);
865 aop->aopu.aop_lit = op->operand.valOperand;
866 aop->size = getSize(operandType(op));
871 sym_link *type = operandType(op);
873 if(IS_PTR_CONST(type))
877 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
880 /* if already has a asmop then continue */
884 /* if the underlying symbol has a aop */
885 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
886 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
887 op->aop = OP_SYMBOL(op)->aop;
891 /* if this is a true symbol */
892 if (IS_TRUE_SYMOP(op)) {
893 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
894 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
898 /* this is a temporary : this has
904 e) can be a return use only */
908 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
909 /* if the type is a conditional */
910 if (sym->regType == REG_CND) {
911 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
916 /* if it is spilt then two situations
918 b) has a spill location */
919 if (sym->isspilt || sym->nRegs == 0) {
921 DEBUGpic16_emitcode(";","%d",__LINE__);
922 /* rematerialize it NOW */
925 sym->aop = op->aop = aop =
927 aop->size = getSize(sym->type);
928 //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
935 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
936 aop->size = getSize(sym->type);
937 for ( i = 0 ; i < 1 ; i++ ) {
938 aop->aopu.aop_str[i] = accUse[i];
939 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
941 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
942 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
950 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
951 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
952 //pic16_allocDirReg (IC_LEFT(ic));
953 aop->size = getSize(sym->type);
958 aop = op->aop = sym->aop = newAsmop(AOP_STR);
959 aop->size = getSize(sym->type);
960 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
961 aop->aopu.aop_str[i] = fReturn[i];
963 DEBUGpic16_emitcode(";","%d",__LINE__);
967 /* else spill location */
968 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
969 /* force a new aop if sizes differ */
970 sym->usl.spillLoc->aop = NULL;
972 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
973 __FUNCTION__,__LINE__,
974 sym->usl.spillLoc->rname,
975 sym->rname, sym->usl.spillLoc->offset);
977 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
978 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
979 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
981 sym->usl.spillLoc->offset);
982 aop->size = getSize(sym->type);
988 sym_link *type = operandType(op);
990 if(IS_PTR_CONST(type))
994 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
997 /* must be in a register */
998 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
999 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1000 aop->size = sym->nRegs;
1001 for ( i = 0 ; i < sym->nRegs ;i++)
1002 aop->aopu.aop_reg[i] = sym->regs[i];
1005 /*-----------------------------------------------------------------*/
1006 /* pic16_freeAsmop - free up the asmop given to an operand */
1007 /*----------------------------------------------------------------*/
1008 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1025 /* depending on the asmop type only three cases need work AOP_RO
1026 , AOP_R1 && AOP_STK */
1028 switch (aop->type) {
1032 pic16_emitcode ("pop","ar0");
1036 bitVectUnSetBit(ic->rUsed,R0_IDX);
1042 pic16_emitcode ("pop","ar1");
1046 bitVectUnSetBit(ic->rUsed,R1_IDX);
1052 int stk = aop->aopu.aop_stk + aop->size;
1053 bitVectUnSetBit(ic->rUsed,R0_IDX);
1054 bitVectUnSetBit(ic->rUsed,R1_IDX);
1056 getFreePtr(ic,&aop,FALSE);
1058 if (options.stack10bit)
1060 /* I'm not sure what to do here yet... */
1063 "*** Warning: probably generating bad code for "
1064 "10 bit stack mode.\n");
1068 pic16_emitcode ("mov","a,_bp");
1069 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1070 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1072 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1076 pic16_emitcode("pop","acc");
1077 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1079 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1082 pic16_freeAsmop(op,NULL,ic,TRUE);
1084 pic16_emitcode("pop","ar0");
1089 pic16_emitcode("pop","ar1");
1097 /* all other cases just dealloc */
1101 OP_SYMBOL(op)->aop = NULL;
1102 /* if the symbol has a spill */
1104 SPIL_LOC(op)->aop = NULL;
1109 /*-----------------------------------------------------------------*/
1110 /* pic16_aopGet - for fetching value of the aop */
1111 /*-----------------------------------------------------------------*/
1112 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1117 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1119 /* offset is greater than size then zero */
1120 if (offset > (aop->size - 1) &&
1121 aop->type != AOP_LIT)
1124 /* depending on type */
1125 switch (aop->type) {
1129 DEBUGpic16_emitcode(";","%d",__LINE__);
1130 /* if we need to increment it */
1131 while (offset > aop->coff) {
1132 pic16_emitcode ("inc","%s",aop->aopu.aop_ptr->name);
1136 while (offset < aop->coff) {
1137 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1141 aop->coff = offset ;
1143 pic16_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1144 return (dname ? "acc" : "a");
1146 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1147 rs = Safe_calloc(1,strlen(s)+1);
1153 DEBUGpic16_emitcode(";","%d",__LINE__);
1154 if (aop->type == AOP_DPTR2)
1159 while (offset > aop->coff) {
1160 pic16_emitcode ("inc","dptr");
1164 while (offset < aop->coff) {
1165 pic16_emitcode("lcall","__decdptr");
1171 pic16_emitcode("clr","a");
1172 pic16_emitcode("movc","a,@a+dptr");
1175 pic16_emitcode("movx","a,@dptr");
1178 if (aop->type == AOP_DPTR2)
1183 return (dname ? "acc" : "a");
1188 sprintf (s,"%s",aop->aopu.aop_immd);
1191 sprintf(s,"(%s >> %d)",
1196 aop->aopu.aop_immd);
1197 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1198 rs = Safe_calloc(1,strlen(s)+1);
1204 sprintf(s,"(%s + %d)",
1207 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1209 sprintf(s,"%s",aop->aopu.aop_dir);
1210 rs = Safe_calloc(1,strlen(s)+1);
1216 // return aop->aopu.aop_reg[offset]->dname;
1218 return aop->aopu.aop_reg[offset]->name;
1221 //pic16_emitcode(";","%d",__LINE__);
1222 return aop->aopu.aop_dir;
1225 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1226 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1228 return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1231 sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1232 rs = Safe_calloc(1,strlen(s)+1);
1237 aop->coff = offset ;
1238 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1241 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1243 return aop->aopu.aop_str[offset];
1247 pCodeOp *pcop = aop->aopu.pcop;
1248 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1250 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1251 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1252 sprintf(s,"%s", pcop->name);
1254 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1257 rs = Safe_calloc(1,strlen(s)+1);
1263 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1264 "aopget got unsupported aop->type");
1269 /*-----------------------------------------------------------------*/
1270 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1271 /*-----------------------------------------------------------------*/
1272 pCodeOp *pic16_popGetTempReg(void)
1276 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1277 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1278 PCOR(pcop)->r->wasUsed=1;
1279 PCOR(pcop)->r->isFree=0;
1281 /* push value on stack */
1282 pic16_pushpCodeOp( pcop );
1288 /*-----------------------------------------------------------------*/
1289 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1290 /*-----------------------------------------------------------------*/
1291 void pic16_popReleaseTempReg(pCodeOp *pcop)
1293 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1294 PCOR(pcop)->r->isFree = 1;
1296 pic16_poppCodeOp( pcop );
1299 /*-----------------------------------------------------------------*/
1300 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1301 /*-----------------------------------------------------------------*/
1302 pCodeOp *pic16_popGetLabel(unsigned int key)
1305 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1310 return pic16_newpCodeOpLabel(NULL,key+100+labelOffset);
1313 /*-----------------------------------------------------------------*/
1314 /* pic16_popCopyReg - copy a pcode operator */
1315 /*-----------------------------------------------------------------*/
1316 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1320 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1321 pcor->pcop.type = pc->pcop.type;
1323 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1324 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1326 pcor->pcop.name = NULL;
1329 pcor->rIdx = pc->rIdx;
1332 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1337 /*-----------------------------------------------------------------*/
1338 /* pic16_popGetLit - asm operator to pcode operator conversion */
1339 /*-----------------------------------------------------------------*/
1340 pCodeOp *pic16_popGetLit(unsigned int lit)
1342 return pic16_newpCodeOpLit(lit);
1345 /*-----------------------------------------------------------------*/
1346 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1347 /*-----------------------------------------------------------------*/
1348 pCodeOp *pic16_popGetLit2(unsigned int lit, pCodeOp *arg2)
1350 return pic16_newpCodeOpLit2(lit, arg2);
1354 /*-----------------------------------------------------------------*/
1355 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1356 /*-----------------------------------------------------------------*/
1357 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1359 return pic16_newpCodeOpImmd(name, offset,index, 0);
1363 /*-----------------------------------------------------------------*/
1364 /* pic16_popGet - asm operator to pcode operator conversion */
1365 /*-----------------------------------------------------------------*/
1366 pCodeOp *pic16_popGetWithString(char *str)
1372 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1376 pcop = pic16_newpCodeOp(str,PO_STR);
1381 /*-----------------------------------------------------------------*/
1382 /* pic16_popRegFromString - */
1383 /*-----------------------------------------------------------------*/
1384 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset)
1387 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1388 pcop->type = PO_DIR;
1390 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1391 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1396 pcop->name = Safe_calloc(1,strlen(str)+1);
1397 strcpy(pcop->name,str);
1399 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1401 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1402 if(PCOR(pcop)->r == NULL) {
1403 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1404 // __FUNCTION__, __LINE__, str, size, offset);
1405 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size);
1407 //fprintf(stderr, "allocating new register -> %s\n", str);
1409 // DEBUGpic16_emitcode(";","%d %s size= %d offset=%d - had to alloc by reg name",__LINE__,pcop->name,size,offset);
1411 // DEBUGpic16_emitcode(";","%d %s size= %d offset=%d",__LINE__,pcop->name,size,offset);
1413 PCOR(pcop)->instance = offset;
1418 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1422 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1424 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1425 PCOR(pcop)->rIdx = rIdx;
1426 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1427 PCOR(pcop)->r->isFree = 0;
1428 PCOR(pcop)->r->wasUsed = 1;
1430 pcop->type = PCOR(pcop)->r->pc_type;
1435 /*---------------------------------------------------------------------------------*/
1436 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1438 /*---------------------------------------------------------------------------------*/
1439 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1444 pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1446 /* comment the following check, so errors to throw up */
1447 // if(!pcop2)return NULL;
1449 temp = pic16_popGet(aop_dst, offset);
1450 pcop2->pcop2 = temp;
1457 /*--------------------------------------------------------------------------------.-*/
1458 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1459 /* VR 030601 , adapted by Hans Dorn */
1460 /*--------------------------------------------------------------------------------.-*/
1461 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1465 pcop2 = (pCodeOpReg2 *)src;
1473 /*---------------------------------------------------------------------------------*/
1474 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
1475 /* movff instruction */
1476 /*---------------------------------------------------------------------------------*/
1477 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1482 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1483 pcop2->pcop2 = pic16_popCopyReg(dst);
1485 /* the pCodeOp may be already allocated */
1486 pcop2 = (pCodeOpReg2 *)(src);
1487 pcop2->pcop2 = (pCodeOp *)(dst);
1494 /*-----------------------------------------------------------------*/
1495 /* pic16_popGet - asm operator to pcode operator conversion */
1496 /*-----------------------------------------------------------------*/
1497 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1499 //char *s = buffer ;
1503 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1504 /* offset is greater than
1507 // if (offset > (aop->size - 1) &&
1508 // aop->type != AOP_LIT)
1509 // return NULL; //zero;
1511 /* depending on type */
1512 switch (aop->type) {
1518 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1519 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1526 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1527 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1531 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
1533 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1535 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1537 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1538 PCOR(pcop)->rIdx = rIdx;
1539 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1540 PCOR(pcop)->r->wasUsed=1;
1541 PCOR(pcop)->r->isFree=0;
1543 PCOR(pcop)->instance = offset;
1544 pcop->type = PCOR(pcop)->r->pc_type;
1545 // rs = aop->aopu.aop_reg[offset]->name;
1546 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1550 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1551 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1557 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1558 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1562 int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1564 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1566 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1567 PCOR(pcop)->rIdx = rIdx;
1568 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1569 PCOR(pcop)->r->wasUsed=1;
1570 PCOR(pcop)->r->isFree=0;
1572 PCOR(pcop)->instance = offset;
1573 pcop->type = PCOR(pcop)->r->pc_type;
1574 rs = aop->aopu.aop_reg[offset]->name;
1575 DEBUGpic16_emitcode(";","%d regiser idx = %d name =%s",__LINE__,rIdx,rs);
1580 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1582 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1583 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1584 //if(PCOR(pcop)->r == NULL)
1585 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1589 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1590 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1593 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1594 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1597 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1598 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1599 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1600 pcop->type = PCOR(pcop)->r->pc_type;
1601 pcop->name = PCOR(pcop)->r->name;
1607 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1609 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1610 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1612 switch( aop->aopu.pcop->type ) {
1613 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
1614 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1616 assert( 0 ); /* should never reach here */;
1619 PCOI(pcop)->offset = offset;
1624 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1625 "pic16_popGet got unsupported aop->type");
1628 /*-----------------------------------------------------------------*/
1629 /* pic16_aopPut - puts a string for a aop */
1630 /*-----------------------------------------------------------------*/
1631 void pic16_aopPut (asmop *aop, char *s, int offset)
1636 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1638 if (aop->size && offset > ( aop->size - 1)) {
1639 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1640 "pic16_aopPut got offset > aop->size");
1644 /* will assign value to value */
1645 /* depending on where it is ofcourse */
1646 switch (aop->type) {
1649 sprintf(d,"(%s + %d)",
1650 aop->aopu.aop_dir,offset);
1651 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1654 sprintf(d,"%s",aop->aopu.aop_dir);
1657 DEBUGpic16_emitcode(";","%d",__LINE__);
1659 pic16_emitcode("movf","%s,w",s);
1660 pic16_emitcode("movwf","%s",d);
1663 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
1664 if(offset >= aop->size) {
1665 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1668 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1671 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1678 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1679 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1682 strcmp(s,"r0") == 0 ||
1683 strcmp(s,"r1") == 0 ||
1684 strcmp(s,"r2") == 0 ||
1685 strcmp(s,"r3") == 0 ||
1686 strcmp(s,"r4") == 0 ||
1687 strcmp(s,"r5") == 0 ||
1688 strcmp(s,"r6") == 0 ||
1689 strcmp(s,"r7") == 0 )
1690 pic16_emitcode("mov","%s,%s ; %d",
1691 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1695 if(strcmp(s,"W")==0 )
1696 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
1698 pic16_emitcode("movwf","%s",
1699 aop->aopu.aop_reg[offset]->name);
1701 if(strcmp(s,zero)==0) {
1702 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1704 } else if(strcmp(s,"W")==0) {
1705 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1706 pcop->type = PO_GPR_REGISTER;
1708 PCOR(pcop)->rIdx = -1;
1709 PCOR(pcop)->r = NULL;
1711 DEBUGpic16_emitcode(";","%d",__LINE__);
1712 pcop->name = Safe_strdup(s);
1713 pic16_emitpcode(POC_MOVFW,pcop);
1714 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1715 } else if(strcmp(s,one)==0) {
1716 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1717 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1719 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1727 if (aop->type == AOP_DPTR2)
1733 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1734 "pic16_aopPut writting to code space");
1738 while (offset > aop->coff) {
1740 pic16_emitcode ("inc","dptr");
1743 while (offset < aop->coff) {
1745 pic16_emitcode("lcall","__decdptr");
1750 /* if not in accumulater */
1753 pic16_emitcode ("movx","@dptr,a");
1755 if (aop->type == AOP_DPTR2)
1763 while (offset > aop->coff) {
1765 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1767 while (offset < aop->coff) {
1769 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1775 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1780 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1782 if (strcmp(s,"r0") == 0 ||
1783 strcmp(s,"r1") == 0 ||
1784 strcmp(s,"r2") == 0 ||
1785 strcmp(s,"r3") == 0 ||
1786 strcmp(s,"r4") == 0 ||
1787 strcmp(s,"r5") == 0 ||
1788 strcmp(s,"r6") == 0 ||
1789 strcmp(s,"r7") == 0 ) {
1791 sprintf(buffer,"a%s",s);
1792 pic16_emitcode("mov","@%s,%s",
1793 aop->aopu.aop_ptr->name,buffer);
1795 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1800 if (strcmp(s,"a") == 0)
1801 pic16_emitcode("push","acc");
1803 pic16_emitcode("push","%s",s);
1808 /* if bit variable */
1809 if (!aop->aopu.aop_dir) {
1810 pic16_emitcode("clr","a");
1811 pic16_emitcode("rlc","a");
1814 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1817 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1820 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1822 lbl = newiTempLabel(NULL);
1824 if (strcmp(s,"a")) {
1827 pic16_emitcode("clr","c");
1828 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
1829 pic16_emitcode("cpl","c");
1830 pic16_emitcode("","%05d_DS_:",lbl->key+100);
1831 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1838 if (strcmp(aop->aopu.aop_str[offset],s))
1839 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1844 if (!offset && (strcmp(s,"acc") == 0))
1847 if (strcmp(aop->aopu.aop_str[offset],s))
1848 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1852 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1853 "pic16_aopPut got unsupported aop->type");
1859 /*-----------------------------------------------------------------*/
1860 /* mov2w - generate either a MOVLW or MOVFW based operand type */
1861 /*-----------------------------------------------------------------*/
1862 static void mov2w (asmop *aop, int offset)
1868 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
1870 if ( aop->type == AOP_PCODE ||
1871 aop->type == AOP_LIT )
1872 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
1874 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
1879 /* push pcop into stack */
1880 void pic16_pushpCodeOp(pCodeOp *pcop)
1882 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
1885 /* pop pcop from stack */
1886 void pic16_poppCodeOp(pCodeOp *pcop)
1888 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
1892 /*-----------------------------------------------------------------*/
1893 /* pushw - pushes wreg to stack */
1894 /*-----------------------------------------------------------------*/
1897 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1898 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
1902 /*-----------------------------------------------------------------*/
1903 /* pushaop - pushes aop to stack */
1904 /*-----------------------------------------------------------------*/
1905 void pushaop(asmop *aop, int offset)
1907 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1908 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
1911 /*-----------------------------------------------------------------*/
1912 /* popaop - pops aop from stack */
1913 /*-----------------------------------------------------------------*/
1914 void popaop(asmop *aop, int offset)
1916 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
1917 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
1920 void popaopidx(asmop *aop, int offset, int index)
1924 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1926 if(STACK_MODEL_LARGE)ofs++;
1928 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
1929 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
1932 /*-----------------------------------------------------------------*/
1933 /* reAdjustPreg - points a register back to where it should */
1934 /*-----------------------------------------------------------------*/
1935 static void reAdjustPreg (asmop *aop)
1939 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1941 if ((size = aop->size) <= 1)
1944 switch (aop->type) {
1948 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1952 if (aop->type == AOP_DPTR2)
1958 pic16_emitcode("lcall","__decdptr");
1961 if (aop->type == AOP_DPTR2)
1973 /*-----------------------------------------------------------------*/
1974 /* opIsGptr: returns non-zero if the passed operand is */
1975 /* a generic pointer type. */
1976 /*-----------------------------------------------------------------*/
1977 static int opIsGptr(operand *op)
1979 sym_link *type = operandType(op);
1981 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1982 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1990 /*-----------------------------------------------------------------*/
1991 /* pic16_getDataSize - get the operand data size */
1992 /*-----------------------------------------------------------------*/
1993 int pic16_getDataSize(operand *op)
1995 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1998 return AOP_SIZE(op);
2000 // tsd- in the pic port, the genptr size is 1, so this code here
2001 // fails. ( in the 8051 port, the size was 4).
2004 size = AOP_SIZE(op);
2005 if (size == GPTRSIZE)
2007 sym_link *type = operandType(op);
2008 if (IS_GENPTR(type))
2010 /* generic pointer; arithmetic operations
2011 * should ignore the high byte (pointer type).
2014 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2021 /*-----------------------------------------------------------------*/
2022 /* pic16_outAcc - output Acc */
2023 /*-----------------------------------------------------------------*/
2024 void pic16_outAcc(operand *result)
2027 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2028 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2031 size = pic16_getDataSize(result);
2033 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2036 /* unsigned or positive */
2038 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2043 /*-----------------------------------------------------------------*/
2044 /* pic16_outBitC - output a bit C */
2045 /*-----------------------------------------------------------------*/
2046 void pic16_outBitC(operand *result)
2049 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2050 /* if the result is bit */
2051 if (AOP_TYPE(result) == AOP_CRY)
2052 pic16_aopPut(AOP(result),"c",0);
2054 pic16_emitcode("clr","a ; %d", __LINE__);
2055 pic16_emitcode("rlc","a");
2056 pic16_outAcc(result);
2060 /*-----------------------------------------------------------------*/
2061 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2062 /*-----------------------------------------------------------------*/
2063 void pic16_toBoolean(operand *oper)
2065 int size = AOP_SIZE(oper) - 1;
2068 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2070 if ( AOP_TYPE(oper) != AOP_ACC) {
2071 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2074 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2079 #if !defined(GEN_Not)
2080 /*-----------------------------------------------------------------*/
2081 /* genNot - generate code for ! operation */
2082 /*-----------------------------------------------------------------*/
2083 static void pic16_genNot (iCode *ic)
2088 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2089 /* assign asmOps to operand & result */
2090 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2091 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2093 DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2094 /* if in bit space then a special case */
2095 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2096 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2097 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2098 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2100 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2101 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2102 pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2107 size = AOP_SIZE(IC_LEFT(ic));
2109 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2110 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2111 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2114 pic16_toBoolean(IC_LEFT(ic));
2116 tlbl = newiTempLabel(NULL);
2117 pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2118 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2119 pic16_outBitC(IC_RESULT(ic));
2122 /* release the aops */
2123 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2124 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2129 #if !defined(GEN_Cpl)
2130 /*-----------------------------------------------------------------*/
2131 /* genCpl - generate code for complement */
2132 /*-----------------------------------------------------------------*/
2133 static void pic16_genCpl (iCode *ic)
2139 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2140 /* assign asmOps to operand & result */
2141 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2142 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2144 /* if both are in bit space then
2146 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2147 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2149 pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
2150 pic16_emitcode("cpl","c");
2151 pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
2155 size = AOP_SIZE(IC_RESULT(ic));
2158 char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2160 pic16_emitcode("cpl","a");
2161 pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2163 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2164 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)), offset));
2166 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2167 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2175 /* release the aops */
2176 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2177 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2181 /*-----------------------------------------------------------------*/
2182 /* genUminusFloat - unary minus for floating points */
2183 /*-----------------------------------------------------------------*/
2184 static void genUminusFloat(operand *op,operand *result)
2186 int size ,offset =0 ;
2189 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2190 /* for this we just need to flip the
2191 first it then copy the rest in place */
2192 size = AOP_SIZE(op) - 1;
2193 l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2197 pic16_emitcode("cpl","acc.7");
2198 pic16_aopPut(AOP(result),"a",3);
2201 pic16_aopPut(AOP(result),
2202 pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2208 /*-----------------------------------------------------------------*/
2209 /* genUminus - unary minus code generation */
2210 /*-----------------------------------------------------------------*/
2211 static void genUminus (iCode *ic)
2214 sym_link *optype, *rtype;
2217 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2219 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2220 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2222 /* if both in bit space then special
2224 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2225 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2227 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2228 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2229 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2234 optype = operandType(IC_LEFT(ic));
2235 rtype = operandType(IC_RESULT(ic));
2237 /* if float then do float stuff */
2238 if (IS_FLOAT(optype)) {
2239 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2243 /* otherwise subtract from zero by taking the 2's complement */
2244 size = AOP_SIZE(IC_LEFT(ic));
2246 for(i=0; i<size; i++) {
2247 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2248 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)),i));
2250 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2251 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2255 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2256 for(i=1; i<size; i++) {
2258 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2262 /* release the aops */
2263 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2264 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2267 /*-----------------------------------------------------------------*/
2268 /* saveRegisters - will look for a call and save the registers */
2269 /*-----------------------------------------------------------------*/
2270 static void saveRegisters(iCode *lic)
2277 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2279 for (ic = lic ; ic ; ic = ic->next)
2280 if (ic->op == CALL || ic->op == PCALL)
2284 fprintf(stderr,"found parameter push with no function call\n");
2288 /* if the registers have been saved already then
2290 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2293 /* find the registers in use at this time
2294 and push them away to safety */
2295 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2299 if (options.useXstack) {
2300 if (bitVectBitValue(rsave,R0_IDX))
2301 pic16_emitcode("mov","b,r0");
2302 pic16_emitcode("mov","r0,%s",spname);
2303 for (i = 0 ; i < pic16_nRegs ; i++) {
2304 if (bitVectBitValue(rsave,i)) {
2306 pic16_emitcode("mov","a,b");
2308 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2309 pic16_emitcode("movx","@r0,a");
2310 pic16_emitcode("inc","r0");
2313 pic16_emitcode("mov","%s,r0",spname);
2314 if (bitVectBitValue(rsave,R0_IDX))
2315 pic16_emitcode("mov","r0,b");
2317 //for (i = 0 ; i < pic16_nRegs ; i++) {
2318 // if (bitVectBitValue(rsave,i))
2319 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2322 dtype = operandType(IC_LEFT(ic));
2323 if (currFunc && dtype &&
2324 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2325 IFFUNC_ISISR(currFunc->type) &&
2328 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2331 /*-----------------------------------------------------------------*/
2332 /* unsaveRegisters - pop the pushed registers */
2333 /*-----------------------------------------------------------------*/
2334 static void unsaveRegisters (iCode *ic)
2339 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2340 /* find the registers in use at this time
2341 and push them away to safety */
2342 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2345 if (options.useXstack) {
2346 pic16_emitcode("mov","r0,%s",spname);
2347 for (i = pic16_nRegs ; i >= 0 ; i--) {
2348 if (bitVectBitValue(rsave,i)) {
2349 pic16_emitcode("dec","r0");
2350 pic16_emitcode("movx","a,@r0");
2352 pic16_emitcode("mov","b,a");
2354 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2358 pic16_emitcode("mov","%s,r0",spname);
2359 if (bitVectBitValue(rsave,R0_IDX))
2360 pic16_emitcode("mov","r0,b");
2362 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2363 // if (bitVectBitValue(rsave,i))
2364 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2370 /*-----------------------------------------------------------------*/
2372 /*-----------------------------------------------------------------*/
2373 static void pushSide(operand * oper, int size)
2376 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2378 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2379 if (AOP_TYPE(oper) != AOP_REG &&
2380 AOP_TYPE(oper) != AOP_DIR &&
2382 pic16_emitcode("mov","a,%s",l);
2383 pic16_emitcode("push","acc");
2385 pic16_emitcode("push","%s",l);
2390 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2392 // (AOP(left)->aopu.pcop->type == PO_DIR)?
2394 if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2395 pic16_emitpcode(POC_MOVFW, src);
2396 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2398 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2399 src, pic16_popGet(AOP(op), offset)));
2404 /*-----------------------------------------------------------------*/
2405 /* assignResultValue - assign results to oper, rescall==1 is */
2406 /* called from genCall() or genPCall() */
2407 /*-----------------------------------------------------------------*/
2408 static void assignResultValue(operand * oper, int rescall)
2410 int size = AOP_SIZE(oper);
2412 DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2413 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2416 /* assign result from a call/pcall function() */
2418 /* function results are stored in a special order,
2419 * see top of file with Function return policy, or manual */
2422 /* 8-bits, result in WREG */
2423 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2426 /* 16-bits, result in PRODL:WREG */
2427 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2428 // pic16_emitpcode(POC_MOVFF,
2429 // pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl), pic16_popGet(AOP(oper), 1)));
2433 /* 24-bits, result in PRODH:PRODL:WREG */
2434 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2436 // pic16_emitpcode(POC_MOVFF,
2437 // pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodh), pic16_popGet(AOP(oper), 2)));
2441 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2442 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2444 // pic16_emitpcode(POC_MOVFF,
2445 // pic16_popGet2p(pic16_popCopyReg(&pic16_pc_fsr0l), pic16_popGet(AOP(oper), 3)));
2448 /* >32-bits, result on stack, and FSR0 points to beginning.
2449 * Fix stack when done */
2452 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2453 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2455 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2460 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2461 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2462 if(STACK_MODEL_LARGE) {
2464 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2468 if(!GpsuedoStkPtr) {
2469 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2470 /* The last byte in the assignment is in W */
2472 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2477 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2478 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2480 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2486 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2488 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2498 /*-----------------------------------------------------------------*/
2499 /* genIpush - genrate code for pushing this gets a little complex */
2500 /*-----------------------------------------------------------------*/
2501 static void genIpush (iCode *ic)
2504 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2506 int size, offset = 0 ;
2510 /* if this is not a parm push : ie. it is spill push
2511 and spill push is always done on the local stack */
2512 if (!ic->parmPush) {
2514 /* and the item is spilt then do nothing */
2515 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2518 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2519 size = AOP_SIZE(IC_LEFT(ic));
2520 /* push it on the stack */
2522 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2527 pic16_emitcode("push","%s",l);
2532 /* this is a paramter push: in this case we call
2533 the routine to find the call and save those
2534 registers that need to be saved */
2537 /* then do the push */
2538 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2541 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2542 size = AOP_SIZE(IC_LEFT(ic));
2545 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2546 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
2547 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2549 pic16_emitcode("mov","a,%s",l);
2550 pic16_emitcode("push","acc");
2552 pic16_emitcode("push","%s",l);
2555 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2559 /*-----------------------------------------------------------------*/
2560 /* genIpop - recover the registers: can happen only for spilling */
2561 /*-----------------------------------------------------------------*/
2562 static void genIpop (iCode *ic)
2564 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2569 /* if the temp was not pushed then */
2570 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2573 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2574 size = AOP_SIZE(IC_LEFT(ic));
2577 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2580 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2584 /*-----------------------------------------------------------------*/
2585 /* unsaverbank - restores the resgister bank from stack */
2586 /*-----------------------------------------------------------------*/
2587 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2589 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2595 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2597 if (options.useXstack) {
2599 r = getFreePtr(ic,&aop,FALSE);
2602 pic16_emitcode("mov","%s,_spx",r->name);
2603 pic16_emitcode("movx","a,@%s",r->name);
2604 pic16_emitcode("mov","psw,a");
2605 pic16_emitcode("dec","%s",r->name);
2608 pic16_emitcode ("pop","psw");
2611 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2612 if (options.useXstack) {
2613 pic16_emitcode("movx","a,@%s",r->name);
2614 //pic16_emitcode("mov","(%s+%d),a",
2615 // regspic16[i].base,8*bank+regspic16[i].offset);
2616 pic16_emitcode("dec","%s",r->name);
2619 pic16_emitcode("pop",""); //"(%s+%d)",
2620 //regspic16[i].base,8*bank); //+regspic16[i].offset);
2623 if (options.useXstack) {
2625 pic16_emitcode("mov","_spx,%s",r->name);
2626 pic16_freeAsmop(NULL,aop,ic,TRUE);
2632 /*-----------------------------------------------------------------*/
2633 /* saverbank - saves an entire register bank on the stack */
2634 /*-----------------------------------------------------------------*/
2635 static void saverbank (int bank, iCode *ic, bool pushPsw)
2637 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2643 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2644 if (options.useXstack) {
2647 r = getFreePtr(ic,&aop,FALSE);
2648 pic16_emitcode("mov","%s,_spx",r->name);
2652 for (i = 0 ; i < pic16_nRegs ;i++) {
2653 if (options.useXstack) {
2654 pic16_emitcode("inc","%s",r->name);
2655 //pic16_emitcode("mov","a,(%s+%d)",
2656 // regspic16[i].base,8*bank+regspic16[i].offset);
2657 pic16_emitcode("movx","@%s,a",r->name);
2659 pic16_emitcode("push","");// "(%s+%d)",
2660 //regspic16[i].base,8*bank+regspic16[i].offset);
2664 if (options.useXstack) {
2665 pic16_emitcode("mov","a,psw");
2666 pic16_emitcode("movx","@%s,a",r->name);
2667 pic16_emitcode("inc","%s",r->name);
2668 pic16_emitcode("mov","_spx,%s",r->name);
2669 pic16_freeAsmop (NULL,aop,ic,TRUE);
2672 pic16_emitcode("push","psw");
2674 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2682 /*-----------------------------------------------------------------*/
2683 /* genCall - generates a call statement */
2684 /*-----------------------------------------------------------------*/
2685 static void genCall (iCode *ic)
2690 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2692 /* if caller saves & we have not saved then */
2696 /* if we are calling a function that is not using
2697 * the same register bank then we need to save the
2698 * destination registers on the stack */
2699 dtype = operandType(IC_LEFT(ic));
2700 if (currFunc && dtype &&
2701 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2702 IFFUNC_ISISR(currFunc->type) &&
2705 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2707 /* if send set is not empty the assign */
2711 /* For the Pic port, there is no data stack.
2712 * So parameters passed to functions are stored
2713 * in registers. (The pCode optimizer will get
2714 * rid of most of these :). */
2716 int psuedoStkPtr=-1;
2717 int firstTimeThruLoop = 1;
2719 _G.sendSet = reverseSet(_G.sendSet);
2721 /* First figure how many parameters are getting passed */
2722 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2723 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2724 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2725 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2728 stackParms = psuedoStkPtr;
2730 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2731 int size, offset = 0;
2733 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2734 size = AOP_SIZE(IC_LEFT(sic));
2737 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2738 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2739 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2741 if(!firstTimeThruLoop) {
2742 /* If this is not the first time we've been through the loop
2743 * then we need to save the parameter in a temporary
2744 * register. The last byte of the last parameter is
2748 --psuedoStkPtr; // sanity check
2751 firstTimeThruLoop=0;
2753 mov2w (AOP(IC_LEFT(sic)), offset);
2756 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2762 pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2763 OP_SYMBOL(IC_LEFT(ic))->rname :
2764 OP_SYMBOL(IC_LEFT(ic))->name));
2767 /* if we need assign a result value */
2768 if ((IS_ITEMP(IC_RESULT(ic)) &&
2769 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2770 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2771 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2774 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2777 assignResultValue(IC_RESULT(ic), 1);
2779 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2780 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2782 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2786 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2787 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2788 if(STACK_MODEL_LARGE) {
2790 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2794 /* adjust the stack for parameters if required */
2795 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2797 if (ic->parmBytes) {
2800 if (ic->parmBytes > 3) {
2801 pic16_emitcode("mov","a,%s",spname);
2802 pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2803 pic16_emitcode("mov","%s,a",spname);
2805 for ( i = 0 ; i < ic->parmBytes ;i++)
2806 pic16_emitcode("dec","%s",spname);
2809 /* if register bank was saved then pop them */
2811 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2813 /* if we hade saved some registers then unsave them */
2814 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2815 unsaveRegisters (ic);
2820 /*-----------------------------------------------------------------*/ // patch 14
2821 /* genPcall - generates a call by pointer statement */
2822 /*-----------------------------------------------------------------*/
2824 // new version, created from genCall
2826 static void genPcall (iCode *ic)
2830 symbol *retlbl = newiTempLabel(NULL);
2831 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
2833 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2835 /* if caller saves & we have not saved then */
2839 /* if we are calling a function that is not using
2840 * the same register bank then we need to save the
2841 * destination registers on the stack */
2842 dtype = operandType(IC_LEFT(ic));
2843 if (currFunc && dtype &&
2844 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2845 IFFUNC_ISISR(currFunc->type) &&
2848 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2850 /* if send set is not empty the assign */
2854 /* For the Pic port, there is no data stack.
2855 * So parameters passed to functions are stored
2856 * in registers. (The pCode optimizer will get
2857 * rid of most of these :). */
2859 int psuedoStkPtr=-1;
2860 int firstTimeThruLoop = 1;
2862 _G.sendSet = reverseSet(_G.sendSet);
2864 /* First figure how many parameters are getting passed */
2865 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2866 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2867 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2868 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2871 stackParms = psuedoStkPtr;
2873 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2874 int size, offset = 0;
2876 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2877 size = AOP_SIZE(IC_LEFT(sic));
2880 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2881 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2882 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2884 if(!firstTimeThruLoop) {
2885 /* If this is not the first time we've been through the loop
2886 * then we need to save the parameter in a temporary
2887 * register. The last byte of the last parameter is
2891 --psuedoStkPtr; // sanity check
2894 firstTimeThruLoop=0;
2896 mov2w (AOP(IC_LEFT(sic)), offset);
2899 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2904 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2906 // push return address
2907 // push $ on return stack, then replace with retlbl
2909 // Note: retlbl is supplied as dummy operand to PUSH
2910 // This has the nice side effect of keeping the label from being optimized out :o)
2911 pic16_emitpcode(POC_PUSH, pic16_popGetLabel(retlbl->key));
2913 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
2914 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
2915 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
2916 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
2917 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
2918 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
2920 /* make the call by writing the pointer into pc */
2921 // FIXME Disabled writes to PCLATU because of gpsim problems
2923 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
2925 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
2926 // note: MOVFF to PCL not allowed
2927 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
2928 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
2930 /* return address is here: (X) */
2931 pic16_emitpLabel(retlbl->key);
2933 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2936 /* if we need assign a result value */
2937 if ((IS_ITEMP(IC_RESULT(ic)) &&
2938 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2939 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2940 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2943 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2946 assignResultValue(IC_RESULT(ic), 1);
2948 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2949 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2951 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2955 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2956 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2957 if(STACK_MODEL_LARGE) {
2959 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2963 /* adjust the stack for parameters if required */
2964 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2966 if (ic->parmBytes) {
2969 if (ic->parmBytes > 3) {
2970 pic16_emitcode("mov","a,%s",spname);
2971 pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2972 pic16_emitcode("mov","%s,a",spname);
2974 for ( i = 0 ; i < ic->parmBytes ;i++)
2975 pic16_emitcode("dec","%s",spname);
2978 /* if register bank was saved then pop them */
2980 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2982 /* if we hade saved some registers then unsave them */
2983 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2984 unsaveRegisters (ic);
2989 // old version, kept for reference
2991 /*-----------------------------------------------------------------*/
2992 /* genPcall - generates a call by pointer statement */
2993 /*-----------------------------------------------------------------*/
2994 static void genPcall (iCode *ic)
2997 symbol *rlbl = newiTempLabel(NULL);
3000 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3001 /* if caller saves & we have not saved then */
3005 /* if we are calling a function that is not using
3006 the same register bank then we need to save the
3007 destination registers on the stack */
3008 dtype = operandType(IC_LEFT(ic));
3009 if (currFunc && dtype &&
3010 IFFUNC_ISISR(currFunc->type) &&
3011 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3012 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
3015 /* push the return address on to the stack */
3016 pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
3017 pic16_emitcode("push","acc");
3018 pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
3019 pic16_emitcode("push","acc");
3021 if (options.model == MODEL_FLAT24)
3023 pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
3024 pic16_emitcode("push","acc");
3027 /* now push the calling address */
3028 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3030 pushSide(IC_LEFT(ic), FPTRSIZE);
3032 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3034 /* if send set is not empty the assign */
3038 for (sic = setFirstItem(_G.sendSet) ; sic ;
3039 sic = setNextItem(_G.sendSet)) {
3040 int size, offset = 0;
3041 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3042 size = AOP_SIZE(IC_LEFT(sic));
3044 char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
3046 if (strcmp(l,fReturn[offset]))
3047 pic16_emitcode("mov","%s,%s",
3052 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3057 pic16_emitcode("ret","");
3058 pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
3061 /* if we need assign a result value */
3062 if ((IS_ITEMP(IC_RESULT(ic)) &&
3063 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3064 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
3065 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3068 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3071 assignResultValue(IC_RESULT(ic), 1);
3073 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3076 /* adjust the stack for parameters if
3078 if (ic->parmBytes) {
3080 if (ic->parmBytes > 3) {
3081 pic16_emitcode("mov","a,%s",spname);
3082 pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3083 pic16_emitcode("mov","%s,a",spname);
3085 for ( i = 0 ; i < ic->parmBytes ;i++)
3086 pic16_emitcode("dec","%s",spname);
3090 /* if register bank was saved then unsave them */
3091 if (currFunc && dtype &&
3092 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3093 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3095 /* if we hade saved some registers then
3098 unsaveRegisters (ic);
3104 /*-----------------------------------------------------------------*/
3105 /* resultRemat - result is rematerializable */
3106 /*-----------------------------------------------------------------*/
3107 static int resultRemat (iCode *ic)
3109 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3110 if (SKIP_IC(ic) || ic->op == IFX)
3113 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3114 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3115 if (sym->remat && !POINTER_SET(ic))
3122 #if defined(__BORLANDC__) || defined(_MSC_VER)
3123 #define STRCASECMP stricmp
3125 #define STRCASECMP strcasecmp
3129 /*-----------------------------------------------------------------*/
3130 /* inExcludeList - return 1 if the string is in exclude Reg list */
3131 /*-----------------------------------------------------------------*/
3132 static bool inExcludeList(char *s)
3134 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3137 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3138 if (options.excludeRegs[i] &&
3139 STRCASECMP(options.excludeRegs[i],"none") == 0)
3142 for ( i = 0 ; options.excludeRegs[i]; i++) {
3143 if (options.excludeRegs[i] &&
3144 STRCASECMP(s,options.excludeRegs[i]) == 0)
3151 /*-----------------------------------------------------------------*/
3152 /* genFunction - generated code for function entry */
3153 /*-----------------------------------------------------------------*/
3154 static void genFunction (iCode *ic)
3159 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
3161 labelOffset += (max_key+4);
3166 ftype = operandType(IC_LEFT(ic));
3167 sym = OP_SYMBOL(IC_LEFT(ic));
3169 if(/*!IFFUNC_ISNAKED(ftype) &&*/ IFFUNC_ISISR(ftype)) {
3170 /* create an absolute section at the interrupt vector:
3171 * that is 0x0008 for interrupt 1, 0x0018 interrupt 2 */
3179 sym = OP_SYMBOL( IC_LEFT(ic));
3181 // fprintf(stderr, "comparing name int %d\t%s with %s\n",
3182 // i, interrupts[i]->name, sym->name);
3183 if(interrupts[i]->name
3184 && !STRCASECMP(interrupts[i]->name, sym->name)) {
3191 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3192 __FILE__, __LINE__, sym->name);
3197 sprintf(asymname, "ivec_%d_%s", ivec, sym->name);
3198 asym = newSymbol(asymname, 0);
3199 pic16_emitcode(";","-----------------------------------------");
3200 pic16_emitcode(";"," interrupt vector %d for function %s", ivec, sym->name);
3201 pic16_emitcode(";","-----------------------------------------");
3203 pic16_addpCode2pBlock(pb, pic16_newpCodeFunction(moduleName, asym->name));
3204 pic16_pBlockConvert2Absolute(pb);
3206 pic16_emitpcode(POC_GOTO, pic16_popGetWithString( sym->rname ));
3208 /* mark the end of this tiny function */
3209 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3214 abSym = Safe_calloc(1, sizeof(absSym));
3215 abSym->name = Safe_strdup( asymname );
3218 case 0: abSym->address = 0x000000; break;
3219 case 1: abSym->address = 0x000008; break;
3220 case 2: abSym->address = 0x000018; break;
3223 addSet(&absSymSet, abSym);
3228 /* create the function header */
3229 pic16_emitcode(";","-----------------------------------------");
3230 pic16_emitcode(";"," function %s",sym->name);
3231 pic16_emitcode(";","-----------------------------------------");
3233 pic16_emitcode("","%s:",sym->rname);
3234 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3239 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet))
3240 if(!strcmp(ab->name, sym->name)) {
3241 pic16_pBlockConvert2Absolute(pb);
3248 if(IFFUNC_ISNAKED(ftype)) {
3249 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3253 /* if critical function then turn interrupts off */
3254 if (IFFUNC_ISCRITICAL(ftype))
3255 pic16_emitcode("clr","ea");
3257 /* if this is an interrupt service routine then
3258 * save acc, b, dpl, dph */
3259 if (IFFUNC_ISISR(sym->type)) {
3261 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3262 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3263 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3264 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3265 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3266 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3267 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3268 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3270 pic16_pBlockConvert2ISR(pb);
3272 /* if any registers used */
3273 if (sym->regsUsed) {
3274 /* save the registers used */
3275 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3276 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3277 if (bitVectBitValue(sym->regsUsed,i)) {
3278 // fprintf(stderr, "%s:%d function %s uses register %s\n",
3279 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3280 // pic16_regWithIdx(i)->name);
3282 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3288 /* emit code to setup stack frame if user enabled,
3289 * and function is not main() */
3291 // fprintf(stderr, "function name: %s\n", sym->name);
3292 if(strcmp(sym->name, "main")) {
3293 if(!options.ommitFramePtr || sym->regsUsed) {
3294 /* setup the stack frame */
3295 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3296 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3297 if(STACK_MODEL_LARGE)
3298 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3302 /* if callee-save to be used for this function
3303 * then save the registers being used in this function */
3304 if (IFFUNC_CALLEESAVES(sym->type)) {
3307 // fprintf(stderr, "%s:%d function sym->regsUsed= %p\n", __FILE__, __LINE__, sym->regsUsed);
3309 /* if any registers used */
3310 if (sym->regsUsed) {
3311 /* save the registers used */
3312 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3313 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3314 if (bitVectBitValue(sym->regsUsed,i)) {
3315 // fprintf(stderr, "%s:%d function %s uses register %s\n",
3316 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3317 // pic16_regWithIdx(i)->name);
3319 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3320 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3321 // PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))),
3322 // &pic16_pc_postdec1, 0));
3333 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3335 if (options.useXstack) {
3336 pic16_emitcode("mov","r0,%s",spname);
3337 pic16_emitcode("mov","a,_bp");
3338 pic16_emitcode("movx","@r0,a");
3339 pic16_emitcode("inc","%s",spname);
3341 /* set up the stack */
3342 pic16_emitcode ("push","_bp"); /* save the callers stack */
3344 pic16_emitcode ("mov","_bp,%s",spname);
3347 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3349 /* adjust the stack for the function */
3354 werror(W_STACK_OVERFLOW,sym->name);
3356 if (i > 3 && sym->recvSize < 4) {
3357 pic16_emitcode ("mov","a,sp");
3358 pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3359 pic16_emitcode ("mov","sp,a");
3362 pic16_emitcode("inc","sp");
3366 DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
3368 pic16_emitcode ("mov","a,_spx");
3369 pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3370 pic16_emitcode ("mov","_spx,a");
3375 /*-----------------------------------------------------------------*/
3376 /* genEndFunction - generates epilogue for functions */
3377 /*-----------------------------------------------------------------*/
3378 static void genEndFunction (iCode *ic)
3380 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3382 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3384 if(IFFUNC_ISNAKED(sym->type)) {
3385 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3390 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3392 pic16_emitcode ("mov","%s,_bp",spname);
3396 /* if use external stack but some variables were
3397 added to the local stack then decrement the
3399 if (options.useXstack && sym->stack) {
3400 pic16_emitcode("mov","a,sp");
3401 pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3402 pic16_emitcode("mov","sp,a");
3407 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3408 if (options.useXstack) {
3409 pic16_emitcode("mov","r0,%s",spname);
3410 pic16_emitcode("movx","a,@r0");
3411 pic16_emitcode("mov","_bp,a");
3412 pic16_emitcode("dec","%s",spname);
3416 pic16_emitcode ("pop","_bp");
3421 /* restore the register bank */
3422 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3423 pic16_emitcode ("pop","psw");
3425 if (IFFUNC_ISISR(sym->type)) {
3427 /* now we need to restore the registers */
3429 /* if any registers used */
3430 if (sym->regsUsed) {
3433 /* restore registers used */
3434 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3435 for ( i = sym->regsUsed->size; i >= 0; i--) {
3436 if (bitVectBitValue(sym->regsUsed,i)) {
3437 // fprintf(stderr, "%s:%d function %s uses register %s\n",
3438 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3439 // pic16_regWithIdx(i)->name);
3441 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3443 PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3448 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3449 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3450 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3451 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3452 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3453 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3454 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3457 /* if debug then send end of function */
3458 /* if (options.debug && currFunc) */
3461 pic16_emitcode(";","C$%s$%d$%d$%d ==.",
3462 FileBaseName(ic->filename),currFunc->lastLine,
3463 ic->level,ic->block);
3464 if (IS_STATIC(currFunc->etype))
3465 pic16_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
3467 pic16_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
3472 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_status));
3473 pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_ssave));
3474 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_status));
3475 pic16_emitpcode(POC_SWAPF, pic16_popCopyReg(&pic16_pc_wsave));
3476 pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_wsave));
3479 pic16_emitpcodeNULLop(POC_RETFIE);
3482 if (IFFUNC_ISCRITICAL(sym->type))
3483 pic16_emitcode("setb","ea");
3485 /* if any registers used */
3486 if (sym->regsUsed) {
3488 /* save the registers used */
3489 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3490 for ( i = sym->regsUsed->size; i >= 0; i--) {
3491 if (bitVectBitValue(sym->regsUsed,i)) {
3492 // fprintf(stderr, "%s:%d function %s uses register %s\n",
3493 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3494 // pic16_regWithIdx(i)->name);
3496 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3498 PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3504 /* if debug then send end of function */
3507 pic16_emitcode(";","C$%s$%d$%d$%d ==.",
3508 FileBaseName(ic->filename),currFunc->lastLine,
3509 ic->level,ic->block);
3510 if (IS_STATIC(currFunc->etype))
3511 pic16_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
3513 pic16_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
3517 /* insert code to restore stack frame, if user enabled it
3518 * and function is not main() */
3520 if(strcmp(sym->name, "main")) {
3521 if(!options.ommitFramePtr || sym->regsUsed) {
3522 /* restore stack frame */
3523 if(STACK_MODEL_LARGE)
3524 pic16_emitpcode(POC_MOVFF,
3525 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3526 pic16_emitpcode(POC_MOVFF,
3527 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3531 pic16_emitcode ("return","");
3532 pic16_emitpcodeNULLop(POC_RETURN);
3534 /* Mark the end of a function */
3535 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3541 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3543 // (AOP(left)->aopu.pcop->type == PO_DIR)?
3545 if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
3546 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset)); // patch 12
3547 pic16_emitpcode(POC_MOVWF, dest);
3549 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3550 pic16_popGet(AOP(op), offset), dest));
3554 /*-----------------------------------------------------------------*/
3555 /* genRet - generate code for return statement */
3556 /*-----------------------------------------------------------------*/
3557 static void genRet (iCode *ic)
3562 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3563 /* if we have no return value then
3564 * just generate the "ret" */
3569 /* we have something to return then
3570 * move the return value into place */
3571 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3572 size = AOP_SIZE(IC_LEFT(ic));
3576 pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3577 // pic16_emitpcode(POC_MOVFF,
3578 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3581 pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3582 // pic16_emitpcode(POC_MOVFF,
3583 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3586 pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3587 // pic16_emitpcode(POC_MOVFF,
3588 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3591 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0)); // patch 12
3593 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg)); // patch 12
3594 // pic16_emitpcode(POC_MOVFF,
3595 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3598 /* >32-bits, setup stack and FSR0 */
3600 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3601 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3603 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3605 // popaopidx(AOP(oper), size, GpseudoStkPtr);
3610 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3611 pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3613 if(STACK_MODEL_LARGE) {
3614 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3615 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3617 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3622 /* old code, left here for reference -- VR */
3626 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3628 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3629 pic16_emitpcomment("push %s",l);
3632 DEBUGpic16_emitcode(";", "%d", __LINE__);
3633 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3634 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
3636 if (strcmp(fReturn[offset],l)) {
3637 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3638 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3639 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3641 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3645 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3655 if (strcmp(fReturn[pushed],"a"))
3656 pic16_emitcode("pop",fReturn[pushed]);
3658 pic16_emitcode("pop","acc");
3664 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3667 /* generate a jump to the return label
3668 * if the next is not the return statement */
3669 if (!(ic->next && ic->next->op == LABEL
3670 && IC_LABEL(ic->next) == returnLabel)) {
3672 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3673 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3677 /*-----------------------------------------------------------------*/
3678 /* genLabel - generates a label */
3679 /*-----------------------------------------------------------------*/
3680 static void genLabel (iCode *ic)
3682 /* special case never generate */
3683 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3684 if (IC_LABEL(ic) == entryLabel)
3687 pic16_emitpLabel(IC_LABEL(ic)->key);
3688 pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3691 /*-----------------------------------------------------------------*/
3692 /* genGoto - generates a goto */
3693 /*-----------------------------------------------------------------*/
3695 static void genGoto (iCode *ic)
3697 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3698 pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3702 /*-----------------------------------------------------------------*/
3703 /* genMultbits :- multiplication of bits */
3704 /*-----------------------------------------------------------------*/
3705 static void genMultbits (operand *left,
3709 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3711 if(!pic16_sameRegs(AOP(result),AOP(right)))
3712 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
3714 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3715 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3716 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
3721 /*-----------------------------------------------------------------*/
3722 /* genMultOneByte : 8 bit multiplication & division */
3723 /*-----------------------------------------------------------------*/
3724 static void genMultOneByte (operand *left,
3728 sym_link *opetype = operandType(result);
3733 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3734 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3735 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3737 /* (if two literals, the value is computed before) */
3738 /* if one literal, literal on the right */
3739 if (AOP_TYPE(left) == AOP_LIT){
3745 size = AOP_SIZE(result);
3748 if (AOP_TYPE(right) == AOP_LIT){
3749 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3750 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3751 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3752 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3754 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3755 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3756 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3757 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3759 pic16_genMult8X8_8 (left, right,result);
3760 } else { // (size > 1)
3762 pic16_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s",
3763 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3764 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3765 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3767 if (SPEC_USIGN(opetype)){
3768 pic16_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3769 pic16_genUMult8X8_16 (left, right, result, NULL);
3772 /* for filling the MSBs */
3773 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),2));
3774 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),3));
3778 pic16_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3780 pic16_emitcode("mov","a,b");
3782 /* adjust the MSB if left or right neg */
3784 /* if one literal */
3785 if (AOP_TYPE(right) == AOP_LIT){
3786 pic16_emitcode("multiply ","right is a lit");
3787 /* AND literal negative */
3788 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3789 /* adjust MSB (c==0 after mul) */
3790 pic16_emitcode("subb","a,%s", pic16_aopGet(AOP(left),0,FALSE,FALSE));
3794 pic16_genSMult8X8_16 (left, right, result, NULL);
3798 pic16_emitcode("multiply ","size is greater than 2, so propogate sign");
3800 pic16_emitcode("rlc","a");
3801 pic16_emitcode("subb","a,acc");
3809 pic16_emitcode("multiply ","size is way greater than 2, so propogate sign");
3810 //pic16_aopPut(AOP(result),"a",offset++);
3814 /*-----------------------------------------------------------------*/
3815 /* genMult - generates code for multiplication */
3816 /*-----------------------------------------------------------------*/
3817 static void genMult (iCode *ic)
3819 operand *left = IC_LEFT(ic);
3820 operand *right = IC_RIGHT(ic);
3821 operand *result= IC_RESULT(ic);
3823 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3824 /* assign the amsops */
3825 pic16_aopOp (left,ic,FALSE);
3826 pic16_aopOp (right,ic,FALSE);
3827 pic16_aopOp (result,ic,TRUE);
3829 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3831 /* special cases first */
3833 if (AOP_TYPE(left) == AOP_CRY &&
3834 AOP_TYPE(right)== AOP_CRY) {
3835 genMultbits(left,right,result);
3839 /* if both are of size == 1 */
3840 if (AOP_SIZE(left) == 1 &&
3841 AOP_SIZE(right) == 1 ) {
3842 genMultOneByte(left,right,result);
3846 pic16_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3848 /* should have been converted to function call */
3852 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3853 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3854 pic16_freeAsmop(result,NULL,ic,TRUE);
3857 /*-----------------------------------------------------------------*/
3858 /* genDivbits :- division of bits */
3859 /*-----------------------------------------------------------------*/
3860 static void genDivbits (operand *left,
3867 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3868 /* the result must be bit */
3869 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3870 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3874 pic16_emitcode("div","ab");
3875 pic16_emitcode("rrc","a");
3876 pic16_aopPut(AOP(result),"c",0);
3879 /*-----------------------------------------------------------------*/
3880 /* genDivOneByte : 8 bit division */
3881 /*-----------------------------------------------------------------*/
3882 static void genDivOneByte (operand *left,
3886 sym_link *opetype = operandType(result);
3891 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3892 size = AOP_SIZE(result) - 1;
3894 /* signed or unsigned */
3895 if (SPEC_USIGN(opetype)) {
3896 /* unsigned is easy */
3897 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3898 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3900 pic16_emitcode("div","ab");
3901 pic16_aopPut(AOP(result),"a",0);
3903 pic16_aopPut(AOP(result),zero,offset++);
3907 /* signed is a little bit more difficult */
3909 /* save the signs of the operands */
3910 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3912 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
3913 pic16_emitcode("push","acc"); /* save it on the stack */
3915 /* now sign adjust for both left & right */
3916 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
3918 lbl = newiTempLabel(NULL);
3919 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3920 pic16_emitcode("cpl","a");
3921 pic16_emitcode("inc","a");
3922 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3923 pic16_emitcode("mov","b,a");
3925 /* sign adjust left side */
3926 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3929 lbl = newiTempLabel(NULL);
3930 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3931 pic16_emitcode("cpl","a");
3932 pic16_emitcode("inc","a");
3933 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3935 /* now the division */
3936 pic16_emitcode("div","ab");
3937 /* we are interested in the lower order
3939 pic16_emitcode("mov","b,a");
3940 lbl = newiTempLabel(NULL);
3941 pic16_emitcode("pop","acc");
3942 /* if there was an over flow we don't
3943 adjust the sign of the result */
3944 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3945 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3947 pic16_emitcode("clr","a");
3948 pic16_emitcode("subb","a,b");
3949 pic16_emitcode("mov","b,a");
3950 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3952 /* now we are done */
3953 pic16_aopPut(AOP(result),"b",0);
3955 pic16_emitcode("mov","c,b.7");
3956 pic16_emitcode("subb","a,acc");
3959 pic16_aopPut(AOP(result),"a",offset++);
3963 /*-----------------------------------------------------------------*/
3964 /* genDiv - generates code for division */
3965 /*-----------------------------------------------------------------*/
3966 static void genDiv (iCode *ic)
3968 operand *left = IC_LEFT(ic);
3969 operand *right = IC_RIGHT(ic);
3970 operand *result= IC_RESULT(ic);
3972 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3973 /* assign the amsops */
3974 pic16_aopOp (left,ic,FALSE);
3975 pic16_aopOp (right,ic,FALSE);
3976 pic16_aopOp (result,ic,TRUE);
3978 /* special cases first */
3980 if (AOP_TYPE(left) == AOP_CRY &&
3981 AOP_TYPE(right)== AOP_CRY) {
3982 genDivbits(left,right,result);
3986 /* if both are of size == 1 */
3987 if (AOP_SIZE(left) == 1 &&
3988 AOP_SIZE(right) == 1 ) {
3989 genDivOneByte(left,right,result);
3993 /* should have been converted to function call */
3996 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3997 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3998 pic16_freeAsmop(result,NULL,ic,TRUE);
4001 /*-----------------------------------------------------------------*/
4002 /* genModbits :- modulus of bits */
4003 /*-----------------------------------------------------------------*/
4004 static void genModbits (operand *left,
4011 /* the result must be bit */
4012 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4013 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4017 pic16_emitcode("div","ab");
4018 pic16_emitcode("mov","a,b");
4019 pic16_emitcode("rrc","a");
4020 pic16_aopPut(AOP(result),"c",0);
4023 /*-----------------------------------------------------------------*/
4024 /* genModOneByte : 8 bit modulus */
4025 /*-----------------------------------------------------------------*/
4026 static void genModOneByte (operand *left,
4030 sym_link *opetype = operandType(result);
4034 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4035 /* signed or unsigned */
4036 if (SPEC_USIGN(opetype)) {
4037 /* unsigned is easy */
4038 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4039 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4041 pic16_emitcode("div","ab");
4042 pic16_aopPut(AOP(result),"b",0);
4046 /* signed is a little bit more difficult */
4048 /* save the signs of the operands */
4049 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4052 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4053 pic16_emitcode("push","acc"); /* save it on the stack */
4055 /* now sign adjust for both left & right */
4056 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4059 lbl = newiTempLabel(NULL);
4060 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4061 pic16_emitcode("cpl","a");
4062 pic16_emitcode("inc","a");
4063 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4064 pic16_emitcode("mov","b,a");
4066 /* sign adjust left side */
4067 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4070 lbl = newiTempLabel(NULL);
4071 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4072 pic16_emitcode("cpl","a");
4073 pic16_emitcode("inc","a");
4074 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4076 /* now the multiplication */
4077 pic16_emitcode("div","ab");
4078 /* we are interested in the lower order
4080 lbl = newiTempLabel(NULL);
4081 pic16_emitcode("pop","acc");
4082 /* if there was an over flow we don't
4083 adjust the sign of the result */
4084 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4085 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4087 pic16_emitcode("clr","a");
4088 pic16_emitcode("subb","a,b");
4089 pic16_emitcode("mov","b,a");
4090 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4092 /* now we are done */
4093 pic16_aopPut(AOP(result),"b",0);
4097 /*-----------------------------------------------------------------*/
4098 /* genMod - generates code for division */
4099 /*-----------------------------------------------------------------*/
4100 static void genMod (iCode *ic)
4102 operand *left = IC_LEFT(ic);
4103 operand *right = IC_RIGHT(ic);
4104 operand *result= IC_RESULT(ic);
4106 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4107 /* assign the amsops */
4108 pic16_aopOp (left,ic,FALSE);
4109 pic16_aopOp (right,ic,FALSE);
4110 pic16_aopOp (result,ic,TRUE);
4112 /* special cases first */
4114 if (AOP_TYPE(left) == AOP_CRY &&
4115 AOP_TYPE(right)== AOP_CRY) {
4116 genModbits(left,right,result);
4120 /* if both are of size == 1 */
4121 if (AOP_SIZE(left) == 1 &&
4122 AOP_SIZE(right) == 1 ) {
4123 genModOneByte(left,right,result);
4127 /* should have been converted to function call */
4131 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4132 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4133 pic16_freeAsmop(result,NULL,ic,TRUE);
4136 /*-----------------------------------------------------------------*/
4137 /* genIfxJump :- will create a jump depending on the ifx */
4138 /*-----------------------------------------------------------------*/
4140 note: May need to add parameter to indicate when a variable is in bit space.
4142 static void genIfxJump (iCode *ic, char *jval)
4145 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4146 /* if true label then we jump if condition
4148 if ( IC_TRUE(ic) ) {
4150 if(strcmp(jval,"a") == 0)
4152 else if (strcmp(jval,"c") == 0)
4155 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4156 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1));
4159 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4160 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
4164 /* false label is present */
4165 if(strcmp(jval,"a") == 0)
4167 else if (strcmp(jval,"c") == 0)
4170 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4171 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1));
4174 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4175 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
4180 /* mark the icode as generated */
4184 /*-----------------------------------------------------------------*/
4186 /*-----------------------------------------------------------------*/
4187 static void genSkip(iCode *ifx,int status_bit)
4189 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4193 if ( IC_TRUE(ifx) ) {
4194 switch(status_bit) {
4209 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4210 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4214 switch(status_bit) {
4228 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4229 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4235 /*-----------------------------------------------------------------*/
4237 /*-----------------------------------------------------------------*/
4238 static void genSkipc(resolvedIfx *rifx)
4248 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4249 rifx->generated = 1;
4252 /*-----------------------------------------------------------------*/
4254 /*-----------------------------------------------------------------*/
4255 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4260 if( (rifx->condition ^ invert_condition) & 1)
4265 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4266 rifx->generated = 1;
4270 /*-----------------------------------------------------------------*/
4272 /*-----------------------------------------------------------------*/
4273 static void genSkipz(iCode *ifx, int condition)
4284 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4286 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4289 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4291 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4296 /*-----------------------------------------------------------------*/
4298 /*-----------------------------------------------------------------*/
4299 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4305 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
4307 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
4310 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4311 rifx->generated = 1;
4315 /*-----------------------------------------------------------------*/
4316 /* genChkZeroes :- greater or less than comparison */
4317 /* For each byte in a literal that is zero, inclusive or the */
4318 /* the corresponding byte in the operand with W */
4319 /* returns true if any of the bytes are zero */
4320 /*-----------------------------------------------------------------*/
4321 static int genChkZeroes(operand *op, int lit, int size)
4328 i = (lit >> (size*8)) & 0xff;
4332 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4334 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4343 /*-----------------------------------------------------------------*/
4344 /* genCmp :- greater or less than comparison */
4345 /*-----------------------------------------------------------------*/
4346 static void genCmp (operand *left,operand *right,
4347 operand *result, iCode *ifx, int sign)
4349 int size; //, offset = 0 ;
4350 unsigned long lit = 0L,i = 0;
4351 resolvedIfx rFalseIfx;
4352 // resolvedIfx rTrueIfx;
4354 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4357 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4358 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4362 resolveIfx(&rFalseIfx,ifx);
4363 truelbl = newiTempLabel(NULL);
4364 size = max(AOP_SIZE(left),AOP_SIZE(right));
4366 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4370 /* if literal is on the right then swap with left */
4371 if ((AOP_TYPE(right) == AOP_LIT)) {
4372 operand *tmp = right ;
4373 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4374 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4377 lit = (lit - 1) & mask;
4380 rFalseIfx.condition ^= 1;
4383 } else if ((AOP_TYPE(left) == AOP_LIT)) {
4384 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4388 //if(IC_TRUE(ifx) == NULL)
4389 /* if left & right are bit variables */
4390 if (AOP_TYPE(left) == AOP_CRY &&
4391 AOP_TYPE(right) == AOP_CRY ) {
4392 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4393 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4395 /* subtract right from left if at the
4396 end the carry flag is set then we know that
4397 left is greater than right */
4401 symbol *lbl = newiTempLabel(NULL);
4404 if(AOP_TYPE(right) == AOP_LIT) {
4406 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4408 DEBUGpic16_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4415 genSkipCond(&rFalseIfx,left,size-1,7);
4417 /* no need to compare to 0...*/
4418 /* NOTE: this is a de-generate compare that most certainly
4419 * creates some dead code. */
4420 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4422 if(ifx) ifx->generated = 1;
4429 //i = (lit >> (size*8)) & 0xff;
4430 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4432 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4434 i = ((0-lit) & 0xff);
4437 /* lit is 0x7f, all signed chars are less than
4438 * this except for 0x7f itself */
4439 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4440 genSkipz2(&rFalseIfx,0);
4442 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4443 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4444 genSkipc(&rFalseIfx);
4449 genSkipz2(&rFalseIfx,1);
4451 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4452 genSkipc(&rFalseIfx);
4456 if(ifx) ifx->generated = 1;
4460 /* chars are out of the way. now do ints and longs */
4463 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4470 genSkipCond(&rFalseIfx,left,size,7);
4471 if(ifx) ifx->generated = 1;
4476 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4478 //rFalseIfx.condition ^= 1;
4479 //genSkipCond(&rFalseIfx,left,size,7);
4480 //rFalseIfx.condition ^= 1;
4482 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4483 if(rFalseIfx.condition)
4484 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4486 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4488 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4489 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4490 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4493 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4495 if(rFalseIfx.condition) {
4497 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4503 genSkipc(&rFalseIfx);
4504 pic16_emitpLabel(truelbl->key);
4505 if(ifx) ifx->generated = 1;
4512 if( (lit & 0xff) == 0) {
4513 /* lower byte is zero */
4514 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4515 i = ((lit >> 8) & 0xff) ^0x80;
4516 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4517 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4518 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4519 genSkipc(&rFalseIfx);
4522 if(ifx) ifx->generated = 1;
4527 /* Special cases for signed longs */
4528 if( (lit & 0xffffff) == 0) {
4529 /* lower byte is zero */
4530 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4531 i = ((lit >> 8*3) & 0xff) ^0x80;
4532 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4533 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4534 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4535 genSkipc(&rFalseIfx);
4538 if(ifx) ifx->generated = 1;
4546 if(lit & (0x80 << (size*8))) {
4547 /* lit is negative */
4548 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4550 //genSkipCond(&rFalseIfx,left,size,7);
4552 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4554 if(rFalseIfx.condition)
4555 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4557 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4561 /* lit is positive */
4562 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4563 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4564 if(rFalseIfx.condition)
4565 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4567 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4572 This works, but is only good for ints.
4573 It also requires a "known zero" register.
4574 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4575 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4576 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
4577 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4578 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4579 genSkipc(&rFalseIfx);
4581 pic16_emitpLabel(truelbl->key);
4582 if(ifx) ifx->generated = 1;
4586 /* There are no more special cases, so perform a general compare */
4588 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4589 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4593 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4595 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4597 //rFalseIfx.condition ^= 1;
4598 genSkipc(&rFalseIfx);
4600 pic16_emitpLabel(truelbl->key);
4602 if(ifx) ifx->generated = 1;
4609 /* sign is out of the way. So now do an unsigned compare */
4610 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4613 /* General case - compare to an unsigned literal on the right.*/
4615 i = (lit >> (size*8)) & 0xff;
4616 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4617 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4619 i = (lit >> (size*8)) & 0xff;
4622 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4624 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4626 /* this byte of the lit is zero,
4627 *if it's not the last then OR in the variable */
4629 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4634 pic16_emitpLabel(lbl->key);
4635 //if(emitFinalCheck)
4636 genSkipc(&rFalseIfx);
4638 pic16_emitpLabel(truelbl->key);
4640 if(ifx) ifx->generated = 1;
4647 if(AOP_TYPE(left) == AOP_LIT) {
4648 //symbol *lbl = newiTempLabel(NULL);
4650 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4653 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4656 if((lit == 0) && (sign == 0)){
4659 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4661 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
4663 genSkipz2(&rFalseIfx,0);
4664 if(ifx) ifx->generated = 1;
4671 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4672 /* degenerate compare can never be true */
4673 if(rFalseIfx.condition == 0)
4674 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4676 if(ifx) ifx->generated = 1;
4681 /* signed comparisons to a literal byte */
4683 int lp1 = (lit+1) & 0xff;
4685 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4688 rFalseIfx.condition ^= 1;
4689 genSkipCond(&rFalseIfx,right,0,7);
4692 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4693 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4694 genSkipz2(&rFalseIfx,1);
4697 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4698 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4699 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4700 rFalseIfx.condition ^= 1;
4701 genSkipc(&rFalseIfx);
4705 /* unsigned comparisons to a literal byte */
4707 switch(lit & 0xff ) {
4709 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4710 genSkipz2(&rFalseIfx,0);
4713 rFalseIfx.condition ^= 1;
4714 genSkipCond(&rFalseIfx,right,0,7);
4718 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
4719 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4720 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4721 rFalseIfx.condition ^= 1;
4722 if (AOP_TYPE(result) == AOP_CRY)
4723 genSkipc(&rFalseIfx);
4725 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4726 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4732 if(ifx) ifx->generated = 1;
4738 /* Size is greater than 1 */
4746 /* this means lit = 0xffffffff, or -1 */
4749 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
4750 rFalseIfx.condition ^= 1;
4751 genSkipCond(&rFalseIfx,right,size,7);
4752 if(ifx) ifx->generated = 1;
4759 if(rFalseIfx.condition) {
4760 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4761 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4764 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4766 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4770 if(rFalseIfx.condition) {
4771 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4772 pic16_emitpLabel(truelbl->key);
4774 rFalseIfx.condition ^= 1;
4775 genSkipCond(&rFalseIfx,right,s,7);
4778 if(ifx) ifx->generated = 1;
4782 if((size == 1) && (0 == (lp1&0xff))) {
4783 /* lower byte of signed word is zero */
4784 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
4785 i = ((lp1 >> 8) & 0xff) ^0x80;
4786 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4787 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4788 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4789 rFalseIfx.condition ^= 1;
4790 genSkipc(&rFalseIfx);
4793 if(ifx) ifx->generated = 1;
4797 if(lit & (0x80 << (size*8))) {
4798 /* Lit is less than zero */
4799 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
4800 //rFalseIfx.condition ^= 1;
4801 //genSkipCond(&rFalseIfx,left,size,7);
4802 //rFalseIfx.condition ^= 1;
4803 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4804 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4806 if(rFalseIfx.condition)
4807 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4809 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4813 /* Lit is greater than or equal to zero */
4814 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
4815 //rFalseIfx.condition ^= 1;
4816 //genSkipCond(&rFalseIfx,right,size,7);
4817 //rFalseIfx.condition ^= 1;
4819 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4820 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4822 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4823 if(rFalseIfx.condition)
4824 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4826 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4831 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4832 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4836 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4838 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4840 rFalseIfx.condition ^= 1;
4841 //rFalseIfx.condition = 1;
4842 genSkipc(&rFalseIfx);
4844 pic16_emitpLabel(truelbl->key);
4846 if(ifx) ifx->generated = 1;
4851 /* compare word or long to an unsigned literal on the right.*/
4856 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4859 break; /* handled above */
4862 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4864 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4865 genSkipz2(&rFalseIfx,0);
4869 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4871 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4874 if(rFalseIfx.condition)
4875 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4877 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4880 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
4881 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4883 rFalseIfx.condition ^= 1;
4884 genSkipc(&rFalseIfx);
4887 pic16_emitpLabel(truelbl->key);
4889 if(ifx) ifx->generated = 1;
4895 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4896 i = (lit >> (size*8)) & 0xff;
4898 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4899 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4902 i = (lit >> (size*8)) & 0xff;
4905 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4907 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4909 /* this byte of the lit is zero,
4910 *if it's not the last then OR in the variable */
4912 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4917 pic16_emitpLabel(lbl->key);
4919 rFalseIfx.condition ^= 1;
4920 genSkipc(&rFalseIfx);
4924 pic16_emitpLabel(truelbl->key);
4925 if(ifx) ifx->generated = 1;
4929 /* Compare two variables */
4931 DEBUGpic16_emitcode(";sign","%d",sign);
4935 /* Sigh. thus sucks... */
4937 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4938 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
4939 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
4940 pic16_emitpcode(POC_XORWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
4941 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
4942 pic16_emitpcode(POC_SUBFW, pic16_popRegFromIdx(pic16_Gstack_base_addr));
4944 /* Signed char comparison */
4945 /* Special thanks to Nikolai Golovchenko for this snippet */
4946 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4947 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
4948 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
4949 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
4950 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
4951 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4953 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4954 genSkipc(&rFalseIfx);
4956 if(ifx) ifx->generated = 1;
4962 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4963 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4967 /* The rest of the bytes of a multi-byte compare */
4971 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
4974 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4975 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4980 pic16_emitpLabel(lbl->key);
4982 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4983 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
4984 (AOP_TYPE(result) == AOP_REG)) {
4985 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4986 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4988 genSkipc(&rFalseIfx);
4990 //genSkipc(&rFalseIfx);
4991 if(ifx) ifx->generated = 1;
4998 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4999 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5000 pic16_outBitC(result);
5002 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5003 /* if the result is used in the next
5004 ifx conditional branch then generate
5005 code a little differently */
5007 genIfxJump (ifx,"c");
5009 pic16_outBitC(result);
5010 /* leave the result in acc */
5015 /*-----------------------------------------------------------------*/
5016 /* genCmpGt :- greater than comparison */
5017 /*-----------------------------------------------------------------*/
5018 static void genCmpGt (iCode *ic, iCode *ifx)
5020 operand *left, *right, *result;
5021 sym_link *letype , *retype;
5024 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5026 right= IC_RIGHT(ic);
5027 result = IC_RESULT(ic);
5029 letype = getSpec(operandType(left));
5030 retype =getSpec(operandType(right));
5031 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5032 /* assign the amsops */
5033 pic16_aopOp (left,ic,FALSE);
5034 pic16_aopOp (right,ic,FALSE);
5035 pic16_aopOp (result,ic,TRUE);
5037 genCmp(right, left, result, ifx, sign);
5039 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5040 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5041 pic16_freeAsmop(result,NULL,ic,TRUE);
5044 /*-----------------------------------------------------------------*/
5045 /* genCmpLt - less than comparisons */
5046 /*-----------------------------------------------------------------*/
5047 static void genCmpLt (iCode *ic, iCode *ifx)
5049 operand *left, *right, *result;
5050 sym_link *letype , *retype;
5053 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5055 right= IC_RIGHT(ic);
5056 result = IC_RESULT(ic);
5058 letype = getSpec(operandType(left));
5059 retype =getSpec(operandType(right));
5060 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5062 /* assign the amsops */
5063 pic16_aopOp (left,ic,FALSE);
5064 pic16_aopOp (right,ic,FALSE);
5065 pic16_aopOp (result,ic,TRUE);
5067 genCmp(left, right, result, ifx, sign);
5069 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5070 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5071 pic16_freeAsmop(result,NULL,ic,TRUE);
5074 /*-----------------------------------------------------------------*/
5075 /* genc16bit2lit - compare a 16 bit value to a literal */
5076 /*-----------------------------------------------------------------*/
5077 static void genc16bit2lit(operand *op, int lit, int offset)
5081 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
5082 if( (lit&0xff) == 0)
5087 switch( BYTEofLONG(lit,i)) {
5089 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5092 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5095 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5098 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5099 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5104 switch( BYTEofLONG(lit,i)) {
5106 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
5110 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5114 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5117 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5119 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
5125 /*-----------------------------------------------------------------*/
5126 /* gencjneshort - compare and jump if not equal */
5127 /*-----------------------------------------------------------------*/
5128 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
5130 int size = max(AOP_SIZE(left),AOP_SIZE(right));
5132 int res_offset = 0; /* the result may be a different size then left or right */
5133 int res_size = AOP_SIZE(result);
5137 unsigned long lit = 0L;
5138 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5139 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5141 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
5142 resolveIfx(&rIfx,ifx);
5143 lbl = newiTempLabel(NULL);
5146 /* if the left side is a literal or
5147 if the right is in a pointer register and left
5149 if ((AOP_TYPE(left) == AOP_LIT) ||
5150 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5155 if(AOP_TYPE(right) == AOP_LIT)
5156 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5158 /* if the right side is a literal then anything goes */
5159 if (AOP_TYPE(right) == AOP_LIT &&
5160 AOP_TYPE(left) != AOP_DIR ) {
5163 genc16bit2lit(left, lit, 0);
5165 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5168 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5171 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5172 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5174 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5178 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5180 if(res_offset < res_size-1)
5188 /* if the right side is in a register or in direct space or
5189 if the left is a pointer register & right is not */
5190 else if (AOP_TYPE(right) == AOP_REG ||
5191 AOP_TYPE(right) == AOP_DIR ||
5192 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5193 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5194 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5195 int lbl_key = lbl->key;
5198 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
5199 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5201 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
5202 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
5203 __FUNCTION__,__LINE__);
5207 /* switch(size) { */
5209 /* genc16bit2lit(left, lit, 0); */
5211 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
5216 if((AOP_TYPE(left) == AOP_DIR) &&
5217 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5219 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5220 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5222 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5224 switch (lit & 0xff) {
5226 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5229 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5230 pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5231 //pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5235 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5236 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5237 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5238 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5242 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5243 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5248 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5251 if(AOP_TYPE(result) == AOP_CRY) {
5252 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5257 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5259 /* fix me. probably need to check result size too */
5260 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
5265 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5266 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5273 if(res_offset < res_size-1)
5278 } else if(AOP_TYPE(right) == AOP_REG &&
5279 AOP_TYPE(left) != AOP_DIR){
5282 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5283 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5284 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5289 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5291 if(res_offset < res_size-1)
5296 /* right is a pointer reg need both a & b */
5298 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
5300 pic16_emitcode("mov","b,%s",l);
5301 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5302 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
5307 pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5309 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5311 pic16_emitpLabel(lbl->key);
5313 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5320 /*-----------------------------------------------------------------*/
5321 /* gencjne - compare and jump if not equal */
5322 /*-----------------------------------------------------------------*/
5323 static void gencjne(operand *left, operand *right, iCode *ifx)
5325 symbol *tlbl = newiTempLabel(NULL);
5327 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5328 gencjneshort(left, right, lbl);
5330 pic16_emitcode("mov","a,%s",one);
5331 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5332 pic16_emitcode("","%05d_DS_:",lbl->key+100);
5333 pic16_emitcode("clr","a");
5334 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5336 pic16_emitpLabel(lbl->key);
5337 pic16_emitpLabel(tlbl->key);
5342 /*-----------------------------------------------------------------*/
5343 /* genCmpEq - generates code for equal to */
5344 /*-----------------------------------------------------------------*/
5345 static void genCmpEq (iCode *ic, iCode *ifx)
5347 operand *left, *right, *result;
5348 unsigned long lit = 0L;
5350 symbol *falselbl = newiTempLabel(NULL);
5353 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5356 DEBUGpic16_emitcode ("; ifx is non-null","");
5358 DEBUGpic16_emitcode ("; ifx is null","");
5360 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5361 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5362 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5364 size = max(AOP_SIZE(left),AOP_SIZE(right));
5366 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5368 /* if literal, literal on the right or
5369 if the right is in a pointer register and left
5371 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
5372 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5373 operand *tmp = right ;
5379 if(ifx && !AOP_SIZE(result)){
5381 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
5382 /* if they are both bit variables */
5383 if (AOP_TYPE(left) == AOP_CRY &&
5384 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5385 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
5386 if(AOP_TYPE(right) == AOP_LIT){
5387 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5389 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5390 pic16_emitcode("cpl","c");
5391 } else if(lit == 1L) {
5392 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5394 pic16_emitcode("clr","c");
5396 /* AOP_TYPE(right) == AOP_CRY */
5398 symbol *lbl = newiTempLabel(NULL);
5399 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5400 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5401 pic16_emitcode("cpl","c");
5402 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5404 /* if true label then we jump if condition
5406 tlbl = newiTempLabel(NULL);
5407 if ( IC_TRUE(ifx) ) {
5408 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5409 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5411 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
5412 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5414 pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5417 /* left and right are both bit variables, result is carry */
5420 resolveIfx(&rIfx,ifx);
5422 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
5423 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
5424 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
5425 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
5430 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
5432 /* They're not both bit variables. Is the right a literal? */
5433 if(AOP_TYPE(right) == AOP_LIT) {
5434 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5439 switch(lit & 0xff) {
5441 if ( IC_TRUE(ifx) ) {
5442 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
5444 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5446 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5447 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5451 if ( IC_TRUE(ifx) ) {
5452 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
5454 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5456 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5457 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5461 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5463 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5468 /* end of size == 1 */
5472 genc16bit2lit(left,lit,offset);
5475 /* end of size == 2 */
5480 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5481 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
5482 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5483 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5486 /* search for patterns that can be optimized */
5488 genc16bit2lit(left,lit,0);
5492 emitSKPZ; // if hi word unequal
5494 emitSKPNZ; // if hi word equal
5496 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
5497 genc16bit2lit(left,lit,2);
5500 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5501 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5505 pic16_emitpLabel(falselbl->key);
5514 } else if(AOP_TYPE(right) == AOP_CRY ) {
5515 /* we know the left is not a bit, but that the right is */
5516 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5517 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
5518 pic16_popGet(AOP(right),offset));
5519 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
5521 /* if the two are equal, then W will be 0 and the Z bit is set
5522 * we could test Z now, or go ahead and check the high order bytes if
5523 * the variable we're comparing is larger than a byte. */
5526 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
5528 if ( IC_TRUE(ifx) ) {
5530 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5531 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5534 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5535 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5539 /* They're both variables that are larger than bits */
5542 tlbl = newiTempLabel(NULL);
5545 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5546 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5548 if ( IC_TRUE(ifx) ) {
5552 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
5554 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
5555 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
5559 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
5562 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5563 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5568 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
5570 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5571 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5575 if(s>1 && IC_TRUE(ifx)) {
5576 pic16_emitpLabel(tlbl->key);
5577 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);
5581 /* mark the icode as generated */
5586 /* if they are both bit variables */
5587 if (AOP_TYPE(left) == AOP_CRY &&
5588 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5589 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
5590 if(AOP_TYPE(right) == AOP_LIT){
5591 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5593 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5594 pic16_emitcode("cpl","c");
5595 } else if(lit == 1L) {
5596 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5598 pic16_emitcode("clr","c");
5600 /* AOP_TYPE(right) == AOP_CRY */
5602 symbol *lbl = newiTempLabel(NULL);
5603 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5604 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5605 pic16_emitcode("cpl","c");
5606 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5609 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5610 pic16_outBitC(result);
5614 genIfxJump (ifx,"c");
5617 /* if the result is used in an arithmetic operation
5618 then put the result in place */
5619 pic16_outBitC(result);
5622 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
5623 gencjne(left,right,result,ifx);
5626 gencjne(left,right,newiTempLabel(NULL));
5628 if(IC_TRUE(ifx)->key)
5629 gencjne(left,right,IC_TRUE(ifx)->key);
5631 gencjne(left,right,IC_FALSE(ifx)->key);
5635 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5636 pic16_aopPut(AOP(result),"a",0);
5641 genIfxJump (ifx,"a");
5645 /* if the result is used in an arithmetic operation
5646 then put the result in place */
5648 if (AOP_TYPE(result) != AOP_CRY)
5649 pic16_outAcc(result);
5651 /* leave the result in acc */
5655 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5656 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5657 pic16_freeAsmop(result,NULL,ic,TRUE);
5660 /*-----------------------------------------------------------------*/
5661 /* ifxForOp - returns the icode containing the ifx for operand */
5662 /*-----------------------------------------------------------------*/
5663 static iCode *ifxForOp ( operand *op, iCode *ic )
5665 /* if true symbol then needs to be assigned */
5666 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5667 if (IS_TRUE_SYMOP(op))
5670 /* if this has register type condition and
5671 the next instruction is ifx with the same operand
5672 and live to of the operand is upto the ifx only then */
5674 ic->next->op == IFX &&
5675 IC_COND(ic->next)->key == op->key &&
5676 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5680 ic->next->op == IFX &&
5681 IC_COND(ic->next)->key == op->key) {
5682 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5686 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
5688 ic->next->op == IFX)
5689 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
5692 ic->next->op == IFX &&
5693 IC_COND(ic->next)->key == op->key) {
5694 DEBUGpic16_emitcode ("; "," key is okay");
5695 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
5696 OP_SYMBOL(op)->liveTo,
5703 /*-----------------------------------------------------------------*/
5704 /* genAndOp - for && operation */
5705 /*-----------------------------------------------------------------*/
5706 static void genAndOp (iCode *ic)
5708 operand *left,*right, *result;
5711 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5712 /* note here that && operations that are in an
5713 if statement are taken away by backPatchLabels
5714 only those used in arthmetic operations remain */
5715 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5716 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5717 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5719 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5721 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5722 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
5723 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
5725 /* if both are bit variables */
5726 /* if (AOP_TYPE(left) == AOP_CRY && */
5727 /* AOP_TYPE(right) == AOP_CRY ) { */
5728 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5729 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5730 /* pic16_outBitC(result); */
5732 /* tlbl = newiTempLabel(NULL); */
5733 /* pic16_toBoolean(left); */
5734 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
5735 /* pic16_toBoolean(right); */
5736 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
5737 /* pic16_outBitAcc(result); */
5740 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5741 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5742 pic16_freeAsmop(result,NULL,ic,TRUE);
5746 /*-----------------------------------------------------------------*/
5747 /* genOrOp - for || operation */
5748 /*-----------------------------------------------------------------*/
5751 modified this code, but it doesn't appear to ever get called
5754 static void genOrOp (iCode *ic)
5756 operand *left,*right, *result;
5759 /* note here that || operations that are in an
5760 if statement are taken away by backPatchLabels
5761 only those used in arthmetic operations remain */
5762 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5763 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5764 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5765 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5767 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5769 /* if both are bit variables */
5770 if (AOP_TYPE(left) == AOP_CRY &&
5771 AOP_TYPE(right) == AOP_CRY ) {
5772 pic16_emitcode("clrc","");
5773 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5774 AOP(left)->aopu.aop_dir,
5775 AOP(left)->aopu.aop_dir);
5776 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5777 AOP(right)->aopu.aop_dir,
5778 AOP(right)->aopu.aop_dir);
5779 pic16_emitcode("setc","");
5782 tlbl = newiTempLabel(NULL);
5783 pic16_toBoolean(left);
5785 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5786 pic16_toBoolean(right);
5787 pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5789 pic16_outBitAcc(result);
5792 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5793 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5794 pic16_freeAsmop(result,NULL,ic,TRUE);
5797 /*-----------------------------------------------------------------*/
5798 /* isLiteralBit - test if lit == 2^n */
5799 /*-----------------------------------------------------------------*/
5800 static int isLiteralBit(unsigned long lit)
5802 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5803 0x100L,0x200L,0x400L,0x800L,
5804 0x1000L,0x2000L,0x4000L,0x8000L,
5805 0x10000L,0x20000L,0x40000L,0x80000L,
5806 0x100000L,0x200000L,0x400000L,0x800000L,
5807 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5808 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5811 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5812 for(idx = 0; idx < 32; idx++)
5818 /*-----------------------------------------------------------------*/
5819 /* continueIfTrue - */
5820 /*-----------------------------------------------------------------*/
5821 static void continueIfTrue (iCode *ic)
5823 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5825 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5829 /*-----------------------------------------------------------------*/
5831 /*-----------------------------------------------------------------*/
5832 static void jumpIfTrue (iCode *ic)
5834 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5836 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5840 /*-----------------------------------------------------------------*/
5841 /* jmpTrueOrFalse - */
5842 /*-----------------------------------------------------------------*/
5843 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5845 // ugly but optimized by peephole
5846 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5848 symbol *nlbl = newiTempLabel(NULL);
5849 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5850 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5851 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5852 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
5855 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5856 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5861 /*-----------------------------------------------------------------*/
5862 /* genAnd - code for and */
5863 /*-----------------------------------------------------------------*/
5864 static void genAnd (iCode *ic, iCode *ifx)
5866 operand *left, *right, *result;
5868 unsigned long lit = 0L;
5873 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5874 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
5875 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5876 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5878 resolveIfx(&rIfx,ifx);
5880 /* if left is a literal & right is not then exchange them */
5881 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5882 AOP_NEEDSACC(left)) {
5883 operand *tmp = right ;
5888 /* if result = right then exchange them */
5889 if(pic16_sameRegs(AOP(result),AOP(right))){
5890 operand *tmp = right ;
5895 /* if right is bit then exchange them */
5896 if (AOP_TYPE(right) == AOP_CRY &&
5897 AOP_TYPE(left) != AOP_CRY){
5898 operand *tmp = right ;
5902 if(AOP_TYPE(right) == AOP_LIT)
5903 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5905 size = AOP_SIZE(result);
5907 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5910 // result = bit & yy;
5911 if (AOP_TYPE(left) == AOP_CRY){
5912 // c = bit & literal;
5913 if(AOP_TYPE(right) == AOP_LIT){
5915 if(size && pic16_sameRegs(AOP(result),AOP(left)))
5918 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5921 if(size && (AOP_TYPE(result) == AOP_CRY)){
5922 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5925 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5929 pic16_emitcode("clr","c");
5932 if (AOP_TYPE(right) == AOP_CRY){
5934 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5935 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5938 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
5940 pic16_emitcode("rrc","a");
5941 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5947 pic16_outBitC(result);
5949 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5950 genIfxJump(ifx, "c");
5954 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5955 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5956 if((AOP_TYPE(right) == AOP_LIT) &&
5957 (AOP_TYPE(result) == AOP_CRY) &&
5958 (AOP_TYPE(left) != AOP_CRY)){
5959 int posbit = isLiteralBit(lit);
5963 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5966 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
5972 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5973 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
5975 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5976 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
5979 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5980 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5981 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5988 symbol *tlbl = newiTempLabel(NULL);
5989 int sizel = AOP_SIZE(left);
5991 pic16_emitcode("setb","c");
5993 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5994 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5996 if((posbit = isLiteralBit(bytelit)) != 0)
5997 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5999 if(bytelit != 0x0FFL)
6000 pic16_emitcode("anl","a,%s",
6001 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
6002 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6007 // bit = left & literal
6009 pic16_emitcode("clr","c");
6010 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6012 // if(left & literal)
6015 jmpTrueOrFalse(ifx, tlbl);
6019 pic16_outBitC(result);
6023 /* if left is same as result */
6024 if(pic16_sameRegs(AOP(result),AOP(left))){
6026 for(;size--; offset++,lit>>=8) {
6027 if(AOP_TYPE(right) == AOP_LIT){
6028 switch(lit & 0xff) {
6030 /* and'ing with 0 has clears the result */
6031 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6032 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6035 /* and'ing with 0xff is a nop when the result and left are the same */
6040 int p = my_powof2( (~lit) & 0xff );
6042 /* only one bit is set in the literal, so use a bcf instruction */
6043 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
6044 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6047 pic16_emitcode("movlw","0x%x", (lit & 0xff));
6048 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6049 if(know_W != (lit&0xff))
6050 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6052 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6057 if (AOP_TYPE(left) == AOP_ACC) {
6058 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6060 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6061 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6068 // left & result in different registers
6069 if(AOP_TYPE(result) == AOP_CRY){
6071 // if(size), result in bit
6072 // if(!size && ifx), conditional oper: if(left & right)
6073 symbol *tlbl = newiTempLabel(NULL);
6074 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
6076 pic16_emitcode("setb","c");
6078 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6079 pic16_emitcode("anl","a,%s",
6080 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6081 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6086 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6087 pic16_outBitC(result);
6089 jmpTrueOrFalse(ifx, tlbl);
6091 for(;(size--);offset++) {
6093 // result = left & right
6094 if(AOP_TYPE(right) == AOP_LIT){
6095 int t = (lit >> (offset*8)) & 0x0FFL;
6098 pic16_emitcode("clrf","%s",
6099 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6100 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6103 pic16_emitcode("movf","%s,w",
6104 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6105 pic16_emitcode("movwf","%s",
6106 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6107 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6108 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6111 pic16_emitcode("movlw","0x%x",t);
6112 pic16_emitcode("andwf","%s,w",
6113 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6114 pic16_emitcode("movwf","%s",
6115 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6117 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6118 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6119 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6124 if (AOP_TYPE(left) == AOP_ACC) {
6125 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6126 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6128 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6129 pic16_emitcode("andwf","%s,w",
6130 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6131 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6132 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6134 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6135 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6141 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6142 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6143 pic16_freeAsmop(result,NULL,ic,TRUE);
6146 /*-----------------------------------------------------------------*/
6147 /* genOr - code for or */
6148 /*-----------------------------------------------------------------*/
6149 static void genOr (iCode *ic, iCode *ifx)
6151 operand *left, *right, *result;
6153 unsigned long lit = 0L;
6155 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6157 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6158 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6159 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6161 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6163 /* if left is a literal & right is not then exchange them */
6164 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6165 AOP_NEEDSACC(left)) {
6166 operand *tmp = right ;
6171 /* if result = right then exchange them */
6172 if(pic16_sameRegs(AOP(result),AOP(right))){
6173 operand *tmp = right ;
6178 /* if right is bit then exchange them */
6179 if (AOP_TYPE(right) == AOP_CRY &&
6180 AOP_TYPE(left) != AOP_CRY){
6181 operand *tmp = right ;
6186 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6188 if(AOP_TYPE(right) == AOP_LIT)
6189 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6191 size = AOP_SIZE(result);
6195 if (AOP_TYPE(left) == AOP_CRY){
6196 if(AOP_TYPE(right) == AOP_LIT){
6197 // c = bit & literal;
6199 // lit != 0 => result = 1
6200 if(AOP_TYPE(result) == AOP_CRY){
6202 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6203 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6204 // AOP(result)->aopu.aop_dir,
6205 // AOP(result)->aopu.aop_dir);
6207 continueIfTrue(ifx);
6211 // lit == 0 => result = left
6212 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6214 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
6217 if (AOP_TYPE(right) == AOP_CRY){
6218 if(pic16_sameRegs(AOP(result),AOP(left))){
6220 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6221 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
6222 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6224 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6225 AOP(result)->aopu.aop_dir,
6226 AOP(result)->aopu.aop_dir);
6227 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6228 AOP(right)->aopu.aop_dir,
6229 AOP(right)->aopu.aop_dir);
6230 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6231 AOP(result)->aopu.aop_dir,
6232 AOP(result)->aopu.aop_dir);
6234 if( AOP_TYPE(result) == AOP_ACC) {
6235 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
6236 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6237 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6238 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
6242 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6243 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6244 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6245 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6247 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6248 AOP(result)->aopu.aop_dir,
6249 AOP(result)->aopu.aop_dir);
6250 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6251 AOP(right)->aopu.aop_dir,
6252 AOP(right)->aopu.aop_dir);
6253 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6254 AOP(left)->aopu.aop_dir,
6255 AOP(left)->aopu.aop_dir);
6256 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6257 AOP(result)->aopu.aop_dir,
6258 AOP(result)->aopu.aop_dir);
6263 symbol *tlbl = newiTempLabel(NULL);
6264 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6267 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6268 if( AOP_TYPE(right) == AOP_ACC) {
6269 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
6271 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6272 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6277 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
6278 pic16_emitcode(";XXX setb","c");
6279 pic16_emitcode(";XXX jb","%s,%05d_DS_",
6280 AOP(left)->aopu.aop_dir,tlbl->key+100);
6281 pic16_toBoolean(right);
6282 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6283 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6284 jmpTrueOrFalse(ifx, tlbl);
6288 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6295 pic16_outBitC(result);
6297 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6298 genIfxJump(ifx, "c");
6302 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6303 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6304 if((AOP_TYPE(right) == AOP_LIT) &&
6305 (AOP_TYPE(result) == AOP_CRY) &&
6306 (AOP_TYPE(left) != AOP_CRY)){
6308 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6311 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6313 continueIfTrue(ifx);
6316 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6317 // lit = 0, result = boolean(left)
6319 pic16_emitcode(";XXX setb","c");
6320 pic16_toBoolean(right);
6322 symbol *tlbl = newiTempLabel(NULL);
6323 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6325 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6327 genIfxJump (ifx,"a");
6331 pic16_outBitC(result);
6335 /* if left is same as result */
6336 if(pic16_sameRegs(AOP(result),AOP(left))){
6338 for(;size--; offset++,lit>>=8) {
6339 if(AOP_TYPE(right) == AOP_LIT){
6340 if((lit & 0xff) == 0)
6341 /* or'ing with 0 has no effect */
6344 int p = my_powof2(lit & 0xff);
6346 /* only one bit is set in the literal, so use a bsf instruction */
6347 pic16_emitpcode(POC_BSF,
6348 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6350 if(know_W != (lit & 0xff))
6351 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6352 know_W = lit & 0xff;
6353 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6358 if (AOP_TYPE(left) == AOP_ACC) {
6359 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
6360 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6362 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
6363 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6365 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6366 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6372 // left & result in different registers
6373 if(AOP_TYPE(result) == AOP_CRY){
6375 // if(size), result in bit
6376 // if(!size && ifx), conditional oper: if(left | right)
6377 symbol *tlbl = newiTempLabel(NULL);
6378 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6379 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6383 pic16_emitcode(";XXX setb","c");
6385 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6386 pic16_emitcode(";XXX orl","a,%s",
6387 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6388 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6393 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6394 pic16_outBitC(result);
6396 jmpTrueOrFalse(ifx, tlbl);
6397 } else for(;(size--);offset++){
6399 // result = left & right
6400 if(AOP_TYPE(right) == AOP_LIT){
6401 int t = (lit >> (offset*8)) & 0x0FFL;
6404 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
6405 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6407 pic16_emitcode("movf","%s,w",
6408 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6409 pic16_emitcode("movwf","%s",
6410 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6413 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6414 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
6415 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6417 pic16_emitcode("movlw","0x%x",t);
6418 pic16_emitcode("iorwf","%s,w",
6419 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6420 pic16_emitcode("movwf","%s",
6421 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6427 // faster than result <- left, anl result,right
6428 // and better if result is SFR
6429 if (AOP_TYPE(left) == AOP_ACC) {
6430 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
6431 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6433 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
6434 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
6436 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6437 pic16_emitcode("iorwf","%s,w",
6438 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6440 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6441 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6446 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6447 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6448 pic16_freeAsmop(result,NULL,ic,TRUE);
6451 /*-----------------------------------------------------------------*/
6452 /* genXor - code for xclusive or */
6453 /*-----------------------------------------------------------------*/
6454 static void genXor (iCode *ic, iCode *ifx)
6456 operand *left, *right, *result;
6458 unsigned long lit = 0L;
6460 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6462 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6463 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6464 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6466 /* if left is a literal & right is not ||
6467 if left needs acc & right does not */
6468 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6469 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6470 operand *tmp = right ;
6475 /* if result = right then exchange them */
6476 if(pic16_sameRegs(AOP(result),AOP(right))){
6477 operand *tmp = right ;
6482 /* if right is bit then exchange them */
6483 if (AOP_TYPE(right) == AOP_CRY &&
6484 AOP_TYPE(left) != AOP_CRY){
6485 operand *tmp = right ;
6489 if(AOP_TYPE(right) == AOP_LIT)
6490 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6492 size = AOP_SIZE(result);
6496 if (AOP_TYPE(left) == AOP_CRY){
6497 if(AOP_TYPE(right) == AOP_LIT){
6498 // c = bit & literal;
6500 // lit>>1 != 0 => result = 1
6501 if(AOP_TYPE(result) == AOP_CRY){
6503 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
6504 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6506 continueIfTrue(ifx);
6509 pic16_emitcode("setb","c");
6513 // lit == 0, result = left
6514 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6516 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6518 // lit == 1, result = not(left)
6519 if(size && pic16_sameRegs(AOP(result),AOP(left))){
6520 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
6521 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
6522 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6525 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6526 pic16_emitcode("cpl","c");
6533 symbol *tlbl = newiTempLabel(NULL);
6534 if (AOP_TYPE(right) == AOP_CRY){
6536 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6539 int sizer = AOP_SIZE(right);
6541 // if val>>1 != 0, result = 1
6542 pic16_emitcode("setb","c");
6544 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
6546 // test the msb of the lsb
6547 pic16_emitcode("anl","a,#0xfe");
6548 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6552 pic16_emitcode("rrc","a");
6554 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6555 pic16_emitcode("cpl","c");
6556 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
6561 pic16_outBitC(result);
6563 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6564 genIfxJump(ifx, "c");
6568 if(pic16_sameRegs(AOP(result),AOP(left))){
6569 /* if left is same as result */
6570 for(;size--; offset++) {
6571 if(AOP_TYPE(right) == AOP_LIT){
6572 int t = (lit >> (offset*8)) & 0x0FFL;
6576 if (IS_AOP_PREG(left)) {
6577 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6578 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6579 pic16_aopPut(AOP(result),"a",offset);
6581 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6582 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6583 pic16_emitcode("xrl","%s,%s",
6584 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
6585 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6588 if (AOP_TYPE(left) == AOP_ACC)
6589 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6591 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6592 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6594 if (IS_AOP_PREG(left)) {
6595 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6596 pic16_aopPut(AOP(result),"a",offset);
6598 pic16_emitcode("xrl","%s,a",
6599 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6605 // left & result in different registers
6606 if(AOP_TYPE(result) == AOP_CRY){
6608 // if(size), result in bit
6609 // if(!size && ifx), conditional oper: if(left ^ right)
6610 symbol *tlbl = newiTempLabel(NULL);
6611 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6613 pic16_emitcode("setb","c");
6615 if((AOP_TYPE(right) == AOP_LIT) &&
6616 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6617 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6619 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6620 pic16_emitcode("xrl","a,%s",
6621 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6623 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6628 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6629 pic16_outBitC(result);
6631 jmpTrueOrFalse(ifx, tlbl);
6632 } else for(;(size--);offset++){
6634 // result = left & right
6635 if(AOP_TYPE(right) == AOP_LIT){
6636 int t = (lit >> (offset*8)) & 0x0FFL;
6639 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6640 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6641 pic16_emitcode("movf","%s,w",
6642 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6643 pic16_emitcode("movwf","%s",
6644 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6647 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
6648 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6649 pic16_emitcode("comf","%s,w",
6650 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6651 pic16_emitcode("movwf","%s",
6652 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6655 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6656 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6657 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6658 pic16_emitcode("movlw","0x%x",t);
6659 pic16_emitcode("xorwf","%s,w",
6660 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6661 pic16_emitcode("movwf","%s",
6662 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6668 // faster than result <- left, anl result,right
6669 // and better if result is SFR
6670 if (AOP_TYPE(left) == AOP_ACC) {
6671 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6672 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6674 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6675 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6676 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6677 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6679 if ( AOP_TYPE(result) != AOP_ACC){
6680 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6681 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6687 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6688 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6689 pic16_freeAsmop(result,NULL,ic,TRUE);
6692 /*-----------------------------------------------------------------*/
6693 /* genInline - write the inline code out */
6694 /*-----------------------------------------------------------------*/
6695 static void genInline (iCode *ic)
6697 char *buffer, *bp, *bp1;
6699 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6701 _G.inLine += (!options.asmpeep);
6703 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6704 strcpy(buffer,IC_INLINE(ic));
6706 // fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
6708 /* emit each line as a code */
6714 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6722 /* print label, use this special format with NULL directive
6723 * to denote that the argument should not be indented with tab */
6724 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6731 if ((bp1 != bp) && *bp1)
6732 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6737 _G.inLine -= (!options.asmpeep);
6740 /*-----------------------------------------------------------------*/
6741 /* genRRC - rotate right with carry */
6742 /*-----------------------------------------------------------------*/
6743 static void genRRC (iCode *ic)
6745 operand *left , *result ;
6746 int size, offset = 0, same;
6748 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6750 /* rotate right with carry */
6752 result=IC_RESULT(ic);
6753 pic16_aopOp (left,ic,FALSE);
6754 pic16_aopOp (result,ic,FALSE);
6756 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6758 same = pic16_sameRegs(AOP(result),AOP(left));
6760 size = AOP_SIZE(result);
6762 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
6764 /* get the lsb and put it into the carry */
6765 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
6772 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
6774 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
6775 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6781 pic16_freeAsmop(left,NULL,ic,TRUE);
6782 pic16_freeAsmop(result,NULL,ic,TRUE);
6785 /*-----------------------------------------------------------------*/
6786 /* genRLC - generate code for rotate left with carry */
6787 /*-----------------------------------------------------------------*/
6788 static void genRLC (iCode *ic)
6790 operand *left , *result ;
6791 int size, offset = 0;
6794 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6795 /* rotate right with carry */
6797 result=IC_RESULT(ic);
6798 pic16_aopOp (left,ic,FALSE);
6799 pic16_aopOp (result,ic,FALSE);
6801 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6803 same = pic16_sameRegs(AOP(result),AOP(left));
6805 /* move it to the result */
6806 size = AOP_SIZE(result);
6808 /* get the msb and put it into the carry */
6809 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
6816 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
6818 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
6819 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6826 pic16_freeAsmop(left,NULL,ic,TRUE);
6827 pic16_freeAsmop(result,NULL,ic,TRUE);
6831 /* gpasm can get the highest order bit with HIGH/UPPER
6832 * so the following probably is not needed -- VR */
6834 /*-----------------------------------------------------------------*/
6835 /* genGetHbit - generates code get highest order bit */
6836 /*-----------------------------------------------------------------*/
6837 static void genGetHbit (iCode *ic)
6839 operand *left, *result;
6841 result=IC_RESULT(ic);
6842 pic16_aopOp (left,ic,FALSE);
6843 pic16_aopOp (result,ic,FALSE);
6845 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6846 /* get the highest order byte into a */
6847 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6848 if(AOP_TYPE(result) == AOP_CRY){
6849 pic16_emitcode("rlc","a");
6850 pic16_outBitC(result);
6853 pic16_emitcode("rl","a");
6854 pic16_emitcode("anl","a,#0x01");
6855 pic16_outAcc(result);
6859 pic16_freeAsmop(left,NULL,ic,TRUE);
6860 pic16_freeAsmop(result,NULL,ic,TRUE);
6864 /*-----------------------------------------------------------------*/
6865 /* AccRol - rotate left accumulator by known count */
6866 /*-----------------------------------------------------------------*/
6867 static void AccRol (int shCount)
6869 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6870 shCount &= 0x0007; // shCount : 0..7
6875 pic16_emitcode("rl","a");
6878 pic16_emitcode("rl","a");
6879 pic16_emitcode("rl","a");
6882 pic16_emitcode("swap","a");
6883 pic16_emitcode("rr","a");
6886 pic16_emitcode("swap","a");
6889 pic16_emitcode("swap","a");
6890 pic16_emitcode("rl","a");
6893 pic16_emitcode("rr","a");
6894 pic16_emitcode("rr","a");
6897 pic16_emitcode("rr","a");
6903 /*-----------------------------------------------------------------*/
6904 /* AccLsh - left shift accumulator by known count */
6905 /*-----------------------------------------------------------------*/
6906 static void AccLsh (int shCount)
6908 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6914 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6917 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6918 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6921 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6922 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6925 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6928 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6929 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6932 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6933 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6936 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6940 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
6943 /*-----------------------------------------------------------------*/
6944 /* AccRsh - right shift accumulator by known count */
6945 /*-----------------------------------------------------------------*/
6946 static void AccRsh (int shCount, int andmask)
6948 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6953 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6954 // andmask = 0; /* no need */
6957 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6958 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6959 // andmask = 0; /* no need */
6962 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6963 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6966 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6969 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6970 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6973 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6974 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6977 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6982 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
6984 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
6988 /*-----------------------------------------------------------------*/
6989 /* AccSRsh - signed right shift accumulator by known count */
6990 /*-----------------------------------------------------------------*/
6991 static void AccSRsh (int shCount)
6994 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6997 pic16_emitcode("mov","c,acc.7");
6998 pic16_emitcode("rrc","a");
6999 } else if(shCount == 2){
7000 pic16_emitcode("mov","c,acc.7");
7001 pic16_emitcode("rrc","a");
7002 pic16_emitcode("mov","c,acc.7");
7003 pic16_emitcode("rrc","a");
7005 tlbl = newiTempLabel(NULL);
7006 /* rotate right accumulator */
7007 AccRol(8 - shCount);
7008 /* and kill the higher order bits */
7009 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
7010 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
7011 pic16_emitcode("orl","a,#0x%02x",
7012 (unsigned char)~SRMask[shCount]);
7013 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7018 /*-----------------------------------------------------------------*/
7019 /* shiftR1Left2Result - shift right one byte from left to result */
7020 /*-----------------------------------------------------------------*/
7021 static void shiftR1Left2ResultSigned (operand *left, int offl,
7022 operand *result, int offr,
7027 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7029 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7033 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7035 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7037 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7038 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7044 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7046 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7048 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7049 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7051 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7052 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7058 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7060 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7061 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7064 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7065 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7066 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7068 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
7069 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
7071 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7075 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7076 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7077 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7078 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
7079 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7083 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7085 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7086 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7088 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7089 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
7090 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
7091 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
7092 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7097 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7098 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7099 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
7100 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
7101 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
7102 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7104 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7105 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7106 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
7107 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
7108 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0));
7114 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7115 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7116 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7117 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7119 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7120 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7121 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
7129 /*-----------------------------------------------------------------*/
7130 /* shiftR1Left2Result - shift right one byte from left to result */
7131 /*-----------------------------------------------------------------*/
7132 static void shiftR1Left2Result (operand *left, int offl,
7133 operand *result, int offr,
7134 int shCount, int sign)
7138 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7140 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7142 /* Copy the msb into the carry if signed. */
7144 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
7154 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7156 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7157 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7163 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7165 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7166 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7169 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7174 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7176 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7177 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7180 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7181 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7182 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7183 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7187 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7188 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7189 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7193 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7194 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7195 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7197 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7202 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7203 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
7204 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7205 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7206 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7211 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7212 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7213 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7222 /*-----------------------------------------------------------------*/
7223 /* shiftL1Left2Result - shift left one byte from left to result */
7224 /*-----------------------------------------------------------------*/
7225 static void shiftL1Left2Result (operand *left, int offl,
7226 operand *result, int offr, int shCount)
7231 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7233 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
7234 DEBUGpic16_emitcode ("; ***","same = %d",same);
7235 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7237 /* shift left accumulator */
7238 //AccLsh(shCount); // don't comment out just yet...
7239 // pic16_aopPut(AOP(result),"a",offr);
7243 /* Shift left 1 bit position */
7244 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7246 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
7248 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
7249 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7253 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7254 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
7255 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7256 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7259 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7260 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
7261 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7262 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7263 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7266 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7267 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7268 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7271 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7272 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7273 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7274 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7277 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7278 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
7279 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7280 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7281 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7284 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7285 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7286 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7290 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
7295 /*-----------------------------------------------------------------*/
7296 /* movLeft2Result - move byte from left to result */
7297 /*-----------------------------------------------------------------*/
7298 static void movLeft2Result (operand *left, int offl,
7299 operand *result, int offr)
7302 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7303 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
7304 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7306 if (*l == '@' && (IS_AOP_PREG(result))) {
7307 pic16_emitcode("mov","a,%s",l);
7308 pic16_aopPut(AOP(result),"a",offr);
7310 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7311 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7316 /*-----------------------------------------------------------------*/
7317 /* shiftL2Left2Result - shift left two bytes from left to result */
7318 /*-----------------------------------------------------------------*/
7319 static void shiftL2Left2Result (operand *left, int offl,
7320 operand *result, int offr, int shCount)
7322 int same = pic16_sameRegs(AOP(result), AOP(left));
7325 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
7327 if (same && (offl != offr)) { // shift bytes
7330 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7331 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7333 } else { // just treat as different later on
7346 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
7347 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7348 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7352 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7353 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7359 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
7360 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
7361 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7362 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7363 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
7364 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7365 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7367 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7368 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7372 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7373 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7374 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7375 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7376 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7377 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7378 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7379 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7380 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7381 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7384 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7385 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7386 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7387 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7388 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7398 /* note, use a mov/add for the shift since the mov has a
7399 chance of getting optimized out */
7400 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7401 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7402 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7403 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7404 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7408 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7409 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7415 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7416 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7417 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7418 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7419 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7420 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7421 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7422 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7426 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7427 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7431 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7432 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7433 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
7434 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7436 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7437 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7438 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7439 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7440 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7441 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7442 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7443 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7446 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7447 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7448 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7449 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7450 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7455 /*-----------------------------------------------------------------*/
7456 /* shiftR2Left2Result - shift right two bytes from left to result */
7457 /*-----------------------------------------------------------------*/
7458 static void shiftR2Left2Result (operand *left, int offl,
7459 operand *result, int offr,
7460 int shCount, int sign)
7462 int same = pic16_sameRegs(AOP(result), AOP(left));
7464 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7466 if (same && (offl != offr)) { // shift right bytes
7469 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7470 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7472 } else { // just treat as different later on
7484 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7489 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7490 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7492 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7493 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7494 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7495 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7500 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7503 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7504 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7511 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7512 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7513 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7515 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7516 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7517 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7518 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7520 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7521 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7522 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7524 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7525 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7526 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7527 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7528 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7532 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7533 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7537 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7538 pic16_emitpcode(POC_BTFSC,
7539 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7540 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7548 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7549 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7551 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7552 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7553 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7554 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7556 pic16_emitpcode(POC_BTFSC,
7557 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7558 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7560 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7561 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7562 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7563 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7565 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7566 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7567 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7568 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7569 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7570 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7571 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
7572 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7574 pic16_emitpcode(POC_BTFSC,
7575 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7576 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7578 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7579 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7586 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7587 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7588 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7589 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
7592 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
7594 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7599 /*-----------------------------------------------------------------*/
7600 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7601 /*-----------------------------------------------------------------*/
7602 static void shiftLLeftOrResult (operand *left, int offl,
7603 operand *result, int offr, int shCount)
7605 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7607 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7608 /* shift left accumulator */
7610 /* or with result */
7611 /* back to result */
7612 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7615 /*-----------------------------------------------------------------*/
7616 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7617 /*-----------------------------------------------------------------*/
7618 static void shiftRLeftOrResult (operand *left, int offl,
7619 operand *result, int offr, int shCount)
7621 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7623 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7624 /* shift right accumulator */
7626 /* or with result */
7627 /* back to result */
7628 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7631 /*-----------------------------------------------------------------*/
7632 /* genlshOne - left shift a one byte quantity by known count */
7633 /*-----------------------------------------------------------------*/
7634 static void genlshOne (operand *result, operand *left, int shCount)
7636 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7637 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7640 /*-----------------------------------------------------------------*/
7641 /* genlshTwo - left shift two bytes by known amount != 0 */
7642 /*-----------------------------------------------------------------*/
7643 static void genlshTwo (operand *result,operand *left, int shCount)
7647 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7648 size = pic16_getDataSize(result);
7650 /* if shCount >= 8 */
7656 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7658 movLeft2Result(left, LSB, result, MSB16);
7660 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7663 /* 1 <= shCount <= 7 */
7666 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7668 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7672 /*-----------------------------------------------------------------*/
7673 /* shiftLLong - shift left one long from left to result */
7674 /* offr = LSB or MSB16 */
7675 /*-----------------------------------------------------------------*/
7676 static void shiftLLong (operand *left, operand *result, int offr )
7678 int size = AOP_SIZE(result);
7679 int same = pic16_sameRegs(AOP(left),AOP(result));
7682 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
7684 if (same && (offr == MSB16)) { //shift one byte
7685 for(i=size-1;i>=MSB16;i--) {
7686 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
7687 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
7690 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
7693 if (size >= LSB+offr ){
7695 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
7697 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
7698 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
7702 if(size >= MSB16+offr){
7704 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
7706 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
7707 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
7711 if(size >= MSB24+offr){
7713 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
7715 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
7716 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
7720 if(size > MSB32+offr){
7722 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
7724 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
7725 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
7729 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7733 /*-----------------------------------------------------------------*/
7734 /* genlshFour - shift four byte by a known amount != 0 */
7735 /*-----------------------------------------------------------------*/
7736 static void genlshFour (operand *result, operand *left, int shCount)
7740 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7741 size = AOP_SIZE(result);
7743 /* if shifting more that 3 bytes */
7744 if (shCount >= 24 ) {
7747 /* lowest order of left goes to the highest
7748 order of the destination */
7749 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7751 movLeft2Result(left, LSB, result, MSB32);
7753 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7754 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7755 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
7760 /* more than two bytes */
7761 else if ( shCount >= 16 ) {
7762 /* lower order two bytes goes to higher order two bytes */
7764 /* if some more remaining */
7766 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7768 movLeft2Result(left, MSB16, result, MSB32);
7769 movLeft2Result(left, LSB, result, MSB24);
7771 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7772 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7776 /* if more than 1 byte */
7777 else if ( shCount >= 8 ) {
7778 /* lower order three bytes goes to higher order three bytes */
7782 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7784 movLeft2Result(left, LSB, result, MSB16);
7786 else{ /* size = 4 */
7788 movLeft2Result(left, MSB24, result, MSB32);
7789 movLeft2Result(left, MSB16, result, MSB24);
7790 movLeft2Result(left, LSB, result, MSB16);
7791 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7793 else if(shCount == 1)
7794 shiftLLong(left, result, MSB16);
7796 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7797 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7798 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7799 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7804 /* 1 <= shCount <= 7 */
7805 else if(shCount <= 3)
7807 shiftLLong(left, result, LSB);
7808 while(--shCount >= 1)
7809 shiftLLong(result, result, LSB);
7811 /* 3 <= shCount <= 7, optimize */
7813 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7814 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7815 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7819 /*-----------------------------------------------------------------*/
7820 /* genLeftShiftLiteral - left shifting by known count */
7821 /*-----------------------------------------------------------------*/
7822 static void genLeftShiftLiteral (operand *left,
7827 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7830 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7831 pic16_freeAsmop(right,NULL,ic,TRUE);
7833 pic16_aopOp(left,ic,FALSE);
7834 pic16_aopOp(result,ic,FALSE);
7836 size = getSize(operandType(result));
7839 pic16_emitcode("; shift left ","result %d, left %d",size,
7843 /* I suppose that the left size >= result size */
7846 movLeft2Result(left, size, result, size);
7850 else if(shCount >= (size * 8))
7852 pic16_aopPut(AOP(result),zero,size);
7856 genlshOne (result,left,shCount);
7861 genlshTwo (result,left,shCount);
7865 genlshFour (result,left,shCount);
7869 pic16_freeAsmop(left,NULL,ic,TRUE);
7870 pic16_freeAsmop(result,NULL,ic,TRUE);
7873 /*-----------------------------------------------------------------*
7874 * genMultiAsm - repeat assembly instruction for size of register.
7875 * if endian == 1, then the high byte (i.e base address + size of
7876 * register) is used first else the low byte is used first;
7877 *-----------------------------------------------------------------*/
7878 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7883 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7896 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
7901 /*-----------------------------------------------------------------*/
7902 /* genLeftShift - generates code for left shifting */
7903 /*-----------------------------------------------------------------*/
7904 static void genLeftShift (iCode *ic)
7906 operand *left,*right, *result;
7909 symbol *tlbl , *tlbl1;
7912 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7914 right = IC_RIGHT(ic);
7916 result = IC_RESULT(ic);
7918 pic16_aopOp(right,ic,FALSE);
7920 /* if the shift count is known then do it
7921 as efficiently as possible */
7922 if (AOP_TYPE(right) == AOP_LIT) {
7923 genLeftShiftLiteral (left,right,result,ic);
7927 /* shift count is unknown then we have to form
7928 a loop get the loop count in B : Note: we take
7929 only the lower order byte since shifting
7930 more that 32 bits make no sense anyway, ( the
7931 largest size of an object can be only 32 bits ) */
7934 pic16_aopOp(left,ic,FALSE);
7935 pic16_aopOp(result,ic,FALSE);
7937 /* now move the left to the result if they are not the
7939 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
7940 AOP_SIZE(result) > 1) {
7942 size = AOP_SIZE(result);
7945 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
7946 if (*l == '@' && (IS_AOP_PREG(result))) {
7948 pic16_emitcode("mov","a,%s",l);
7949 pic16_aopPut(AOP(result),"a",offset);
7951 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
7952 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7953 //pic16_aopPut(AOP(result),l,offset);
7959 size = AOP_SIZE(result);
7961 /* if it is only one byte then */
7963 if(optimized_for_speed) {
7964 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
7965 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7966 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0));
7967 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
7968 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
7969 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
7970 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
7971 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
7972 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
7973 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
7974 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0));
7975 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
7978 tlbl = newiTempLabel(NULL);
7979 if (!pic16_sameRegs(AOP(left),AOP(result))) {
7980 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
7981 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
7984 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
7985 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
7986 pic16_emitpLabel(tlbl->key);
7987 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
7988 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
7990 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7995 if (pic16_sameRegs(AOP(left),AOP(result))) {
7997 tlbl = newiTempLabel(NULL);
7998 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
7999 genMultiAsm(POC_RRCF, result, size,1);
8000 pic16_emitpLabel(tlbl->key);
8001 genMultiAsm(POC_RLCF, result, size,0);
8002 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8004 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8008 //tlbl = newiTempLabel(NULL);
8010 //tlbl1 = newiTempLabel(NULL);
8012 //reAdjustPreg(AOP(result));
8014 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8015 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8016 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8018 //pic16_emitcode("add","a,acc");
8019 //pic16_aopPut(AOP(result),"a",offset++);
8021 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8023 // pic16_emitcode("rlc","a");
8024 // pic16_aopPut(AOP(result),"a",offset++);
8026 //reAdjustPreg(AOP(result));
8028 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8029 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8032 tlbl = newiTempLabel(NULL);
8033 tlbl1= newiTempLabel(NULL);
8035 size = AOP_SIZE(result);
8038 pctemp = pic16_popGetTempReg(); /* grab a temporary working register. */
8040 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8042 /* offset should be 0, 1 or 3 */
8044 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8046 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
8048 pic16_emitpcode(POC_MOVWF, pctemp);
8051 pic16_emitpLabel(tlbl->key);
8054 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8056 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
8058 pic16_emitpcode(POC_DECFSZ, pctemp);
8059 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8060 pic16_emitpLabel(tlbl1->key);
8062 pic16_popReleaseTempReg(pctemp);
8066 pic16_freeAsmop (right,NULL,ic,TRUE);
8067 pic16_freeAsmop(left,NULL,ic,TRUE);
8068 pic16_freeAsmop(result,NULL,ic,TRUE);
8071 /*-----------------------------------------------------------------*/
8072 /* genrshOne - right shift a one byte quantity by known count */
8073 /*-----------------------------------------------------------------*/
8074 static void genrshOne (operand *result, operand *left,
8075 int shCount, int sign)
8077 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8078 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
8081 /*-----------------------------------------------------------------*/
8082 /* genrshTwo - right shift two bytes by known amount != 0 */
8083 /*-----------------------------------------------------------------*/
8084 static void genrshTwo (operand *result,operand *left,
8085 int shCount, int sign)
8087 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8088 /* if shCount >= 8 */
8092 shiftR1Left2Result(left, MSB16, result, LSB,
8095 movLeft2Result(left, MSB16, result, LSB);
8097 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8100 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
8101 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
8105 /* 1 <= shCount <= 7 */
8107 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
8110 /*-----------------------------------------------------------------*/
8111 /* shiftRLong - shift right one long from left to result */
8112 /* offl = LSB or MSB16 */
8113 /*-----------------------------------------------------------------*/
8114 static void shiftRLong (operand *left, int offl,
8115 operand *result, int sign)
8117 int size = AOP_SIZE(result);
8118 int same = pic16_sameRegs(AOP(left),AOP(result));
8120 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
8122 if (same && (offl == MSB16)) { //shift one byte right
8123 for(i=MSB16;i<size;i++) {
8124 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
8125 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
8130 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
8136 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
8138 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
8139 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
8143 /* add sign of "a" */
8144 pic16_addSign(result, MSB32, sign);
8148 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
8150 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
8151 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
8155 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
8157 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
8158 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
8162 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
8165 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
8166 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
8171 /*-----------------------------------------------------------------*/
8172 /* genrshFour - shift four byte by a known amount != 0 */
8173 /*-----------------------------------------------------------------*/
8174 static void genrshFour (operand *result, operand *left,
8175 int shCount, int sign)
8177 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8178 /* if shifting more that 3 bytes */
8179 if(shCount >= 24 ) {
8182 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8184 movLeft2Result(left, MSB32, result, LSB);
8186 pic16_addSign(result, MSB16, sign);
8188 else if(shCount >= 16){
8191 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8193 movLeft2Result(left, MSB24, result, LSB);
8194 movLeft2Result(left, MSB32, result, MSB16);
8196 pic16_addSign(result, MSB24, sign);
8198 else if(shCount >= 8){
8201 shiftRLong(left, MSB16, result, sign);
8202 else if(shCount == 0){
8203 movLeft2Result(left, MSB16, result, LSB);
8204 movLeft2Result(left, MSB24, result, MSB16);
8205 movLeft2Result(left, MSB32, result, MSB24);
8206 pic16_addSign(result, MSB32, sign);
8208 else{ //shcount >= 2
8209 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8210 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8211 /* the last shift is signed */
8212 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8213 pic16_addSign(result, MSB32, sign);
8216 else{ /* 1 <= shCount <= 7 */
8218 shiftRLong(left, LSB, result, sign);
8220 shiftRLong(result, LSB, result, sign);
8223 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8224 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8225 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8230 /*-----------------------------------------------------------------*/
8231 /* genRightShiftLiteral - right shifting by known count */
8232 /*-----------------------------------------------------------------*/
8233 static void genRightShiftLiteral (operand *left,
8239 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8242 pic16_freeAsmop(right,NULL,ic,TRUE);
8244 pic16_aopOp(left,ic,FALSE);
8245 pic16_aopOp(result,ic,FALSE);
8247 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
8250 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8254 lsize = pic16_getDataSize(left);
8255 res_size = pic16_getDataSize(result);
8256 /* test the LEFT size !!! */
8258 /* I suppose that the left size >= result size */
8261 movLeft2Result(left, lsize, result, res_size);
8264 else if(shCount >= (lsize * 8)){
8267 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
8269 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8270 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
8275 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8276 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8277 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8279 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
8284 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
8291 genrshOne (result,left,shCount,sign);
8295 genrshTwo (result,left,shCount,sign);
8299 genrshFour (result,left,shCount,sign);
8307 pic16_freeAsmop(left,NULL,ic,TRUE);
8308 pic16_freeAsmop(result,NULL,ic,TRUE);
8311 /*-----------------------------------------------------------------*/
8312 /* genSignedRightShift - right shift of signed number */
8313 /*-----------------------------------------------------------------*/
8314 static void genSignedRightShift (iCode *ic)
8316 operand *right, *left, *result;
8319 symbol *tlbl, *tlbl1 ;
8322 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8324 /* we do it the hard way put the shift count in b
8325 and loop thru preserving the sign */
8326 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8328 right = IC_RIGHT(ic);
8330 result = IC_RESULT(ic);
8332 pic16_aopOp(right,ic,FALSE);
8333 pic16_aopOp(left,ic,FALSE);
8334 pic16_aopOp(result,ic,FALSE);
8337 if ( AOP_TYPE(right) == AOP_LIT) {
8338 genRightShiftLiteral (left,right,result,ic,1);
8341 /* shift count is unknown then we have to form
8342 a loop get the loop count in B : Note: we take
8343 only the lower order byte since shifting
8344 more that 32 bits make no sense anyway, ( the
8345 largest size of an object can be only 32 bits ) */
8347 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8348 //pic16_emitcode("inc","b");
8349 //pic16_freeAsmop (right,NULL,ic,TRUE);
8350 //pic16_aopOp(left,ic,FALSE);
8351 //pic16_aopOp(result,ic,FALSE);
8353 /* now move the left to the result if they are not the
8355 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
8356 AOP_SIZE(result) > 1) {
8358 size = AOP_SIZE(result);
8362 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8363 if (*l == '@' && IS_AOP_PREG(result)) {
8365 pic16_emitcode("mov","a,%s",l);
8366 pic16_aopPut(AOP(result),"a",offset);
8368 pic16_aopPut(AOP(result),l,offset);
8370 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8371 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8377 /* mov the highest order bit to OVR */
8378 tlbl = newiTempLabel(NULL);
8379 tlbl1= newiTempLabel(NULL);
8381 size = AOP_SIZE(result);
8384 pctemp = pic16_popGetTempReg(); /* grab a temporary working register. */
8386 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8388 /* offset should be 0, 1 or 3 */
8389 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
8391 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
8393 pic16_emitpcode(POC_MOVWF, pctemp);
8396 pic16_emitpLabel(tlbl->key);
8398 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
8399 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
8402 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
8405 pic16_emitpcode(POC_DECFSZ, pctemp);
8406 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8407 pic16_emitpLabel(tlbl1->key);
8409 pic16_popReleaseTempReg(pctemp);
8411 size = AOP_SIZE(result);
8413 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8414 pic16_emitcode("rlc","a");
8415 pic16_emitcode("mov","ov,c");
8416 /* if it is only one byte then */
8418 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8420 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8421 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8422 pic16_emitcode("mov","c,ov");
8423 pic16_emitcode("rrc","a");
8424 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8425 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8426 pic16_aopPut(AOP(result),"a",0);
8430 reAdjustPreg(AOP(result));
8431 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8432 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8433 pic16_emitcode("mov","c,ov");
8435 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8437 pic16_emitcode("rrc","a");
8438 pic16_aopPut(AOP(result),"a",offset--);
8440 reAdjustPreg(AOP(result));
8441 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8442 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8447 pic16_freeAsmop(left,NULL,ic,TRUE);
8448 pic16_freeAsmop(result,NULL,ic,TRUE);
8449 pic16_freeAsmop(right,NULL,ic,TRUE);
8452 /*-----------------------------------------------------------------*/
8453 /* genRightShift - generate code for right shifting */
8454 /*-----------------------------------------------------------------*/
8455 static void genRightShift (iCode *ic)
8457 operand *right, *left, *result;
8461 symbol *tlbl, *tlbl1 ;
8463 /* if signed then we do it the hard way preserve the
8464 sign bit moving it inwards */
8465 letype = getSpec(operandType(IC_LEFT(ic)));
8466 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8468 if (!SPEC_USIGN(letype)) {
8469 genSignedRightShift (ic);
8473 /* signed & unsigned types are treated the same : i.e. the
8474 signed is NOT propagated inwards : quoting from the
8475 ANSI - standard : "for E1 >> E2, is equivalent to division
8476 by 2**E2 if unsigned or if it has a non-negative value,
8477 otherwise the result is implementation defined ", MY definition
8478 is that the sign does not get propagated */
8480 right = IC_RIGHT(ic);
8482 result = IC_RESULT(ic);
8484 pic16_aopOp(right,ic,FALSE);
8486 /* if the shift count is known then do it
8487 as efficiently as possible */
8488 if (AOP_TYPE(right) == AOP_LIT) {
8489 genRightShiftLiteral (left,right,result,ic, 0);
8493 /* shift count is unknown then we have to form
8494 a loop get the loop count in B : Note: we take
8495 only the lower order byte since shifting
8496 more that 32 bits make no sense anyway, ( the
8497 largest size of an object can be only 32 bits ) */
8499 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8500 pic16_emitcode("inc","b");
8501 pic16_aopOp(left,ic,FALSE);
8502 pic16_aopOp(result,ic,FALSE);
8504 /* now move the left to the result if they are not the
8506 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
8507 AOP_SIZE(result) > 1) {
8509 size = AOP_SIZE(result);
8512 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8513 if (*l == '@' && IS_AOP_PREG(result)) {
8515 pic16_emitcode("mov","a,%s",l);
8516 pic16_aopPut(AOP(result),"a",offset);
8518 pic16_aopPut(AOP(result),l,offset);
8523 tlbl = newiTempLabel(NULL);
8524 tlbl1= newiTempLabel(NULL);
8525 size = AOP_SIZE(result);
8528 /* if it is only one byte then */
8531 tlbl = newiTempLabel(NULL);
8532 if (!pic16_sameRegs(AOP(left),AOP(result))) {
8533 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8534 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8537 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8538 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8539 pic16_emitpLabel(tlbl->key);
8540 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
8541 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8543 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8548 reAdjustPreg(AOP(result));
8549 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8550 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8553 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8555 pic16_emitcode("rrc","a");
8556 pic16_aopPut(AOP(result),"a",offset--);
8558 reAdjustPreg(AOP(result));
8560 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8561 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8564 pic16_freeAsmop(left,NULL,ic,TRUE);
8565 pic16_freeAsmop (right,NULL,ic,TRUE);
8566 pic16_freeAsmop(result,NULL,ic,TRUE);
8569 /*-----------------------------------------------------------------*/
8570 /* genUnpackBits - generates code for unpacking bits */
8571 /*-----------------------------------------------------------------*/
8572 static void genUnpackBits (operand *result, char *rname, int ptype)
8579 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8580 etype = getSpec(operandType(result));
8582 /* read the first byte */
8589 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
8592 pic16_emitcode("clr","a");
8593 pic16_emitcode("movc","a","@a+dptr");
8598 /* if we have bitdisplacement then it fits */
8599 /* into this byte completely or if length is */
8600 /* less than a byte */
8601 if ((shCnt = SPEC_BSTR(etype)) ||
8602 (SPEC_BLEN(etype) <= 8)) {
8604 /* shift right acc */
8607 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
8608 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
8610 /* VR -- normally I would use the following, but since we use the hack,
8611 * to avoid the masking from AccRsh, why not mask it right now? */
8614 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
8617 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
8623 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
8624 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
8627 /* bit field did not fit in a byte */
8628 rlen = SPEC_BLEN(etype) - 8;
8629 pic16_aopPut(AOP(result),"a",offset++);
8636 pic16_emitcode("inc","%s",rname);
8637 pic16_emitcode("mov","a,@%s",rname);
8641 pic16_emitcode("inc","%s",rname);
8642 pic16_emitcode("movx","a,@%s",rname);
8646 pic16_emitcode("inc","dptr");
8647 pic16_emitcode("movx","a,@dptr");
8651 pic16_emitcode("clr","a");
8652 pic16_emitcode("inc","dptr");
8653 pic16_emitcode("movc","a","@a+dptr");
8657 pic16_emitcode("inc","dptr");
8658 pic16_emitcode("lcall","__gptrget");
8663 /* if we are done */
8667 pic16_aopPut(AOP(result),"a",offset++);
8672 pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
8673 pic16_aopPut(AOP(result),"a",offset);
8680 static void genDataPointerGet(operand *left,
8684 int size, offset = 0, leoffset=0 ;
8686 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8687 pic16_aopOp(result, ic, FALSE);
8689 size = AOP_SIZE(result);
8690 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
8694 /* The following tests may save a redudant movff instruction when
8695 * accessing unions */
8697 /* if they are the same */
8698 if (operandsEqu (left, result)) {
8699 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
8703 /* if they are the same registers */
8704 if (pic16_sameRegs(AOP(left),AOP(result))) {
8705 DEBUGpic16_emitcode("; ***", "left and result registers are same");
8711 if ( AOP_TYPE(left) == AOP_PCODE) {
8712 fprintf(stderr,"genDataPointerGet %s, %d\n",
8713 AOP(left)->aopu.pcop->name,
8714 (AOP(left)->aopu.pcop->type == PO_DIR)?
8715 PCOR(AOP(left)->aopu.pcop)->instance:
8716 PCOI(AOP(left)->aopu.pcop)->offset);
8720 if(AOP(left)->aopu.pcop->type == PO_DIR)
8721 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
8723 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8726 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
8728 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
8729 || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
8730 mov2w(AOP(left), offset); // patch 8
8731 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
8733 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
8734 pic16_popGet(AOP(left), offset), //patch 8
8735 pic16_popGet(AOP(result), offset)));
8743 pic16_freeAsmop(result,NULL,ic,TRUE);
8746 void pic16_loadFSR0(operand *op)
8748 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
8752 /*-----------------------------------------------------------------*/
8753 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
8754 /*-----------------------------------------------------------------*/
8755 static void genNearPointerGet (operand *left,
8760 //regs *preg = NULL ;
8761 sym_link *rtype, *retype;
8762 sym_link *ltype = operandType(left);
8764 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8765 rtype = operandType(result);
8766 retype= getSpec(rtype);
8768 pic16_aopOp(left,ic,FALSE);
8770 pic16_DumpOp("(left)",left);
8771 pic16_DumpOp("(result)",result);
8773 /* if left is rematerialisable and
8774 * result is not bit variable type and
8775 * the left is pointer to data space i.e
8776 * lower 128 bytes of space */
8777 if (AOP_TYPE(left) == AOP_PCODE
8778 && !IS_BITFIELD(retype)
8779 && DCL_TYPE(ltype) == POINTER) {
8781 genDataPointerGet (left,result,ic);
8782 pic16_freeAsmop(left, NULL, ic, TRUE);
8786 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8788 /* if the value is already in a pointer register
8789 * then don't need anything more */
8790 if (!AOP_INPREG(AOP(left))) {
8791 /* otherwise get a free pointer register */
8792 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8794 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
8795 if( (AOP_TYPE(left) == AOP_PCODE)
8796 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
8797 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
8799 pic16_loadFSR0( left ); // patch 10
8801 // set up FSR0 with address from left
8802 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
8803 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
8807 // rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8809 pic16_aopOp (result,ic,FALSE);
8811 /* if bitfield then unpack the bits */
8812 if (IS_BITFIELD(retype))
8813 genUnpackBits (result, NULL, POINTER);
8815 /* we have can just get the values */
8816 int size = AOP_SIZE(result);
8819 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8822 /* fsr0 is loaded already -- VR */
8823 // pic16_loadFSR0( left );
8825 // pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
8826 // pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
8830 pic16_emitpcode(POC_MOVFF,
8831 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
8832 pic16_popGet(AOP(result), offset++)));
8834 pic16_emitpcode(POC_MOVFF,
8835 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
8836 pic16_popGet(AOP(result), offset++)));
8840 // pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
8841 // pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
8843 pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
8847 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
8849 pic16_emitcode("mov","a,@%s",rname);
8850 pic16_aopPut(AOP(result),"a",offset);
8852 sprintf(buffer,"@%s",rname);
8853 pic16_aopPut(AOP(result),buffer,offset);
8857 pic16_emitcode("inc","%s",rname);
8862 /* now some housekeeping stuff */
8864 /* we had to allocate for this iCode */
8865 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8866 pic16_freeAsmop(NULL,aop,ic,TRUE);
8868 /* we did not allocate which means left
8869 already in a pointer register, then
8870 if size > 0 && this could be used again
8871 we have to point it back to where it
8873 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8874 if (AOP_SIZE(result) > 1 &&
8875 !OP_SYMBOL(left)->remat &&
8876 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8878 // int size = AOP_SIZE(result) - 1;
8880 // pic16_emitcode("dec","%s",rname);
8885 pic16_freeAsmop(left,NULL,ic,TRUE);
8886 pic16_freeAsmop(result,NULL,ic,TRUE);
8890 /*-----------------------------------------------------------------*/
8891 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
8892 /*-----------------------------------------------------------------*/
8893 static void genPagedPointerGet (operand *left,
8900 sym_link *rtype, *retype;
8902 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8904 rtype = operandType(result);
8905 retype= getSpec(rtype);
8907 pic16_aopOp(left,ic,FALSE);
8909 /* if the value is already in a pointer register
8910 then don't need anything more */
8911 if (!AOP_INPREG(AOP(left))) {
8912 /* otherwise get a free pointer register */
8914 preg = getFreePtr(ic,&aop,FALSE);
8915 pic16_emitcode("mov","%s,%s",
8917 pic16_aopGet(AOP(left),0,FALSE,TRUE));
8918 rname = preg->name ;
8920 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8922 pic16_freeAsmop(left,NULL,ic,TRUE);
8923 pic16_aopOp (result,ic,FALSE);
8925 /* if bitfield then unpack the bits */
8926 if (IS_BITFIELD(retype))
8927 genUnpackBits (result,rname,PPOINTER);
8929 /* we have can just get the values */
8930 int size = AOP_SIZE(result);
8935 pic16_emitcode("movx","a,@%s",rname);
8936 pic16_aopPut(AOP(result),"a",offset);
8941 pic16_emitcode("inc","%s",rname);
8945 /* now some housekeeping stuff */
8947 /* we had to allocate for this iCode */
8948 pic16_freeAsmop(NULL,aop,ic,TRUE);
8950 /* we did not allocate which means left
8951 already in a pointer register, then
8952 if size > 0 && this could be used again
8953 we have to point it back to where it
8955 if (AOP_SIZE(result) > 1 &&
8956 !OP_SYMBOL(left)->remat &&
8957 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8959 int size = AOP_SIZE(result) - 1;
8961 pic16_emitcode("dec","%s",rname);
8966 pic16_freeAsmop(result,NULL,ic,TRUE);
8971 /*-----------------------------------------------------------------*/
8972 /* genFarPointerGet - gget value from far space */
8973 /*-----------------------------------------------------------------*/
8974 static void genFarPointerGet (operand *left,
8975 operand *result, iCode *ic)
8978 sym_link *retype = getSpec(operandType(result));
8980 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8982 pic16_aopOp(left,ic,FALSE);
8984 /* if the operand is already in dptr
8985 then we do nothing else we move the value to dptr */
8986 if (AOP_TYPE(left) != AOP_STR) {
8987 /* if this is remateriazable */
8988 if (AOP_TYPE(left) == AOP_IMMD)
8989 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
8990 else { /* we need to get it byte by byte */
8991 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
8992 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
8993 if (options.model == MODEL_FLAT24)
8995 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
8999 /* so dptr know contains the address */
9000 pic16_freeAsmop(left,NULL,ic,TRUE);
9001 pic16_aopOp(result,ic,FALSE);
9003 /* if bit then unpack */
9004 if (IS_BITFIELD(retype))
9005 genUnpackBits(result,"dptr",FPOINTER);
9007 size = AOP_SIZE(result);
9011 pic16_emitcode("movx","a,@dptr");
9012 pic16_aopPut(AOP(result),"a",offset++);
9014 pic16_emitcode("inc","dptr");
9018 pic16_freeAsmop(result,NULL,ic,TRUE);
9021 /*-----------------------------------------------------------------*/
9022 /* genCodePointerGet - get value from code space */
9023 /*-----------------------------------------------------------------*/
9024 static void genCodePointerGet (operand *left,
9025 operand *result, iCode *ic)
9028 sym_link *retype = getSpec(operandType(result));
9030 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9032 pic16_aopOp(left,ic,FALSE);
9034 /* if the operand is already in dptr
9035 then we do nothing else we move the value to dptr */
9036 if (AOP_TYPE(left) != AOP_STR) {
9037 /* if this is remateriazable */
9038 if (AOP_TYPE(left) == AOP_IMMD)
9039 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9040 else { /* we need to get it byte by byte */
9041 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9042 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9043 if (options.model == MODEL_FLAT24)
9045 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9049 /* so dptr know contains the address */
9050 pic16_freeAsmop(left,NULL,ic,TRUE);
9051 pic16_aopOp(result,ic,FALSE);
9053 /* if bit then unpack */
9054 if (IS_BITFIELD(retype))
9055 genUnpackBits(result,"dptr",CPOINTER);
9057 size = AOP_SIZE(result);
9061 pic16_emitcode("clr","a");
9062 pic16_emitcode("movc","a,@a+dptr");
9063 pic16_aopPut(AOP(result),"a",offset++);
9065 pic16_emitcode("inc","dptr");
9069 pic16_freeAsmop(result,NULL,ic,TRUE);
9072 /*-----------------------------------------------------------------*/
9073 /* genGenPointerGet - gget value from generic pointer space */
9074 /*-----------------------------------------------------------------*/
9075 static void genGenPointerGet (operand *left,
9076 operand *result, iCode *ic)
9078 int size, offset, lit;
9079 sym_link *retype = getSpec(operandType(result));
9081 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9082 pic16_aopOp(left,ic,FALSE);
9083 pic16_aopOp(result,ic,FALSE);
9084 size = AOP_SIZE(result);
9086 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9088 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
9090 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
9091 // load FSR0 from immediate
9092 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9094 // pic16_loadFSR0( left );
9099 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9101 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9108 else { /* we need to get it byte by byte */
9109 // set up FSR0 with address from left
9110 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9111 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9117 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9119 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9126 /* if bit then unpack */
9127 if (IS_BITFIELD(retype))
9128 genUnpackBits(result,"BAD",GPOINTER);
9131 pic16_freeAsmop(left,NULL,ic,TRUE);
9132 pic16_freeAsmop(result,NULL,ic,TRUE);
9136 /*-----------------------------------------------------------------*/
9137 /* genConstPointerGet - get value from const generic pointer space */
9138 /*-----------------------------------------------------------------*/
9139 static void genConstPointerGet (operand *left,
9140 operand *result, iCode *ic)
9142 //sym_link *retype = getSpec(operandType(result));
9143 // symbol *albl = newiTempLabel(NULL); // patch 15
9144 // symbol *blbl = newiTempLabel(NULL); //
9145 // PIC_OPCODE poc; // patch 15
9149 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9150 pic16_aopOp(left,ic,FALSE);
9151 pic16_aopOp(result,ic,TRUE);
9152 size = AOP_SIZE(result);
9154 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9156 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
9158 pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
9159 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
9160 pic16_emitpLabel(albl->key);
9162 poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
9164 /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
9165 pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
9166 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
9167 pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
9168 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
9170 pic16_emitpLabel(blbl->key);
9172 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
9176 // set up table pointer
9177 if( (AOP_TYPE(left) == AOP_PCODE)
9178 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9179 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 15 ......
9181 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
9182 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9183 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
9184 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9185 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
9186 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9190 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
9191 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
9192 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
9198 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9199 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
9203 pic16_freeAsmop(left,NULL,ic,TRUE);
9204 pic16_freeAsmop(result,NULL,ic,TRUE);
9207 /*-----------------------------------------------------------------*/
9208 /* genPointerGet - generate code for pointer get */
9209 /*-----------------------------------------------------------------*/
9210 static void genPointerGet (iCode *ic)
9212 operand *left, *result ;
9213 sym_link *type, *etype;
9216 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9219 result = IC_RESULT(ic) ;
9221 /* depending on the type of pointer we need to
9222 move it to the correct pointer register */
9223 type = operandType(left);
9224 etype = getSpec(type);
9227 if (IS_PTR_CONST(type))
9229 if (IS_CODEPTR(type))
9231 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
9233 /* if left is of type of pointer then it is simple */
9234 if (IS_PTR(type) && !IS_FUNC(type->next))
9235 p_type = DCL_TYPE(type);
9237 /* we have to go by the storage class */
9238 p_type = PTR_TYPE(SPEC_OCLS(etype));
9240 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9242 if (SPEC_OCLS(etype)->codesp ) {
9243 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
9244 //p_type = CPOINTER ;
9247 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9248 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
9249 /*p_type = FPOINTER ;*/
9251 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9252 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
9253 /* p_type = PPOINTER; */
9255 if (SPEC_OCLS(etype) == idata )
9256 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
9257 /* p_type = IPOINTER; */
9259 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
9260 /* p_type = POINTER ; */
9263 /* now that we have the pointer type we assign
9264 the pointer values */
9269 genNearPointerGet (left,result,ic);
9273 genPagedPointerGet(left,result,ic);
9277 genFarPointerGet (left,result,ic);
9281 genConstPointerGet (left,result,ic);
9282 //pic16_emitcodePointerGet (left,result,ic);
9287 if (IS_PTR_CONST(type))
9288 genConstPointerGet (left,result,ic);
9291 genGenPointerGet (left,result,ic);
9297 /*-----------------------------------------------------------------*/
9298 /* genPackBits - generates code for packed bit storage */
9299 /*-----------------------------------------------------------------*/
9300 static void genPackBits (sym_link *etype ,
9302 char *rname, int p_type)
9310 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9311 blen = SPEC_BLEN(etype);
9312 bstr = SPEC_BSTR(etype);
9314 if(AOP_TYPE(right) == AOP_LIT) {
9315 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
9318 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
9320 /* l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9323 /* if the bit lenth is less than or */
9324 /* it exactly fits a byte then */
9325 if((shCnt=SPEC_BSTR(etype))
9326 || SPEC_BLEN(etype) <= 8 ) {
9328 /* shift left acc */
9331 /* using PRODL as a temporary register here */
9332 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
9338 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9339 // pic16_emitcode ("mov","b,a");
9340 // pic16_emitcode("mov","a,@%s",rname);
9344 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9345 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
9346 (unsigned char)(0xff >> (8-bstr))) ));
9347 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
9348 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
9352 pic16_emitcode ("anl","a,#0x%02x",(unsigned char)
9353 ((unsigned char)(0xFF << (blen+bstr)) |
9354 (unsigned char)(0xFF >> (8-bstr)) ) );
9355 pic16_emitcode ("orl","a,b");
9356 if (p_type == GPOINTER)
9357 pic16_emitcode("pop","b");
9362 pic16_emitcode("mov","@%s,a",rname);
9365 pic16_emitcode("movx","@dptr,a");
9368 DEBUGpic16_emitcode(";lcall","__gptrput");
9377 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9378 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9383 if ( SPEC_BLEN(etype) <= 8 )
9386 pic16_emitcode("inc","%s",rname);
9387 rLen = SPEC_BLEN(etype) ;
9391 /* now generate for lengths greater than one byte */
9394 l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
9404 pic16_emitcode("mov","@%s,a",rname);
9406 pic16_emitcode("mov","@%s,%s",rname,l);
9411 pic16_emitcode("movx","@dptr,a");
9416 DEBUGpic16_emitcode(";lcall","__gptrput");
9419 pic16_emitcode ("inc","%s",rname);
9424 /* last last was not complete */
9426 /* save the byte & read byte */
9429 pic16_emitcode ("mov","b,a");
9430 pic16_emitcode("mov","a,@%s",rname);
9434 pic16_emitcode ("mov","b,a");
9435 pic16_emitcode("movx","a,@dptr");
9439 pic16_emitcode ("push","b");
9440 pic16_emitcode ("push","acc");
9441 pic16_emitcode ("lcall","__gptrget");
9442 pic16_emitcode ("pop","b");
9446 pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
9447 pic16_emitcode ("orl","a,b");
9450 if (p_type == GPOINTER)
9451 pic16_emitcode("pop","b");
9456 pic16_emitcode("mov","@%s,a",rname);
9460 pic16_emitcode("movx","@dptr,a");
9464 DEBUGpic16_emitcode(";lcall","__gptrput");
9468 /*-----------------------------------------------------------------*/
9469 /* genDataPointerSet - remat pointer to data space */
9470 /*-----------------------------------------------------------------*/
9471 static void genDataPointerSet(operand *right,
9475 int size, offset = 0, resoffset=0 ;
9477 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9478 pic16_aopOp(right,ic,FALSE);
9480 size = AOP_SIZE(right);
9481 fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9484 if ( AOP_TYPE(result) == AOP_PCODE) {
9485 fprintf(stderr,"genDataPointerSet %s, %d\n",
9486 AOP(result)->aopu.pcop->name,
9487 (AOP(result)->aopu.pcop->type == PO_DIR)?
9488 PCOR(AOP(result)->aopu.pcop)->instance:
9489 PCOI(AOP(result)->aopu.pcop)->offset);
9493 if(AOP(result)->aopu.pcop->type == PO_DIR)
9494 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
9497 if (AOP_TYPE(right) == AOP_LIT) {
9498 unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9500 lit = lit >> (8*offset);
9502 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
9503 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
9505 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
9508 mov2w(AOP(right), offset);
9509 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
9515 pic16_freeAsmop(right,NULL,ic,TRUE);
9520 /*-----------------------------------------------------------------*/
9521 /* genNearPointerSet - pic16_emitcode for near pointer put */
9522 /*-----------------------------------------------------------------*/
9523 static void genNearPointerSet (operand *right,
9530 sym_link *ptype = operandType(result);
9533 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9534 retype= getSpec(operandType(right));
9535 resetype = getSpec(operandType(result));
9537 pic16_aopOp(result,ic,FALSE);
9539 /* if the result is rematerializable &
9540 * in data space & not a bit variable */
9542 /* and result is not a bit variable */
9543 if (AOP_TYPE(result) == AOP_PCODE
9544 // && AOP_TYPE(result) == AOP_IMMD
9545 && DCL_TYPE(ptype) == POINTER
9546 && !IS_BITFIELD(retype)
9547 && !IS_BITFIELD(resetype)) {
9549 genDataPointerSet (right,result,ic);
9550 pic16_freeAsmop(result,NULL,ic,TRUE);
9554 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9555 pic16_aopOp(right,ic,FALSE);
9556 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9558 /* if the value is already in a pointer register
9559 * then don't need anything more */
9560 if (!AOP_INPREG(AOP(result))) {
9561 /* otherwise get a free pointer register */
9562 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9564 if( (AOP_TYPE(result) == AOP_PCODE)
9565 && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
9566 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
9568 pic16_loadFSR0( result ); // patch 10
9570 // set up FSR0 with address of result
9571 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9572 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9577 // rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9579 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9581 /* if bitfield then unpack the bits */
9582 if (IS_BITFIELD(resetype)) {
9583 genPackBits (resetype, right, NULL, POINTER);
9585 /* we have can just get the values */
9586 int size = AOP_SIZE(right);
9589 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9591 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
9594 //pic16_emitcode("mov","@%s,a",rname);
9595 pic16_emitcode("movf","indf0,w ;1");
9598 if (AOP_TYPE(right) == AOP_LIT) { // patch 10
9599 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset)); //
9601 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0)); //
9603 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0)); //
9605 } else { // no literal //
9607 pic16_emitpcode(POC_MOVFF, //
9608 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
9609 pic16_popCopyReg(&pic16_pc_postinc0))); //
9611 pic16_emitpcode(POC_MOVFF, //
9612 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
9613 pic16_popCopyReg(&pic16_pc_indf0))); //
9621 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9622 /* now some housekeeping stuff */
9624 /* we had to allocate for this iCode */
9625 pic16_freeAsmop(NULL,aop,ic,TRUE);
9627 /* we did not allocate which means left
9628 * already in a pointer register, then
9629 * if size > 0 && this could be used again
9630 * we have to point it back to where it
9632 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9633 if (AOP_SIZE(right) > 1
9634 && !OP_SYMBOL(result)->remat
9635 && ( OP_SYMBOL(result)->liveTo > ic->seq
9638 int size = AOP_SIZE(right) - 1;
9641 pic16_emitcode("decf","fsr0,f");
9642 //pic16_emitcode("dec","%s",rname);
9646 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9649 pic16_freeAsmop(right,NULL,ic,TRUE);
9650 pic16_freeAsmop(result,NULL,ic,TRUE);
9653 /*-----------------------------------------------------------------*/
9654 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
9655 /*-----------------------------------------------------------------*/
9656 static void genPagedPointerSet (operand *right,
9665 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9667 retype= getSpec(operandType(right));
9669 pic16_aopOp(result,ic,FALSE);
9671 /* if the value is already in a pointer register
9672 then don't need anything more */
9673 if (!AOP_INPREG(AOP(result))) {
9674 /* otherwise get a free pointer register */
9676 preg = getFreePtr(ic,&aop,FALSE);
9677 pic16_emitcode("mov","%s,%s",
9679 pic16_aopGet(AOP(result),0,FALSE,TRUE));
9680 rname = preg->name ;
9682 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9684 pic16_freeAsmop(result,NULL,ic,TRUE);
9685 pic16_aopOp (right,ic,FALSE);
9687 /* if bitfield then unpack the bits */
9688 if (IS_BITFIELD(retype))
9689 genPackBits (retype,right,rname,PPOINTER);
9691 /* we have can just get the values */
9692 int size = AOP_SIZE(right);
9696 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
9699 pic16_emitcode("movx","@%s,a",rname);
9702 pic16_emitcode("inc","%s",rname);
9708 /* now some housekeeping stuff */
9710 /* we had to allocate for this iCode */
9711 pic16_freeAsmop(NULL,aop,ic,TRUE);
9713 /* we did not allocate which means left
9714 already in a pointer register, then
9715 if size > 0 && this could be used again
9716 we have to point it back to where it
9718 if (AOP_SIZE(right) > 1 &&
9719 !OP_SYMBOL(result)->remat &&
9720 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9722 int size = AOP_SIZE(right) - 1;
9724 pic16_emitcode("dec","%s",rname);
9729 pic16_freeAsmop(right,NULL,ic,TRUE);
9734 /*-----------------------------------------------------------------*/
9735 /* genFarPointerSet - set value from far space */
9736 /*-----------------------------------------------------------------*/
9737 static void genFarPointerSet (operand *right,
9738 operand *result, iCode *ic)
9741 sym_link *retype = getSpec(operandType(right));
9743 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9744 pic16_aopOp(result,ic,FALSE);
9746 /* if the operand is already in dptr
9747 then we do nothing else we move the value to dptr */
9748 if (AOP_TYPE(result) != AOP_STR) {
9749 /* if this is remateriazable */
9750 if (AOP_TYPE(result) == AOP_IMMD)
9751 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
9752 else { /* we need to get it byte by byte */
9753 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
9754 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
9755 if (options.model == MODEL_FLAT24)
9757 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
9761 /* so dptr know contains the address */
9762 pic16_freeAsmop(result,NULL,ic,TRUE);
9763 pic16_aopOp(right,ic,FALSE);
9765 /* if bit then unpack */
9766 if (IS_BITFIELD(retype))
9767 genPackBits(retype,right,"dptr",FPOINTER);
9769 size = AOP_SIZE(right);
9773 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9775 pic16_emitcode("movx","@dptr,a");
9777 pic16_emitcode("inc","dptr");
9781 pic16_freeAsmop(right,NULL,ic,TRUE);
9784 /*-----------------------------------------------------------------*/
9785 /* genGenPointerSet - set value from generic pointer space */
9786 /*-----------------------------------------------------------------*/
9787 static void genGenPointerSet (operand *right,
9788 operand *result, iCode *ic)
9790 int i, size, offset, lit;
9791 sym_link *retype = getSpec(operandType(right));
9793 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9795 pic16_aopOp(result,ic,FALSE);
9796 pic16_aopOp(right,ic,FALSE);
9797 size = AOP_SIZE(right);
9800 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9802 /* if the operand is already in dptr
9803 then we do nothing else we move the value to dptr */
9804 if (AOP_TYPE(result) != AOP_STR) {
9805 /* if this is remateriazable */
9806 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9807 // WARNING: anythig until "else" is untested!
9808 if (AOP_TYPE(result) == AOP_IMMD) {
9809 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9810 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
9811 // load FSR0 from immediate
9812 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9816 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
9818 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
9824 else { /* we need to get it byte by byte */
9825 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9826 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9828 // set up FSR0 with address of result
9829 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9830 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9832 /* hack hack! see if this the FSR. If so don't load W */
9833 if(AOP_TYPE(right) != AOP_ACC) {
9835 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9837 if(AOP_TYPE(right) == AOP_LIT)
9840 // note: pic16_popGet handles sign extension
9841 for(i=0;i<size;i++) {
9842 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
9844 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
9846 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
9851 for(i=0;i<size;i++) {
9853 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
9854 pic16_popCopyReg(&pic16_pc_postinc0)));
9856 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
9857 pic16_popCopyReg(&pic16_pc_indf0)));
9863 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9864 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9866 } // if (AOP_TYPE(result) != AOP_IMMD)
9868 } // if (AOP_TYPE(result) != AOP_STR)
9869 /* so dptr know contains the address */
9872 /* if bit then unpack */
9873 if (IS_BITFIELD(retype))
9874 genPackBits(retype,right,"dptr",GPOINTER);
9876 size = AOP_SIZE(right);
9879 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
9881 // set up FSR0 with address of result
9882 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9883 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9886 if (AOP_TYPE(right) == AOP_LIT) {
9887 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9889 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
9891 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9893 } else { // no literal
9895 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
9897 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
9905 pic16_freeAsmop(right,NULL,ic,TRUE);
9906 pic16_freeAsmop(result,NULL,ic,TRUE);
9909 /*-----------------------------------------------------------------*/
9910 /* genPointerSet - stores the value into a pointer location */
9911 /*-----------------------------------------------------------------*/
9912 static void genPointerSet (iCode *ic)
9914 operand *right, *result ;
9915 sym_link *type, *etype;
9918 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9920 right = IC_RIGHT(ic);
9921 result = IC_RESULT(ic) ;
9923 /* depending on the type of pointer we need to
9924 move it to the correct pointer register */
9925 type = operandType(result);
9926 etype = getSpec(type);
9927 /* if left is of type of pointer then it is simple */
9928 if (IS_PTR(type) && !IS_FUNC(type->next)) {
9929 p_type = DCL_TYPE(type);
9932 /* we have to go by the storage class */
9933 p_type = PTR_TYPE(SPEC_OCLS(etype));
9935 /* if (SPEC_OCLS(etype)->codesp ) { */
9936 /* p_type = CPOINTER ; */
9939 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9940 /* p_type = FPOINTER ; */
9942 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9943 /* p_type = PPOINTER ; */
9945 /* if (SPEC_OCLS(etype) == idata ) */
9946 /* p_type = IPOINTER ; */
9948 /* p_type = POINTER ; */
9951 /* now that we have the pointer type we assign
9952 the pointer values */
9957 genNearPointerSet (right,result,ic);
9961 genPagedPointerSet (right,result,ic);
9965 genFarPointerSet (right,result,ic);
9969 genGenPointerSet (right,result,ic);
9973 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9974 "genPointerSet: illegal pointer type");
9978 /*-----------------------------------------------------------------*/
9979 /* genIfx - generate code for Ifx statement */
9980 /*-----------------------------------------------------------------*/
9981 static void genIfx (iCode *ic, iCode *popIc)
9983 operand *cond = IC_COND(ic);
9986 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9988 pic16_aopOp(cond,ic,FALSE);
9990 /* get the value into acc */
9991 if (AOP_TYPE(cond) != AOP_CRY)
9992 pic16_toBoolean(cond);
9995 /* the result is now in the accumulator */
9996 pic16_freeAsmop(cond,NULL,ic,TRUE);
9998 /* if there was something to be popped then do it */
10002 /* if the condition is a bit variable */
10003 if (isbit && IS_ITEMP(cond) &&
10005 genIfxJump(ic,SPIL_LOC(cond)->rname);
10006 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
10009 if (isbit && !IS_ITEMP(cond))
10010 genIfxJump(ic,OP_SYMBOL(cond)->rname);
10012 genIfxJump(ic,"a");
10018 /*-----------------------------------------------------------------*/
10019 /* genAddrOf - generates code for address of */
10020 /*-----------------------------------------------------------------*/
10021 static void genAddrOf (iCode *ic)
10023 operand *result, *left;
10025 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
10026 pCodeOp *pcop0, *pcop1, *pcop2;
10028 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10030 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
10031 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
10033 sym = OP_SYMBOL( left );
10035 size = AOP_SIZE(IC_RESULT(ic));
10037 if(pic16_debug_verbose) {
10038 fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
10039 __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
10042 /* Assume that what we want the address of is in data space
10043 * since there is no stack on the PIC, yet! -- VR */
10045 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10048 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10051 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10055 pic16_emitpcode(POC_MOVLW, pcop0);
10056 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10057 pic16_emitpcode(POC_MOVLW, pcop1);
10058 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10059 pic16_emitpcode(POC_MOVLW, pcop2);
10060 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10063 pic16_emitpcode(POC_MOVLW, pcop0);
10064 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10065 pic16_emitpcode(POC_MOVLW, pcop1);
10066 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10068 pic16_emitpcode(POC_MOVLW, pcop0);
10069 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10072 pic16_freeAsmop(result,NULL,ic,TRUE);
10073 pic16_freeAsmop(left, NULL, ic, FALSE);
10078 /*-----------------------------------------------------------------*/
10079 /* genFarFarAssign - assignment when both are in far space */
10080 /*-----------------------------------------------------------------*/
10081 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
10083 int size = AOP_SIZE(right);
10086 /* first push the right side on to the stack */
10088 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10090 pic16_emitcode ("push","acc");
10093 pic16_freeAsmop(right,NULL,ic,FALSE);
10094 /* now assign DPTR to result */
10095 pic16_aopOp(result,ic,FALSE);
10096 size = AOP_SIZE(result);
10098 pic16_emitcode ("pop","acc");
10099 pic16_aopPut(AOP(result),"a",--offset);
10101 pic16_freeAsmop(result,NULL,ic,FALSE);
10106 /*-----------------------------------------------------------------*/
10107 /* genAssign - generate code for assignment */
10108 /*-----------------------------------------------------------------*/
10109 static void genAssign (iCode *ic)
10111 operand *result, *right;
10112 int size, offset,know_W;
10113 unsigned long lit = 0L;
10115 result = IC_RESULT(ic);
10116 right = IC_RIGHT(ic) ;
10118 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10120 /* if they are the same */
10121 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10124 pic16_aopOp(right,ic,FALSE);
10125 pic16_aopOp(result,ic,TRUE);
10127 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10129 /* if they are the same registers */
10130 if (pic16_sameRegs(AOP(right),AOP(result)))
10133 /* if the result is a bit */
10134 if (AOP_TYPE(result) == AOP_CRY) {
10135 /* if the right size is a literal then
10136 we know what the value is */
10137 if (AOP_TYPE(right) == AOP_LIT) {
10139 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10140 pic16_popGet(AOP(result),0));
10142 if (((int) operandLitValue(right)))
10143 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10144 AOP(result)->aopu.aop_dir,
10145 AOP(result)->aopu.aop_dir);
10147 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10148 AOP(result)->aopu.aop_dir,
10149 AOP(result)->aopu.aop_dir);
10153 /* the right is also a bit variable */
10154 if (AOP_TYPE(right) == AOP_CRY) {
10155 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
10156 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
10157 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
10159 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10160 AOP(result)->aopu.aop_dir,
10161 AOP(result)->aopu.aop_dir);
10162 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
10163 AOP(right)->aopu.aop_dir,
10164 AOP(right)->aopu.aop_dir);
10165 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10166 AOP(result)->aopu.aop_dir,
10167 AOP(result)->aopu.aop_dir);
10171 /* we need to or */
10172 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
10173 pic16_toBoolean(right);
10175 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
10176 //pic16_aopPut(AOP(result),"a",0);
10180 /* bit variables done */
10182 size = AOP_SIZE(result);
10184 if(AOP_TYPE(right) == AOP_LIT)
10185 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10187 /* VR - What is this?! */
10188 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
10189 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10190 if(aopIdx(AOP(result),0) == 4) {
10191 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10192 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10193 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10196 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
10201 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10202 if(AOP_TYPE(right) == AOP_LIT) {
10204 if(know_W != (lit&0xff))
10205 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
10207 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10209 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10213 } else if (AOP_TYPE(right) == AOP_CRY) {
10214 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10216 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
10217 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
10219 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
10220 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10221 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10223 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10226 /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
10227 normally should work, but mind that the W register live range
10228 is not checked, so if the code generator assumes that the W
10229 is already loaded after such a pair, wrong code will be generated.
10231 Checking the live range is the next step.
10232 This is experimental code yet and has not been fully tested yet.
10233 USE WITH CARE. Revert to old code by setting 0 to the condition above.
10234 Vangelis Rokas 030603 (vrokas@otenet.gr) */
10236 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
10238 /* This is the old code, which is assumed(?!) that works fine(!?) */
10240 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10241 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10250 pic16_freeAsmop (right,NULL,ic,FALSE);
10251 pic16_freeAsmop (result,NULL,ic,TRUE);
10254 /*-----------------------------------------------------------------*/
10255 /* genJumpTab - generates code for jump table */
10256 /*-----------------------------------------------------------------*/
10257 static void genJumpTab (iCode *ic)
10262 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10264 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
10265 /* get the condition into accumulator */
10266 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10268 /* multiply by three */
10269 pic16_emitcode("add","a,acc");
10270 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10272 jtab = newiTempLabel(NULL);
10273 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10274 pic16_emitcode("jmp","@a+dptr");
10275 pic16_emitcode("","%05d_DS_:",jtab->key+100);
10277 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
10278 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
10280 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
10281 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
10282 pic16_emitpLabel(jtab->key);
10284 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10286 /* now generate the jump labels */
10287 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10288 jtab = setNextItem(IC_JTLABELS(ic))) {
10289 pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
10290 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
10296 /*-----------------------------------------------------------------*/
10297 /* genMixedOperation - gen code for operators between mixed types */
10298 /*-----------------------------------------------------------------*/
10300 TSD - Written for the PIC port - but this unfortunately is buggy.
10301 This routine is good in that it is able to efficiently promote
10302 types to different (larger) sizes. Unfortunately, the temporary
10303 variables that are optimized out by this routine are sometimes
10304 used in other places. So until I know how to really parse the
10305 iCode tree, I'm going to not be using this routine :(.
10307 static int genMixedOperation (iCode *ic)
10310 operand *result = IC_RESULT(ic);
10311 sym_link *ctype = operandType(IC_LEFT(ic));
10312 operand *right = IC_RIGHT(ic);
10318 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10320 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10326 nextright = IC_RIGHT(nextic);
10327 nextleft = IC_LEFT(nextic);
10328 nextresult = IC_RESULT(nextic);
10330 pic16_aopOp(right,ic,FALSE);
10331 pic16_aopOp(result,ic,FALSE);
10332 pic16_aopOp(nextright, nextic, FALSE);
10333 pic16_aopOp(nextleft, nextic, FALSE);
10334 pic16_aopOp(nextresult, nextic, FALSE);
10336 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10338 operand *t = right;
10342 pic16_emitcode(";remove right +","");
10344 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10346 operand *t = right;
10350 pic16_emitcode(";remove left +","");
10354 big = AOP_SIZE(nextleft);
10355 small = AOP_SIZE(nextright);
10357 switch(nextic->op) {
10360 pic16_emitcode(";optimize a +","");
10361 /* if unsigned or not an integral type */
10362 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10363 pic16_emitcode(";add a bit to something","");
10366 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10368 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10369 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10370 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10372 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10380 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10381 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10382 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10385 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10387 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10388 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10389 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10390 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10391 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10394 pic16_emitcode("rlf","known_zero,w");
10401 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10402 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10403 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10405 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10415 pic16_freeAsmop(right,NULL,ic,TRUE);
10416 pic16_freeAsmop(result,NULL,ic,TRUE);
10417 pic16_freeAsmop(nextright,NULL,ic,TRUE);
10418 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
10420 nextic->generated = 1;
10427 /*-----------------------------------------------------------------*/
10428 /* genCast - gen code for casting */
10429 /*-----------------------------------------------------------------*/
10430 static void genCast (iCode *ic)
10432 operand *result = IC_RESULT(ic);
10433 sym_link *ctype = operandType(IC_LEFT(ic));
10434 sym_link *rtype = operandType(IC_RIGHT(ic));
10435 operand *right = IC_RIGHT(ic);
10438 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10439 /* if they are equivalent then do nothing */
10440 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10443 pic16_aopOp(right,ic,FALSE) ;
10444 pic16_aopOp(result,ic,FALSE);
10446 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10448 /* if the result is a bit */
10449 if (AOP_TYPE(result) == AOP_CRY) {
10451 /* if the right size is a literal then
10452 * we know what the value is */
10453 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10455 if (AOP_TYPE(right) == AOP_LIT) {
10456 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10457 pic16_popGet(AOP(result),0));
10459 if (((int) operandLitValue(right)))
10460 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
10461 AOP(result)->aopu.aop_dir,
10462 AOP(result)->aopu.aop_dir);
10464 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
10465 AOP(result)->aopu.aop_dir,
10466 AOP(result)->aopu.aop_dir);
10470 /* the right is also a bit variable */
10471 if (AOP_TYPE(right) == AOP_CRY) {
10473 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
10475 pic16_emitcode("clrc","");
10476 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10477 AOP(right)->aopu.aop_dir,
10478 AOP(right)->aopu.aop_dir);
10479 pic16_aopPut(AOP(result),"c",0);
10483 /* we need to or */
10484 if (AOP_TYPE(right) == AOP_REG) {
10485 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
10486 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
10487 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
10489 pic16_toBoolean(right);
10490 pic16_aopPut(AOP(result),"a",0);
10494 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10497 size = AOP_SIZE(result);
10499 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10501 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
10502 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
10503 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
10506 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
10511 /* if they are the same size : or less */
10512 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10514 /* if they are in the same place */
10515 if (pic16_sameRegs(AOP(right),AOP(result)))
10518 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10520 if (IS_PTR_CONST(rtype))
10522 if (IS_CODEPTR(rtype))
10524 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
10527 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10529 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
10531 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
10534 if(AOP_TYPE(right) == AOP_IMMD) {
10535 pCodeOp *pcop0, *pcop1, *pcop2;
10536 symbol *sym = OP_SYMBOL( right );
10538 size = AOP_SIZE(result);
10540 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10542 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10544 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10547 pic16_emitpcode(POC_MOVLW, pcop0);
10548 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10549 pic16_emitpcode(POC_MOVLW, pcop1);
10550 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10551 pic16_emitpcode(POC_MOVLW, pcop2);
10552 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10555 pic16_emitpcode(POC_MOVLW, pcop0);
10556 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10557 pic16_emitpcode(POC_MOVLW, pcop1);
10558 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10560 pic16_emitpcode(POC_MOVLW, pcop0);
10561 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10565 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10566 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
10567 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10568 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
10569 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10570 if(AOP_SIZE(result) <2)
10571 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10573 /* if they in different places then copy */
10574 size = AOP_SIZE(result);
10577 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10578 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10585 /* if the result is of type pointer */
10586 if (IS_PTR(ctype)) {
10588 sym_link *type = operandType(right);
10589 sym_link *etype = getSpec(type);
10591 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
10593 /* pointer to generic pointer */
10594 if (IS_GENPTR(ctype)) {
10598 p_type = DCL_TYPE(type);
10600 /* we have to go by the storage class */
10601 p_type = PTR_TYPE(SPEC_OCLS(etype));
10603 /* if (SPEC_OCLS(etype)->codesp ) */
10604 /* p_type = CPOINTER ; */
10606 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10607 /* p_type = FPOINTER ; */
10609 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10610 /* p_type = PPOINTER; */
10612 /* if (SPEC_OCLS(etype) == idata ) */
10613 /* p_type = IPOINTER ; */
10615 /* p_type = POINTER ; */
10618 /* the first two bytes are known */
10619 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
10620 size = GPTRSIZE - 1;
10623 if(offset < AOP_SIZE(right)) {
10624 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3",__FUNCTION__,__LINE__);
10625 if ((AOP_TYPE(right) == AOP_PCODE) &&
10626 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10627 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10628 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10630 pic16_aopPut(AOP(result),
10631 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
10635 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
10638 /* the last byte depending on type */
10642 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
10645 pic16_emitcode(";BUG!? ","%d",__LINE__);
10649 pic16_emitcode(";BUG!? ","%d",__LINE__);
10653 pic16_emitcode(";BUG!? ","%d",__LINE__);
10658 /* this should never happen */
10659 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10660 "got unknown pointer type");
10663 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
10667 /* just copy the pointers */
10668 size = AOP_SIZE(result);
10671 pic16_aopPut(AOP(result),
10672 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
10681 /* so we now know that the size of destination is greater
10682 than the size of the source.
10683 Now, if the next iCode is an operator then we might be
10684 able to optimize the operation without performing a cast.
10686 if(genMixedOperation(ic))
10689 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10691 /* we move to result for the size of source */
10692 size = AOP_SIZE(right);
10695 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10696 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10700 /* now depending on the sign of the destination */
10701 size = AOP_SIZE(result) - AOP_SIZE(right);
10702 /* if unsigned or not an integral type */
10703 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
10705 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
10707 /* we need to extend the sign :( */
10710 /* Save one instruction of casting char to int */
10711 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10712 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10713 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset));
10715 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
10718 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10720 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0));
10722 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10725 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
10730 pic16_freeAsmop(right,NULL,ic,TRUE);
10731 pic16_freeAsmop(result,NULL,ic,TRUE);
10735 /*-----------------------------------------------------------------*/
10736 /* genDjnz - generate decrement & jump if not zero instrucion */
10737 /*-----------------------------------------------------------------*/
10738 static int genDjnz (iCode *ic, iCode *ifx)
10740 symbol *lbl, *lbl1;
10741 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10746 /* if the if condition has a false label
10747 then we cannot save */
10751 /* if the minus is not of the form
10753 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10754 !IS_OP_LITERAL(IC_RIGHT(ic)))
10757 if (operandLitValue(IC_RIGHT(ic)) != 1)
10760 /* if the size of this greater than one then no
10762 if (getSize(operandType(IC_RESULT(ic))) > 1)
10765 /* otherwise we can save BIG */
10766 lbl = newiTempLabel(NULL);
10767 lbl1= newiTempLabel(NULL);
10769 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10771 if (IS_AOP_PREG(IC_RESULT(ic))) {
10772 pic16_emitcode("dec","%s",
10773 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10774 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10775 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
10779 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
10780 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
10782 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10783 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10786 /* pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10787 /* pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
10788 /* pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10789 /* pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
10792 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10793 ifx->generated = 1;
10797 /*-----------------------------------------------------------------*/
10798 /* genReceive - generate code for a receive iCode */
10799 /*-----------------------------------------------------------------*/
10800 static void genReceive (iCode *ic)
10802 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10804 if (isOperandInFarSpace(IC_RESULT(ic)) &&
10805 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10806 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10808 int size = getSize(operandType(IC_RESULT(ic)));
10809 int offset = pic16_fReturnSizePic - size;
10812 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
10813 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
10817 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
10819 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10820 size = AOP_SIZE(IC_RESULT(ic));
10823 pic16_emitcode ("pop","acc");
10824 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10827 DEBUGpic16_emitcode ("; ***","2 %s %d",__FUNCTION__,__LINE__);
10830 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10832 assignResultValue(IC_RESULT(ic), 0);
10835 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10838 /*-----------------------------------------------------------------*/
10839 /* genDummyRead - generate code for dummy read of volatiles */
10840 /*-----------------------------------------------------------------*/
10842 genDummyRead (iCode * ic)
10844 pic16_emitcode ("; genDummyRead","");
10845 pic16_emitcode ("; not implemented","");
10850 /*-----------------------------------------------------------------*/
10851 /* genpic16Code - generate code for pic16 based controllers */
10852 /*-----------------------------------------------------------------*/
10854 * At this point, ralloc.c has gone through the iCode and attempted
10855 * to optimize in a way suitable for a PIC. Now we've got to generate
10856 * PIC instructions that correspond to the iCode.
10858 * Once the instructions are generated, we'll pass through both the
10859 * peep hole optimizer and the pCode optimizer.
10860 *-----------------------------------------------------------------*/
10862 void genpic16Code (iCode *lic)
10867 lineHead = lineCurr = NULL;
10869 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
10870 pic16_addpBlock(pb);
10873 /* if debug information required */
10874 if (options.debug && currFunc) {
10876 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
10878 if (IS_STATIC(currFunc->etype)) {
10879 pic16_emitcode("",";F%s$%s$0$0 %d",moduleName,currFunc->name,__LINE__);
10880 //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(moduleName,currFunc->name));
10882 pic16_emitcode("",";G$%s$0$0 %d",currFunc->name,__LINE__);
10883 //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,currFunc->name));
10890 for (ic = lic ; ic ; ic = ic->next ) {
10892 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
10893 if ( cln != ic->lineno ) {
10894 if ( options.debug ) {
10896 pic16_emitcode("",";C$%s$%d$%d$%d ==.",
10897 FileBaseName(ic->filename),ic->lineno,
10898 ic->level,ic->block);
10902 if(!options.noCcodeInAsm) {
10903 pic16_addpCode2pBlock(pb,
10904 pic16_newpCodeCSource(ic->lineno, ic->filename,
10905 printCLine(ic->filename, ic->lineno)));
10911 if(options.iCodeInAsm) {
10912 /* insert here code to print iCode as comment */
10913 pic16_emitpcomment("ic:%d: %s", ic->seq, printILine(ic));
10916 /* if the result is marked as
10917 spilt and rematerializable or code for
10918 this has already been generated then
10920 if (resultRemat(ic) || ic->generated )
10923 /* depending on the operation */
10942 /* IPOP happens only when trying to restore a
10943 spilt live range, if there is an ifx statement
10944 following this pop then the if statement might
10945 be using some of the registers being popped which
10946 would destroy the contents of the register so
10947 we need to check for this condition and handle it */
10949 ic->next->op == IFX &&
10950 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10951 genIfx (ic->next,ic);
10969 genEndFunction (ic);
10985 pic16_genPlus (ic) ;
10989 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10990 pic16_genMinus (ic);
11006 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
11010 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
11017 /* note these two are xlated by algebraic equivalence
11018 during parsing SDCC.y */
11019 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11020 "got '>=' or '<=' shouldn't have come here");
11024 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
11036 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
11040 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
11044 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
11068 genRightShift (ic);
11071 case GET_VALUE_AT_ADDRESS:
11076 if (POINTER_SET(ic))
11103 addSet(&_G.sendSet,ic);
11106 case DUMMY_READ_VOLATILE:
11116 /* now we are ready to call the
11117 peep hole optimizer */
11118 if (!options.nopeep) {
11119 peepHole (&lineHead);
11121 /* now do the actual printing */
11122 printLine (lineHead,codeOutFile);
11125 DFPRINTF((stderr,"printing pBlock\n\n"));
11126 pic16_printpBlock(stdout,pb);