1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for pic
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 cont'd - Raphael Neider <rneider AT web.de> (2005)
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 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
42 #include "SDCCpeeph.h"
47 /* When changing these, you must also update the assembler template
48 * in device/lib/libsdcc/macros.inc */
49 #define GPTRTAG_DATA 0x00
50 #define GPTRTAG_CODE 0x80
52 /* The PIC port(s) need not differentiate between POINTER and FPOINTER. */
53 #define PIC_IS_DATA_PTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
54 #define PIC_IS_FARPTR(x) (PIC_IS_DATA_PTR(x))
56 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
57 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
58 void genMult8X8_8 (operand *, operand *,operand *);
59 extern void printpBlock(FILE *of, pBlock *pb);
61 static int labelOffset=0;
62 extern int debug_verbose;
63 extern int pic14_hasInterrupt;
64 //static int optimized_for_speed = 0;
66 /* max_key keeps track of the largest label number used in
67 a function. This is then used to adjust the label offset
68 for the next function.
71 static int GpsuedoStkPtr=0;
73 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
74 extern char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
75 unsigned int pic14aopLiteral (value *val, int offset);
76 const char *AopType(short type);
78 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0x00ff)
80 /* this is the down and dirty file with all kinds of
81 kludgy & hacky stuff. This is what it is all about
82 CODE GENERATION for a specific MCU . some of the
83 routines may be reusable, will have to see */
85 static char *zero = "#0x00";
86 static char *one = "#0x01";
87 static char *spname = "sp";
89 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
90 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
91 static char **fReturn = fReturnpic14;
93 //static char *accUse[] = {"a","b"};
95 //static short rbank = -1;
107 /* Resolved ifx structure. This structure stores information
108 about an iCode ifx that makes it easier to generate code.
110 typedef struct resolvedIfx {
111 symbol *lbl; /* pointer to a label */
112 int condition; /* true or false ifx */
113 int generated; /* set true when the code associated with the ifx
117 extern int pic14_ptrRegReq ;
118 extern int pic14_nRegs;
119 extern FILE *codeOutFile;
120 static void saverbank (int, iCode *,bool);
122 static lineNode *lineHead = NULL;
123 static lineNode *lineCurr = NULL;
126 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
127 0xE0, 0xC0, 0x80, 0x00};
128 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
129 0x07, 0x03, 0x01, 0x00};
134 /*-----------------------------------------------------------------*/
135 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
136 /* exponent of 2 is returned, otherwise -1 is */
138 /* note that this is similar to the function `powof2' in SDCCsymt */
142 /*-----------------------------------------------------------------*/
143 static int my_powof2 (unsigned long num)
146 if( (num & (num-1)) == 0) {
159 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
162 DEBUGpic14_emitcode ("; ","line = %d result %s=%s, size=%d, left %s=%s, size=%d, right %s=%s, size=%d",
164 ((result) ? AopType(AOP_TYPE(result)) : "-"),
165 ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
166 ((result) ? AOP_SIZE(result) : 0),
167 ((left) ? AopType(AOP_TYPE(left)) : "-"),
168 ((left) ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
169 ((left) ? AOP_SIZE(left) : 0),
170 ((right) ? AopType(AOP_TYPE(right)) : "-"),
171 ((right) ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
172 ((right) ? AOP_SIZE(right) : 0));
176 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
179 DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
181 ((result) ? AopType(AOP_TYPE(result)) : "-"),
182 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
183 ((left) ? AopType(AOP_TYPE(left)) : "-"),
184 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
185 ((right) ? AopType(AOP_TYPE(right)) : "-"),
186 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
190 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
193 char lb[INITIAL_INLINEASM];
194 unsigned char *lbp = (unsigned char *)lb;
196 if(!debug_verbose && !options.debug)
203 sprintf(lb,"%s\t",inst);
205 sprintf(lb,"%s",inst);
206 vsprintf(lb+(strlen(lb)),fmt,ap);
210 while (isspace(*lbp)) lbp++;
213 lineCurr = (lineCurr ?
214 connectLine(lineCurr,newLineNode(lb)) :
215 (lineHead = newLineNode(lb)));
216 lineCurr->isInline = _G.inLine;
217 lineCurr->isDebug = _G.debugLine;
219 addpCode2pBlock(pb,newpCodeCharP(lb));
224 static void Safe_vsnprintf (char *buf, size_t size, const char *fmt, va_list ap)
226 #if defined (HAVE_VSNPRINTF)
227 vsnprintf (buf, size, fmt, ap);
228 #elif defined (HAVE_VSPRINTF)
229 vsprintf (buf, size, fmt, ap);
230 if (strlen (buf) >= size)
232 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
234 #elif defined (HAVE_SNPRINTF)
235 snprintf (buf, size, "vs(n)printf required");
236 #elif defined (HAVE_SRINTF)
237 sprintf (buf, "vs(n)printf required");
238 if (strlen (buf) >= size)
240 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
243 assert ( !"neither vsnprintf nor vsprintf is present -- unable to proceed" );
247 void emitpComment (const char *fmt, ...)
254 Safe_vsnprintf (buffer, 4096, fmt, va);
255 //fprintf (stderr, "%s\n" ,buffer);
256 addpCode2pBlock (pb, newpCodeCharP (buffer));
259 Safe_vsnprintf (buffer, 4096, fmt, va);
260 fprintf (stderr, "No current pBlock -- discarding comment [%s]\n", buffer);
266 void emitpLabel(int key)
268 addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
271 /* gen.h defines a macro emitpcode that should be used to call emitpcode
272 * as this allows for easy debugging (ever asked the question: where was
273 * this instruction geenrated? Here is the answer... */
274 void emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
277 addpCode2pBlock(pb,newpCode(poc,pcop));
279 DEBUGpic14_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
282 void emitpcodeNULLop(PIC_OPCODE poc)
285 addpCode2pBlock(pb,newpCode(poc,NULL));
290 /*-----------------------------------------------------------------*/
291 /* pic14_emitcode - writes the code into a file : for now it is simple */
292 /*-----------------------------------------------------------------*/
293 void pic14_emitcode (char *inst,char *fmt, ...)
296 char lb[INITIAL_INLINEASM];
297 unsigned char *lbp = (unsigned char *)lb;
303 sprintf(lb,"%s\t",inst);
305 sprintf(lb,"%s",inst);
306 vsprintf(lb+(strlen(lb)),fmt,ap);
310 while (isspace(*lbp)) lbp++;
313 lineCurr = (lineCurr ?
314 connectLine(lineCurr,newLineNode(lb)) :
315 (lineHead = newLineNode(lb)));
316 lineCurr->isInline = _G.inLine;
317 lineCurr->isDebug = _G.debugLine;
320 addpCode2pBlock(pb,newpCodeCharP(lb));
325 /*-----------------------------------------------------------------*/
326 /* pic14_emitDebuggerSymbol - associate the current code location */
327 /* with a debugger symbol */
328 /*-----------------------------------------------------------------*/
330 pic14_emitDebuggerSymbol (char * debugSym)
333 pic14_emitcode ("", ";%s ==.", debugSym);
338 /*-----------------------------------------------------------------*/
339 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
340 /*-----------------------------------------------------------------*/
341 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
343 bool r0iu = FALSE , r1iu = FALSE;
344 bool r0ou = FALSE , r1ou = FALSE;
346 /* the logic: if r0 & r1 used in the instruction
347 then we are in trouble otherwise */
349 /* first check if r0 & r1 are used by this
350 instruction, in which case we are in trouble */
351 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
352 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
357 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
358 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
360 /* if no usage of r0 then return it */
361 if (!r0iu && !r0ou) {
362 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
363 (*aopp)->type = AOP_R0;
365 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
368 /* if no usage of r1 then return it */
369 if (!r1iu && !r1ou) {
370 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
371 (*aopp)->type = AOP_R1;
373 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
376 /* now we know they both have usage */
377 /* if r0 not used in this instruction */
379 /* push it if not already pushed */
381 //pic14_emitcode ("push","%s",
382 // pic14_regWithIdx(R0_IDX)->dname);
386 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
387 (*aopp)->type = AOP_R0;
389 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
392 /* if r1 not used then */
395 /* push it if not already pushed */
397 //pic14_emitcode ("push","%s",
398 // pic14_regWithIdx(R1_IDX)->dname);
402 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
403 (*aopp)->type = AOP_R1;
404 return pic14_regWithIdx(R1_IDX);
408 /* I said end of world but not quite end of world yet */
409 /* if this is a result then we can push it on the stack*/
411 (*aopp)->type = AOP_STK;
415 /* other wise this is true end of the world */
416 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
417 "getFreePtr should never reach here");
422 /*-----------------------------------------------------------------*/
423 /* newAsmop - creates a new asmOp */
424 /*-----------------------------------------------------------------*/
425 asmop *newAsmop (short type)
429 aop = Safe_calloc(1,sizeof(asmop));
434 static void genSetDPTR(int n)
438 pic14_emitcode(";", "Select standard DPTR");
439 pic14_emitcode("mov", "dps, #0x00");
443 pic14_emitcode(";", "Select alternate DPTR");
444 pic14_emitcode("mov", "dps, #0x01");
448 /*-----------------------------------------------------------------*/
449 /* resolveIfx - converts an iCode ifx into a form more useful for */
450 /* generating code */
451 /*-----------------------------------------------------------------*/
452 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
457 // DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
459 resIfx->condition = 1; /* assume that the ifx is true */
460 resIfx->generated = 0; /* indicate that the ifx has not been used */
463 resIfx->lbl = NULL; /* this is wrong: newiTempLabel(NULL); / * oops, there is no ifx. so create a label */
465 DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
466 __FUNCTION__,__LINE__,resIfx->lbl->key);
470 resIfx->lbl = IC_TRUE(ifx);
472 resIfx->lbl = IC_FALSE(ifx);
473 resIfx->condition = 0;
477 DEBUGpic14_emitcode("; ***","ifx true is non-null");
479 DEBUGpic14_emitcode("; ***","ifx false is non-null");
483 // DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
486 /*-----------------------------------------------------------------*/
487 /* pointerCode - returns the code for a pointer type */
488 /*-----------------------------------------------------------------*/
490 static int pointerCode (sym_link *etype)
493 return PTR_TYPE(SPEC_OCLS(etype));
498 /*-----------------------------------------------------------------*/
499 /* aopForSym - for a true symbol */
500 /*-----------------------------------------------------------------*/
501 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
504 memmap *space= SPEC_OCLS(sym->etype);
506 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
507 /* if already has one */
512 /* assign depending on the storage class */
513 /* if it is on the stack or indirectly addressable */
514 /* space we need to assign either r0 or r1 to it */
515 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
516 sym->aop = aop = newAsmop(0);
517 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
518 aop->size = getSize(sym->type);
520 /* now assign the address of the variable to
521 the pointer register */
522 if (aop->type != AOP_STK) {
526 pic14_emitcode("push","acc");
528 pic14_emitcode("mov","a,_bp");
529 pic14_emitcode("add","a,#0x%02x",
531 ((char)(sym->stack - _G.nRegsSaved )) :
532 ((char)sym->stack)) & 0xff);
533 pic14_emitcode("mov","%s,a",
534 aop->aopu.aop_ptr->name);
537 pic14_emitcode("pop","acc");
539 pic14_emitcode("mov","%s,#%s",
540 aop->aopu.aop_ptr->name,
542 aop->paged = space->paged;
544 aop->aopu.aop_stk = sym->stack;
548 if (sym->onStack && options.stack10bit)
550 /* It's on the 10 bit stack, which is located in
554 //DEBUGpic14_emitcode(";","%d",__LINE__);
557 pic14_emitcode("push","acc");
559 pic14_emitcode("mov","a,_bp");
560 pic14_emitcode("add","a,#0x%02x",
562 ((char)(sym->stack - _G.nRegsSaved )) :
563 ((char)sym->stack)) & 0xff);
566 pic14_emitcode ("mov","dpx1,#0x40");
567 pic14_emitcode ("mov","dph1,#0x00");
568 pic14_emitcode ("mov","dpl1, a");
572 pic14_emitcode("pop","acc");
574 sym->aop = aop = newAsmop(AOP_DPTR2);
575 aop->size = getSize(sym->type);
580 //DEBUGpic14_emitcode(";","%d",__LINE__);
581 /* if in bit space */
582 if (IN_BITSPACE(space)) {
583 sym->aop = aop = newAsmop (AOP_CRY);
584 aop->aopu.aop_dir = sym->rname ;
585 aop->size = getSize(sym->type);
586 //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
589 /* if it is in direct space */
590 if (IN_DIRSPACE(space)) {
591 sym->aop = aop = newAsmop (AOP_DIR);
592 aop->aopu.aop_dir = sym->rname ;
593 aop->size = getSize(sym->type);
594 DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
598 /* special case for a function */
599 if (IS_FUNC(sym->type)) {
601 sym->aop = aop = newAsmop(AOP_PCODE);
602 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
603 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
604 PCOI(aop->aopu.pcop)->_function = 1;
605 PCOI(aop->aopu.pcop)->index = 0;
606 aop->size = FPTRSIZE;
608 sym->aop = aop = newAsmop(AOP_IMMD);
609 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
610 strcpy(aop->aopu.aop_immd,sym->rname);
611 aop->size = FPTRSIZE;
613 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
617 if (IS_ARRAY(sym->type)) {
618 sym->aop = aop = newAsmop(AOP_PCODE);
619 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
620 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
621 PCOI(aop->aopu.pcop)->_function = 0;
622 PCOI(aop->aopu.pcop)->index = 0;
623 aop->size = getSize(sym->etype) * DCL_ELEM(sym->type);
625 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
629 /* only remaining is far space */
630 /* in which case DPTR gets the address */
631 sym->aop = aop = newAsmop(AOP_PCODE);
633 aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
634 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
635 PCOI(aop->aopu.pcop)->index = 0;
637 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
638 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
640 allocDirReg (IC_LEFT(ic));
642 aop->size = FPTRSIZE;
644 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
645 sym->aop = aop = newAsmop(AOP_DPTR);
646 pic14_emitcode ("mov","dptr,#%s", sym->rname);
647 aop->size = getSize(sym->type);
649 DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
652 /* if it is in code space */
653 if (IN_CODESPACE(space))
659 /*-----------------------------------------------------------------*/
660 /* aopForRemat - rematerialzes an object */
661 /*-----------------------------------------------------------------*/
662 static asmop *aopForRemat (operand *op) // x symbol *sym)
664 symbol *sym = OP_SYMBOL(op);
666 asmop *aop = newAsmop(AOP_PCODE);
670 ic = sym->rematiCode;
672 DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
673 if(IS_OP_POINTER(op)) {
674 DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
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;
688 aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
689 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
690 PCOI(aop->aopu.pcop)->index = val;
692 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
693 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
694 val, IS_PTR_CONST(operandType(op)));
696 // DEBUGpic14_emitcode(";","aop type %s",AopType(AOP_TYPE(IC_LEFT(ic))));
698 allocDirReg (IC_LEFT(ic));
703 int aopIdx (asmop *aop, int offset)
708 if(aop->type != AOP_REG)
711 return aop->aopu.aop_reg[offset]->rIdx;
714 /*-----------------------------------------------------------------*/
715 /* regsInCommon - two operands have some registers in common */
716 /*-----------------------------------------------------------------*/
717 static bool regsInCommon (operand *op1, operand *op2)
722 /* if they have registers in common */
723 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
726 sym1 = OP_SYMBOL(op1);
727 sym2 = OP_SYMBOL(op2);
729 if (sym1->nRegs == 0 || sym2->nRegs == 0)
732 for (i = 0 ; i < sym1->nRegs ; i++) {
737 for (j = 0 ; j < sym2->nRegs ;j++ ) {
741 if (sym2->regs[j] == sym1->regs[i])
749 /*-----------------------------------------------------------------*/
750 /* operandsEqu - equivalent */
751 /*-----------------------------------------------------------------*/
752 static bool operandsEqu ( operand *op1, operand *op2)
756 /* if they not symbols */
757 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
760 sym1 = OP_SYMBOL(op1);
761 sym2 = OP_SYMBOL(op2);
763 /* if both are itemps & one is spilt
764 and the other is not then false */
765 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
766 sym1->isspilt != sym2->isspilt )
769 /* if they are the same */
773 if (sym1->rname[0] && sym2->rname[0]
774 && strcmp (sym1->rname, sym2->rname) == 0)
778 /* if left is a tmp & right is not */
782 (sym1->usl.spillLoc == sym2))
789 (sym2->usl.spillLoc == sym1))
795 /*-----------------------------------------------------------------*/
796 /* pic14_sameRegs - two asmops have the same registers */
797 /*-----------------------------------------------------------------*/
798 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
805 if (aop1->type != AOP_REG ||
806 aop2->type != AOP_REG )
809 if (aop1->size != aop2->size )
812 for (i = 0 ; i < aop1->size ; i++ )
813 if (aop1->aopu.aop_reg[i] !=
814 aop2->aopu.aop_reg[i] )
820 /*-----------------------------------------------------------------*/
821 /* aopOp - allocates an asmop for an operand : */
822 /*-----------------------------------------------------------------*/
823 void aopOp (operand *op, iCode *ic, bool result)
832 /* if this a literal */
833 if (IS_OP_LITERAL(op)) {
834 op->aop = aop = newAsmop(AOP_LIT);
835 aop->aopu.aop_lit = op->operand.valOperand;
836 aop->size = getSize(operandType(op));
841 sym_link *type = operandType(op);
842 if(IS_PTR_CONST(type))
843 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
846 /* if already has a asmop then continue */
850 /* if the underlying symbol has a aop */
851 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
852 DEBUGpic14_emitcode(";","%d",__LINE__);
853 op->aop = OP_SYMBOL(op)->aop;
857 /* if this is a true symbol */
858 if (IS_TRUE_SYMOP(op)) {
859 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
860 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
864 /* this is a temporary : this has
870 e) can be a return use only */
875 /* if the type is a conditional */
876 if (sym->regType == REG_CND) {
877 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
882 /* if it is spilt then two situations
884 b) has a spill location */
885 if (sym->isspilt || sym->nRegs == 0) {
887 DEBUGpic14_emitcode(";","%d",__LINE__);
888 /* rematerialize it NOW */
891 sym->aop = op->aop = aop = aopForRemat (op);
892 aop->size = getSize(sym->type);
893 //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
898 /* WREG is not usable as an ordinary operand with PIC architecture,
899 * one might introduce a scratch register that can be used to make
900 * WREG accesible as an operand... disable WREG for now */
903 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
904 aop->size = getSize(sym->type);
905 for ( i = 0 ; i < 2 ; i++ )
906 aop->aopu.aop_str[i] = accUse[i];
907 DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
913 if(sym->isptr) { // && sym->uptr
914 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
915 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
917 //PCOI(aop->aopu.pcop)->_const = 0;
918 //PCOI(aop->aopu.pcop)->index = 0;
920 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
921 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
923 //allocDirReg (IC_LEFT(ic));
925 aop->size = getSize(sym->type);
926 DEBUGpic14_emitcode(";","%d",__LINE__);
933 aop = op->aop = sym->aop = newAsmop(AOP_STR);
934 aop->size = getSize(sym->type);
935 for ( i = 0 ; i < fReturnSizePic ; i++ )
936 aop->aopu.aop_str[i] = fReturn[i];
938 DEBUGpic14_emitcode(";","%d",__LINE__);
943 /* else spill location */
944 if (sym->usl.spillLoc)
946 asmop *oldAsmOp = NULL;
948 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
950 /* force a new aop if sizes differ */
951 oldAsmOp = sym->usl.spillLoc->aop;
952 sym->usl.spillLoc->aop = NULL;
954 DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
955 __FUNCTION__,__LINE__,
956 sym->usl.spillLoc->rname,
957 sym->rname, sym->usl.spillLoc->offset);
959 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
960 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
962 /* Don't reuse the new aop, go with the last one */
963 sym->usl.spillLoc->aop = oldAsmOp;
965 //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
966 aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname,
968 sym->usl.spillLoc->offset);
969 aop->size = getSize(sym->type);
976 sym_link *type = operandType(op);
977 if(IS_PTR_CONST(type))
978 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
981 /* must be in a register */
982 DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
983 sym->aop = op->aop = aop = newAsmop(AOP_REG);
984 aop->size = sym->nRegs;
985 for ( i = 0 ; i < sym->nRegs ;i++)
986 aop->aopu.aop_reg[i] = sym->regs[i];
989 /*-----------------------------------------------------------------*/
990 /* freeAsmop - free up the asmop given to an operand */
991 /*----------------------------------------------------------------*/
992 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1009 /* depending on the asmop type only three cases need work AOP_RO
1010 , AOP_R1 && AOP_STK */
1012 switch (aop->type) {
1016 pic14_emitcode ("pop","ar0");
1020 bitVectUnSetBit(ic->rUsed,R0_IDX);
1026 pic14_emitcode ("pop","ar1");
1030 bitVectUnSetBit(ic->rUsed,R1_IDX);
1036 int stk = aop->aopu.aop_stk + aop->size;
1037 bitVectUnSetBit(ic->rUsed,R0_IDX);
1038 bitVectUnSetBit(ic->rUsed,R1_IDX);
1040 getFreePtr(ic,&aop,FALSE);
1042 if (options.stack10bit)
1044 /* I'm not sure what to do here yet... */
1047 "*** Warning: probably generating bad code for "
1048 "10 bit stack mode.\n");
1052 pic14_emitcode ("mov","a,_bp");
1053 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1054 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1056 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1060 pic14_emitcode("pop","acc");
1061 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1063 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1066 freeAsmop(op,NULL,ic,TRUE);
1068 pic14_emitcode("pop","ar0");
1073 pic14_emitcode("pop","ar1");
1081 /* all other cases just dealloc */
1085 OP_SYMBOL(op)->aop = NULL;
1086 /* if the symbol has a spill */
1088 SPIL_LOC(op)->aop = NULL;
1093 /*-----------------------------------------------------------------*/
1094 /* aopGet - for fetching value of the aop */
1095 /*-----------------------------------------------------------------*/
1096 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1101 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1102 /* offset is greater than
1104 if (offset > (aop->size - 1) &&
1105 aop->type != AOP_LIT)
1108 /* depending on type */
1109 switch (aop->type) {
1113 DEBUGpic14_emitcode(";","%d",__LINE__);
1114 /* if we need to increment it */
1115 while (offset > aop->coff) {
1116 pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);
1120 while (offset < aop->coff) {
1121 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1125 aop->coff = offset ;
1127 pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1128 return (dname ? "acc" : "a");
1130 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1131 rs = Safe_calloc(1,strlen(s)+1);
1137 DEBUGpic14_emitcode(";","%d",__LINE__);
1138 if (aop->type == AOP_DPTR2)
1143 while (offset > aop->coff) {
1144 pic14_emitcode ("inc","dptr");
1148 while (offset < aop->coff) {
1149 pic14_emitcode("lcall","__decdptr");
1155 pic14_emitcode("clr","a");
1156 pic14_emitcode("movc","a,@a+dptr");
1159 pic14_emitcode("movx","a,@dptr");
1162 if (aop->type == AOP_DPTR2)
1167 return (dname ? "acc" : "a");
1172 sprintf (s,"%s",aop->aopu.aop_immd);
1175 sprintf(s,"(%s >> %d)",
1180 aop->aopu.aop_immd);
1181 DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1182 rs = Safe_calloc(1,strlen(s)+1);
1188 sprintf(s,"(%s + %d)",
1191 DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1193 sprintf(s,"%s",aop->aopu.aop_dir);
1194 rs = Safe_calloc(1,strlen(s)+1);
1200 // return aop->aopu.aop_reg[offset]->dname;
1202 return aop->aopu.aop_reg[offset]->name;
1205 //pic14_emitcode(";","%d",__LINE__);
1206 return aop->aopu.aop_dir;
1209 DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1210 return "AOP_accumulator_bug";
1213 sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1214 rs = Safe_calloc(1,strlen(s)+1);
1219 aop->coff = offset ;
1220 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1223 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1225 return aop->aopu.aop_str[offset];
1229 pCodeOp *pcop = aop->aopu.pcop;
1230 DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1233 DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
1234 sprintf(s,"(%s+%d)", pcop->name,offset);
1236 DEBUGpic14_emitcode(";","%s",pcop->name);
1237 sprintf(s,"%s", pcop->name);
1240 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1243 rs = Safe_calloc(1,strlen(s)+1);
1249 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1250 "aopget got unsupported aop->type");
1255 /*-----------------------------------------------------------------*/
1256 /* popGetTempReg - create a new temporary pCodeOp */
1257 /*-----------------------------------------------------------------*/
1258 pCodeOp *popGetTempReg(void)
1263 pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1264 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1265 PCOR(pcop)->r->wasUsed=1;
1266 PCOR(pcop)->r->isFree=0;
1272 /*-----------------------------------------------------------------*/
1273 /* popReleaseTempReg - create a new temporary pCodeOp */
1274 /*-----------------------------------------------------------------*/
1275 void popReleaseTempReg(pCodeOp *pcop)
1278 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1279 PCOR(pcop)->r->isFree = 1;
1282 /*-----------------------------------------------------------------*/
1283 /* popGetLabel - create a new pCodeOp of type PO_LABEL */
1284 /*-----------------------------------------------------------------*/
1285 pCodeOp *popGetLabel(unsigned int key)
1288 DEBUGpic14_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1290 if(key>(unsigned int)max_key)
1293 return newpCodeOpLabel(NULL,key+100+labelOffset);
1296 /*-------------------------------------------------------------------*/
1297 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1298 /*-------------------------------------------------------------------*/
1299 pCodeOp *popGetHighLabel(unsigned int key)
1302 pcop = popGetLabel(key);
1303 PCOLAB(pcop)->offset = 1;
1307 /*-----------------------------------------------------------------*/
1308 /* popGetLit - asm operator to pcode operator conversion */
1309 /*-----------------------------------------------------------------*/
1310 pCodeOp *popGetLit(unsigned int lit)
1313 return newpCodeOpLit((unsigned char)lit);
1316 /*-----------------------------------------------------------------*/
1317 /* popGetImmd - asm operator to pcode immediate conversion */
1318 /*-----------------------------------------------------------------*/
1319 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1322 return newpCodeOpImmd(name, offset,index, 0, is_func);
1325 extern set *externs;
1327 /*-----------------------------------------------------------------*/
1328 /* popGetWithString - asm operator to pcode operator conversion */
1329 /*-----------------------------------------------------------------*/
1330 pCodeOp *popGetWithString(char *str, int isExtern)
1336 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1340 pcop = newpCodeOp(str,PO_STR);
1341 PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1346 pCodeOp *popGetExternal (char *str)
1348 pCodeOp *pcop = popGetWithString (str, 1);
1354 for (sym = setFirstItem (externs); !found && sym; sym = setNextItem (externs))
1356 if (!strcmp (str, sym->rname))
1362 sym = newSymbol(str, 0);
1363 strncpy(sym->rname, str, SDCC_NAME_MAX);
1364 addSet (&externs, sym);
1370 /*-----------------------------------------------------------------*/
1371 /* popRegFromString - */
1372 /*-----------------------------------------------------------------*/
1373 pCodeOp *popRegFromString(char *str, int size, int offset)
1376 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1377 pcop->type = PO_DIR;
1379 DEBUGpic14_emitcode(";","%d",__LINE__);
1384 pcop->name = Safe_calloc(1,strlen(str)+1);
1385 strcpy(pcop->name,str);
1387 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1389 PCOR(pcop)->r = dirregWithName(pcop->name);
1390 if(PCOR(pcop)->r == NULL) {
1391 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1392 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1393 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1395 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1397 PCOR(pcop)->instance = offset;
1402 /*-----------------------------------------------------------------*/
1403 /*-----------------------------------------------------------------*/
1404 pCodeOp *popRegFromIdx(int rIdx)
1408 DEBUGpic14_emitcode ("; ***","%s,%d , rIdx=0x%x",
1409 __FUNCTION__,__LINE__,rIdx);
1411 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1413 PCOR(pcop)->rIdx = rIdx;
1414 PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1415 PCOR(pcop)->r->isFree = 0;
1416 PCOR(pcop)->r->wasUsed = 1;
1418 pcop->type = PCOR(pcop)->r->pc_type;
1424 /*-----------------------------------------------------------------*/
1425 /* popGet - asm operator to pcode operator conversion */
1426 /*-----------------------------------------------------------------*/
1427 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1429 //char *s = buffer ;
1434 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1435 /* offset is greater than
1440 /* XXX: still needed for BIT operands (AOP_CRY) */
1441 if (offset > (aop->size - 1) &&
1442 aop->type != AOP_LIT)
1443 return NULL; //zero;
1445 /* depending on type */
1446 switch (aop->type) {
1453 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1457 DEBUGpic14_emitcode(";","%d",__LINE__);
1458 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1461 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1463 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1464 pcop->type = PO_DIR;
1466 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1467 strcpy(pcop->name,aop->aopu.aop_dir);
1468 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1469 if(PCOR(pcop)->r == NULL) {
1470 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1471 PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1472 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1474 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1476 PCOR(pcop)->instance = offset;
1484 assert (offset < aop->size);
1485 rIdx = aop->aopu.aop_reg[offset]->rIdx;
1487 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1488 PCOR(pcop)->rIdx = rIdx;
1489 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1490 PCOR(pcop)->r->wasUsed=1;
1491 PCOR(pcop)->r->isFree=0;
1493 PCOR(pcop)->instance = offset;
1494 pcop->type = PCOR(pcop)->r->pc_type;
1495 //rs = aop->aopu.aop_reg[offset]->name;
1496 DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1501 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1502 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1503 //if(PCOR(pcop)->r == NULL)
1504 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1508 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1511 DEBUGpic14_emitcode(";","%d %s",__LINE__,aop->aopu.aop_str[offset]);
1512 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1514 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1515 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1516 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1517 pcop->type = PCOR(pcop)->r->pc_type;
1518 pcop->name = PCOR(pcop)->r->name;
1525 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1527 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1528 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1529 switch (aop->aopu.pcop->type)
1532 pcop = pCodeOpCopy (aop->aopu.pcop);
1533 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1534 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1535 PCOI(pcop)->index += offset;
1536 //PCOI(pcop)->offset = 0;
1539 pcop = pCodeOpCopy (aop->aopu.pcop);
1540 PCOR(pcop)->instance = offset;
1543 assert ( !"unhandled pCode type" );
1549 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1550 "popGet got unsupported aop->type");
1554 /*-----------------------------------------------------------------*/
1555 /* popGetAddr - access the low/high word of a symbol (immediate) */
1556 /* (for non-PO_IMMEDIATEs this is the same as popGet) */
1557 /*-----------------------------------------------------------------*/
1558 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1560 if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1562 pCodeOp *pcop = aop->aopu.pcop;
1563 assert (offset <= GPTRSIZE);
1565 /* special case: index >= 2 should return GPOINTER-style values */
1568 pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1572 pcop = pCodeOpCopy (pcop);
1573 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1574 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1575 PCOI(pcop)->offset += offset;
1576 PCOI(pcop)->index += index;
1577 //fprintf (stderr, "is PO_IMMEDIATE: %s+o%d+i%d (new o%d,i%d)\n", pcop->name,PCOI(pcop)->offset,PCOI(pcop)->index, offset, index);
1580 return popGet (aop, offset + index);
1584 /*-----------------------------------------------------------------*/
1585 /* aopPut - puts a string for a aop */
1586 /*-----------------------------------------------------------------*/
1587 void aopPut (asmop *aop, char *s, int offset)
1592 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1594 if (aop->size && offset > ( aop->size - 1)) {
1595 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1596 "aopPut got offset > aop->size");
1600 /* will assign value to value */
1601 /* depending on where it is ofcourse */
1602 switch (aop->type) {
1605 sprintf(d,"(%s + %d)",
1606 aop->aopu.aop_dir,offset);
1607 fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1610 sprintf(d,"%s",aop->aopu.aop_dir);
1613 DEBUGpic14_emitcode(";","%d",__LINE__);
1615 pic14_emitcode("movf","%s,w",s);
1616 pic14_emitcode("movwf","%s",d);
1619 pic14_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
1620 if(offset >= aop->size) {
1621 emitpcode(POC_CLRF,popGet(aop,offset));
1624 emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
1627 emitpcode(POC_MOVWF,popGet(aop,offset));
1633 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1634 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1637 strcmp(s,"r0") == 0 ||
1638 strcmp(s,"r1") == 0 ||
1639 strcmp(s,"r2") == 0 ||
1640 strcmp(s,"r3") == 0 ||
1641 strcmp(s,"r4") == 0 ||
1642 strcmp(s,"r5") == 0 ||
1643 strcmp(s,"r6") == 0 ||
1644 strcmp(s,"r7") == 0 )
1645 pic14_emitcode("mov","%s,%s ; %d",
1646 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1650 if(strcmp(s,"W")==0 )
1651 pic14_emitcode("movf","%s,w ; %d",s,__LINE__);
1653 pic14_emitcode("movwf","%s",
1654 aop->aopu.aop_reg[offset]->name);
1656 if(strcmp(s,zero)==0) {
1657 emitpcode(POC_CLRF,popGet(aop,offset));
1659 } else if(strcmp(s,"W")==0) {
1660 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1661 pcop->type = PO_GPR_REGISTER;
1663 PCOR(pcop)->rIdx = -1;
1664 PCOR(pcop)->r = NULL;
1666 DEBUGpic14_emitcode(";","%d",__LINE__);
1667 pcop->name = Safe_strdup(s);
1668 emitpcode(POC_MOVFW,pcop);
1669 emitpcode(POC_MOVWF,popGet(aop,offset));
1670 } else if(strcmp(s,one)==0) {
1671 emitpcode(POC_CLRF,popGet(aop,offset));
1672 emitpcode(POC_INCF,popGet(aop,offset));
1674 emitpcode(POC_MOVWF,popGet(aop,offset));
1682 if (aop->type == AOP_DPTR2)
1688 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1689 "aopPut writting to code space");
1693 while (offset > aop->coff) {
1695 pic14_emitcode ("inc","dptr");
1698 while (offset < aop->coff) {
1700 pic14_emitcode("lcall","__decdptr");
1705 /* if not in accumulater */
1708 pic14_emitcode ("movx","@dptr,a");
1710 if (aop->type == AOP_DPTR2)
1718 while (offset > aop->coff) {
1720 pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1722 while (offset < aop->coff) {
1724 pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1730 pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1735 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1737 if (strcmp(s,"r0") == 0 ||
1738 strcmp(s,"r1") == 0 ||
1739 strcmp(s,"r2") == 0 ||
1740 strcmp(s,"r3") == 0 ||
1741 strcmp(s,"r4") == 0 ||
1742 strcmp(s,"r5") == 0 ||
1743 strcmp(s,"r6") == 0 ||
1744 strcmp(s,"r7") == 0 ) {
1746 sprintf(buffer,"a%s",s);
1747 pic14_emitcode("mov","@%s,%s",
1748 aop->aopu.aop_ptr->name,buffer);
1750 pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1755 if (strcmp(s,"a") == 0)
1756 pic14_emitcode("push","acc");
1758 pic14_emitcode("push","%s",s);
1763 /* if bit variable */
1764 if (!aop->aopu.aop_dir) {
1765 pic14_emitcode("clr","a");
1766 pic14_emitcode("rlc","a");
1769 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1772 pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1775 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1777 lbl = newiTempLabel(NULL);
1779 if (strcmp(s,"a")) {
1782 pic14_emitcode("clr","c");
1783 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1784 pic14_emitcode("cpl","c");
1785 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1786 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1793 if (strcmp(aop->aopu.aop_str[offset],s))
1794 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1799 if (!offset && (strcmp(s,"acc") == 0))
1802 if (strcmp(aop->aopu.aop_str[offset],s))
1803 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1807 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1808 "aopPut got unsupported aop->type");
1814 /*-----------------------------------------------------------------*/
1815 /* mov2w_op - generate either a MOVLW or MOVFW based operand type */
1816 /*-----------------------------------------------------------------*/
1817 static void mov2w_op (operand *op, int offset)
1822 /* for PO_IMMEDIATEs: use address or value? */
1823 if (op_isLitLike (op))
1825 /* access address of op */
1826 if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
1827 if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
1829 if (offset == GPTRSIZE-1)
1830 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1832 emitpcode (POC_MOVLW, popGetLit (0));
1835 emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
1837 /* access value stored in op */
1838 mov2w (AOP(op), offset);
1843 /*-----------------------------------------------------------------*/
1844 /* mov2w - generate either a MOVLW or MOVFW based operand type */
1845 /*-----------------------------------------------------------------*/
1846 void mov2w (asmop *aop, int offset)
1852 DEBUGpic14_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
1854 if ( aop_isLitLike (aop) )
1855 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1857 emitpcode(POC_MOVFW,popGet(aop,offset));
1861 static void movwf (asmop *op, int offset)
1863 emitpcode (POC_MOVWF, popGet(op, offset));
1866 static pCodeOp *get_argument_pcop (int idx)
1868 assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1869 return popRegFromIdx (Gstack_base_addr - (idx - 1));
1872 static pCodeOp *get_return_val_pcop (int offset)
1874 assert (offset > 0 && "the most significant byte is returned via WREG");
1875 return popRegFromIdx (Gstack_base_addr - (offset - 1));
1878 static void pass_argument (operand *op, int offset, int idx)
1881 mov2w_op (op, offset);
1883 emitpcode(POC_MOVWF, get_argument_pcop (idx));
1886 static void get_returnvalue (operand *op, int offset, int idx)
1889 emitpcode(POC_MOVFW, get_return_val_pcop (idx));
1890 movwf(AOP(op), offset);
1893 static void call_libraryfunc (char *name)
1895 /* library code might reside in different page... */
1896 emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1897 /* call the library function */
1898 emitpcode (POC_CALL, popGetExternal (name));
1899 /* might return from different page... */
1900 emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1903 /*-----------------------------------------------------------------*/
1904 /* reAdjustPreg - points a register back to where it should */
1905 /*-----------------------------------------------------------------*/
1906 static void reAdjustPreg (asmop *aop)
1910 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1912 if ((size = aop->size) <= 1)
1915 switch (aop->type) {
1919 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1923 if (aop->type == AOP_DPTR2)
1929 pic14_emitcode("lcall","__decdptr");
1932 if (aop->type == AOP_DPTR2)
1945 /*-----------------------------------------------------------------*/
1946 /* opIsGptr: returns non-zero if the passed operand is */
1947 /* a generic pointer type. */
1948 /*-----------------------------------------------------------------*/
1949 static int opIsGptr(operand *op)
1951 sym_link *type = operandType(op);
1953 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1954 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1962 /*-----------------------------------------------------------------*/
1963 /* pic14_getDataSize - get the operand data size */
1964 /*-----------------------------------------------------------------*/
1965 int pic14_getDataSize(operand *op)
1969 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1972 size = getSize(OP_SYM_ETYPE(op));
1974 //return AOP_SIZE(op);
1976 // tsd- in the pic port, the genptr size is 1, so this code here
1977 // fails. ( in the 8051 port, the size was 4).
1979 size = AOP_SIZE(op);
1980 if (IS_GENPTR(OP_SYM_TYPE(op)))
1982 sym_link *type = operandType(op);
1983 if (IS_GENPTR(type))
1985 /* generic pointer; arithmetic operations
1986 * should ignore the high byte (pointer type).
1989 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1996 /*-----------------------------------------------------------------*/
1997 /* pic14_outAcc - output Acc */
1998 /*-----------------------------------------------------------------*/
1999 void pic14_outAcc(operand *result)
2002 DEBUGpic14_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2003 DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
2006 size = pic14_getDataSize(result);
2008 emitpcode(POC_MOVWF,popGet(AOP(result),0));
2011 /* unsigned or positive */
2013 emitpcode(POC_CLRF,popGet(AOP(result),offset++));
2018 /*-----------------------------------------------------------------*/
2019 /* pic14_outBitC - output a bit C */
2020 /*-----------------------------------------------------------------*/
2021 void pic14_outBitC(operand *result)
2024 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2025 /* if the result is bit */
2026 if (AOP_TYPE(result) == AOP_CRY)
2027 aopPut(AOP(result),"c",0);
2029 pic14_emitcode("clr","a ; %d", __LINE__);
2030 pic14_emitcode("rlc","a");
2031 pic14_outAcc(result);
2035 /*-----------------------------------------------------------------*/
2036 /* pic14_toBoolean - emit code for orl a,operator(sizeop) */
2037 /*-----------------------------------------------------------------*/
2038 void pic14_toBoolean(operand *oper)
2040 int size = AOP_SIZE(oper);
2043 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2048 /* MOVFW does not load the flags... */
2049 if (AOP_TYPE(oper) == AOP_ACC) {
2050 emitpcode(POC_IORLW, popGetLit(0));
2053 emitpcode(POC_MOVLW, popGetLit(0));
2057 if ( AOP_TYPE(oper) != AOP_ACC) {
2058 emitpcode(POC_MOVFW,popGet(AOP(oper),0));
2063 while (offset < size) {
2064 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
2066 /* Z is set iff (oper == 0) */
2070 /*-----------------------------------------------------------------*/
2071 /* genNot - generate code for ! operation */
2072 /*-----------------------------------------------------------------*/
2073 static void genNot (iCode *ic)
2080 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2081 /* assign asmOps to operand & result */
2082 aopOp (IC_LEFT(ic),ic,FALSE);
2083 aopOp (IC_RESULT(ic),ic,TRUE);
2085 DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2086 /* if in bit space then a special case */
2087 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2088 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2089 emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
2090 emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
2092 emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
2093 emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
2094 emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
2099 size = AOP_SIZE(IC_LEFT(ic));
2100 mov2w (AOP(IC_LEFT(ic)),0);
2103 if (op_isLitLike (IC_LEFT(ic)))
2104 emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
2106 emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
2108 emitpcode(POC_MOVLW, popGetLit (0));
2110 emitpcode(POC_MOVLW, popGetLit (1));
2111 movwf(AOP(IC_RESULT(ic)), 0);
2113 for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
2115 emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
2120 /* release the aops */
2121 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2122 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2126 /*-----------------------------------------------------------------*/
2127 /* genCpl - generate code for complement */
2128 /*-----------------------------------------------------------------*/
2129 static void genCpl (iCode *ic)
2131 operand *left, *result;
2136 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2137 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2138 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2140 /* if both are in bit space then
2142 if (AOP_TYPE(result) == AOP_CRY &&
2143 AOP_TYPE(left) == AOP_CRY ) {
2145 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir);
2146 pic14_emitcode("cpl","c");
2147 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir);
2151 size = AOP_SIZE(result);
2152 if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
2155 if(AOP_TYPE(left) == AOP_ACC)
2156 emitpcode(POC_XORLW, popGetLit(0xff));
2158 emitpcode(POC_COMFW,popGet(AOP(left),offset));
2160 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
2163 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2167 /* release the aops */
2168 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2169 freeAsmop(result,NULL,ic,TRUE);
2172 /*-----------------------------------------------------------------*/
2173 /* genUminusFloat - unary minus for floating points */
2174 /*-----------------------------------------------------------------*/
2175 static void genUminusFloat(operand *op,operand *result)
2177 int size ,offset =0 ;
2182 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2183 /* for this we just need to flip the
2184 first it then copy the rest in place */
2185 size = AOP_SIZE(op) - 1;
2186 l = aopGet(AOP(op),3,FALSE,FALSE);
2190 pic14_emitcode("cpl","acc.7");
2191 aopPut(AOP(result),"a",3);
2195 aopGet(AOP(op),offset,FALSE,FALSE),
2201 /*-----------------------------------------------------------------*/
2202 /* genUminus - unary minus code generation */
2203 /*-----------------------------------------------------------------*/
2204 static void genUminus (iCode *ic)
2207 sym_link *optype, *rtype;
2211 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2213 aopOp(IC_LEFT(ic),ic,FALSE);
2214 aopOp(IC_RESULT(ic),ic,TRUE);
2216 /* if both in bit space then special
2218 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2219 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2221 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0));
2222 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2223 emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0));
2228 optype = operandType(IC_LEFT(ic));
2229 rtype = operandType(IC_RESULT(ic));
2231 /* if float then do float stuff */
2232 if (IS_FLOAT(optype)) {
2233 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2237 /* otherwise subtract from zero by taking the 2's complement */
2238 size = AOP_SIZE(IC_LEFT(ic));
2240 for(i=0; i<size; i++) {
2241 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2242 emitpcode(POC_COMF, popGet(AOP(IC_LEFT(ic)),i));
2244 emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2245 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2249 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0));
2250 for(i=1; i<size; i++) {
2252 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),i));
2256 /* release the aops */
2257 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2258 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2261 /*-----------------------------------------------------------------*/
2262 /* saveRegisters - will look for a call and save the registers */
2263 /*-----------------------------------------------------------------*/
2264 static void saveRegisters(iCode *lic)
2273 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2275 for (ic = lic ; ic ; ic = ic->next)
2276 if (ic->op == CALL || ic->op == PCALL)
2280 fprintf(stderr,"found parameter push with no function call\n");
2284 /* if the registers have been saved already then
2286 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2289 /* find the registers in use at this time
2290 and push them away to safety */
2291 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2295 if (options.useXstack) {
2296 if (bitVectBitValue(rsave,R0_IDX))
2297 pic14_emitcode("mov","b,r0");
2298 pic14_emitcode("mov","r0,%s",spname);
2299 for (i = 0 ; i < pic14_nRegs ; i++) {
2300 if (bitVectBitValue(rsave,i)) {
2302 pic14_emitcode("mov","a,b");
2304 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2305 pic14_emitcode("movx","@r0,a");
2306 pic14_emitcode("inc","r0");
2309 pic14_emitcode("mov","%s,r0",spname);
2310 if (bitVectBitValue(rsave,R0_IDX))
2311 pic14_emitcode("mov","r0,b");
2313 //for (i = 0 ; i < pic14_nRegs ; i++) {
2314 // if (bitVectBitValue(rsave,i))
2315 // pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2318 dtype = operandType(IC_LEFT(ic));
2319 if (currFunc && dtype &&
2320 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2321 IFFUNC_ISISR(currFunc->type) &&
2324 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2327 /*-----------------------------------------------------------------*/
2328 /* unsaveRegisters - pop the pushed registers */
2329 /*-----------------------------------------------------------------*/
2330 static void unsaveRegisters (iCode *ic)
2337 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2338 /* find the registers in use at this time
2339 and push them away to safety */
2340 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2343 if (options.useXstack) {
2344 pic14_emitcode("mov","r0,%s",spname);
2345 for (i = pic14_nRegs ; i >= 0 ; i--) {
2346 if (bitVectBitValue(rsave,i)) {
2347 pic14_emitcode("dec","r0");
2348 pic14_emitcode("movx","a,@r0");
2350 pic14_emitcode("mov","b,a");
2352 pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2356 pic14_emitcode("mov","%s,r0",spname);
2357 if (bitVectBitValue(rsave,R0_IDX))
2358 pic14_emitcode("mov","r0,b");
2360 //for (i = pic14_nRegs ; i >= 0 ; i--) {
2361 // if (bitVectBitValue(rsave,i))
2362 // pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2368 /*-----------------------------------------------------------------*/
2370 /*-----------------------------------------------------------------*/
2371 static void pushSide(operand * oper, int size)
2375 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2377 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2378 if (AOP_TYPE(oper) != AOP_REG &&
2379 AOP_TYPE(oper) != AOP_DIR &&
2381 pic14_emitcode("mov","a,%s",l);
2382 pic14_emitcode("push","acc");
2384 pic14_emitcode("push","%s",l);
2389 /*-----------------------------------------------------------------*/
2390 /* assignResultValue - */
2391 /*-----------------------------------------------------------------*/
2392 static void assignResultValue(operand * oper)
2394 int size = AOP_SIZE(oper);
2399 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2401 DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2403 /* assign MSB first (passed via WREG) */
2405 get_returnvalue (oper, size, offset + GpsuedoStkPtr);
2411 /*-----------------------------------------------------------------*/
2412 /* genIpush - genrate code for pushing this gets a little complex */
2413 /*-----------------------------------------------------------------*/
2414 static void genIpush (iCode *ic)
2418 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2420 int size, offset = 0 ;
2424 /* if this is not a parm push : ie. it is spill push
2425 and spill push is always done on the local stack */
2426 if (!ic->parmPush) {
2428 /* and the item is spilt then do nothing */
2429 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2432 aopOp(IC_LEFT(ic),ic,FALSE);
2433 size = AOP_SIZE(IC_LEFT(ic));
2434 /* push it on the stack */
2436 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2441 pic14_emitcode("push","%s",l);
2446 /* this is a paramter push: in this case we call
2447 the routine to find the call and save those
2448 registers that need to be saved */
2451 /* then do the push */
2452 aopOp(IC_LEFT(ic),ic,FALSE);
2455 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2456 size = AOP_SIZE(IC_LEFT(ic));
2459 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2460 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
2461 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2463 pic14_emitcode("mov","a,%s",l);
2464 pic14_emitcode("push","acc");
2466 pic14_emitcode("push","%s",l);
2469 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2473 /*-----------------------------------------------------------------*/
2474 /* genIpop - recover the registers: can happen only for spilling */
2475 /*-----------------------------------------------------------------*/
2476 static void genIpop (iCode *ic)
2480 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2481 assert (!"genIpop -- unimplemented");
2486 /* if the temp was not pushed then */
2487 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2490 aopOp(IC_LEFT(ic),ic,FALSE);
2491 size = AOP_SIZE(IC_LEFT(ic));
2494 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2497 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2501 /*-----------------------------------------------------------------*/
2502 /* unsaverbank - restores the resgister bank from stack */
2503 /*-----------------------------------------------------------------*/
2504 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2508 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2514 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2516 if (options.useXstack) {
2518 r = getFreePtr(ic,&aop,FALSE);
2521 pic14_emitcode("mov","%s,_spx",r->name);
2522 pic14_emitcode("movx","a,@%s",r->name);
2523 pic14_emitcode("mov","psw,a");
2524 pic14_emitcode("dec","%s",r->name);
2527 pic14_emitcode ("pop","psw");
2530 for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2531 if (options.useXstack) {
2532 pic14_emitcode("movx","a,@%s",r->name);
2533 //pic14_emitcode("mov","(%s+%d),a",
2534 // regspic14[i].base,8*bank+regspic14[i].offset);
2535 pic14_emitcode("dec","%s",r->name);
2538 pic14_emitcode("pop",""); //"(%s+%d)",
2539 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2542 if (options.useXstack) {
2544 pic14_emitcode("mov","_spx,%s",r->name);
2545 freeAsmop(NULL,aop,ic,TRUE);
2551 /*-----------------------------------------------------------------*/
2552 /* saverbank - saves an entire register bank on the stack */
2553 /*-----------------------------------------------------------------*/
2554 static void saverbank (int bank, iCode *ic, bool pushPsw)
2558 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2564 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2565 if (options.useXstack) {
2568 r = getFreePtr(ic,&aop,FALSE);
2569 pic14_emitcode("mov","%s,_spx",r->name);
2573 for (i = 0 ; i < pic14_nRegs ;i++) {
2574 if (options.useXstack) {
2575 pic14_emitcode("inc","%s",r->name);
2576 //pic14_emitcode("mov","a,(%s+%d)",
2577 // regspic14[i].base,8*bank+regspic14[i].offset);
2578 pic14_emitcode("movx","@%s,a",r->name);
2580 pic14_emitcode("push","");// "(%s+%d)",
2581 //regspic14[i].base,8*bank+regspic14[i].offset);
2585 if (options.useXstack) {
2586 pic14_emitcode("mov","a,psw");
2587 pic14_emitcode("movx","@%s,a",r->name);
2588 pic14_emitcode("inc","%s",r->name);
2589 pic14_emitcode("mov","_spx,%s",r->name);
2590 freeAsmop (NULL,aop,ic,TRUE);
2593 pic14_emitcode("push","psw");
2595 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2601 /*-----------------------------------------------------------------*/
2602 /* genCall - generates a call statement */
2603 /*-----------------------------------------------------------------*/
2604 static void genCall (iCode *ic)
2613 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2615 /* if caller saves & we have not saved then */
2619 /* if we are calling a function that is not using
2620 the same register bank then we need to save the
2621 destination registers on the stack */
2622 dtype = operandType(IC_LEFT(ic));
2623 if (currFunc && dtype &&
2624 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2625 IFFUNC_ISISR(currFunc->type) &&
2628 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2630 /* if send set is not empty the assign */
2633 /* For the Pic port, there is no data stack.
2634 * So parameters passed to functions are stored
2635 * in registers. (The pCode optimizer will get
2636 * rid of most of these :).
2638 int psuedoStkPtr=-1;
2639 int firstTimeThruLoop = 1;
2641 _G.sendSet = reverseSet(_G.sendSet);
2643 /* First figure how many parameters are getting passed */
2644 for (sic = setFirstItem(_G.sendSet) ; sic ;
2645 sic = setNextItem(_G.sendSet)) {
2647 aopOp(IC_LEFT(sic),sic,FALSE);
2648 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2649 freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2652 for (sic = setFirstItem(_G.sendSet) ; sic ;
2653 sic = setNextItem(_G.sendSet)) {
2654 int size, offset = 0;
2656 aopOp(IC_LEFT(sic),sic,FALSE);
2657 size = AOP_SIZE(IC_LEFT(sic));
2660 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2661 AopType(AOP_TYPE(IC_LEFT(sic))));
2663 if(!firstTimeThruLoop) {
2664 /* If this is not the first time we've been through the loop
2665 * then we need to save the parameter in a temporary
2666 * register. The last byte of the last parameter is
2668 emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2671 firstTimeThruLoop=0;
2673 mov2w_op (IC_LEFT(sic), offset);
2676 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2681 sym = OP_SYMBOL(IC_LEFT(ic));
2682 name = sym->rname[0] ? sym->rname : sym->name;
2683 isExtern = IS_EXTERN(sym->etype);
2685 emitpcode(POC_PAGESEL,popGetWithString(name,1)); /* Extern functions maybe on another page - must call pagesel */
2687 emitpcode(POC_CALL,popGetWithString(name,isExtern));
2689 emitpcode(POC_PAGESEL,popGetWithString("$",0)); /* May have returned from another page - must call pagesel to restore PCLATH before next goto or call instruction */
2692 /* if we need assign a result value */
2693 if ((IS_ITEMP(IC_RESULT(ic)) &&
2694 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2695 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2696 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2699 aopOp(IC_RESULT(ic),ic,FALSE);
2702 assignResultValue(IC_RESULT(ic));
2704 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2705 AopType(AOP_TYPE(IC_RESULT(ic))));
2707 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2710 /* if register bank was saved then pop them */
2712 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2714 /* if we hade saved some registers then unsave them */
2715 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2716 unsaveRegisters (ic);
2721 /*-----------------------------------------------------------------*/
2722 /* genPcall - generates a call by pointer statement */
2723 /*-----------------------------------------------------------------*/
2724 static void genPcall (iCode *ic)
2727 symbol *albl = newiTempLabel(NULL);
2728 symbol *blbl = newiTempLabel(NULL);
2735 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2736 /* if caller saves & we have not saved then */
2740 /* if we are calling a function that is not using
2741 the same register bank then we need to save the
2742 destination registers on the stack */
2743 dtype = operandType(IC_LEFT(ic));
2744 if (currFunc && dtype &&
2745 IFFUNC_ISISR(currFunc->type) &&
2746 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2747 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2750 aopOp(left,ic,FALSE);
2751 DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2753 poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2755 pushSide(IC_LEFT(ic), FPTRSIZE);
2757 /* if send set is not empty, assign parameters */
2760 DEBUGpic14_emitcode ("; ***","%s %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2761 /* no way to pass args - W always gets used to make the call */
2763 /* first idea - factor out a common helper function and call it.
2764 But don't know how to get it generated only once in its own block
2766 if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2769 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2770 DEBUGpic14_emitcode ("; ***","%s %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2771 buffer = Safe_calloc(1,strlen(rname)+16);
2772 sprintf(buffer, "%s_goto_helper", rname);
2773 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2777 emitpcode(POC_CALL,popGetLabel(albl->key));
2778 pcop = popGetLabel(blbl->key);
2779 emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
2780 emitpcode(POC_GOTO,pcop);
2781 emitpLabel(albl->key);
2783 emitpcode(poc,popGetAddr(AOP(left),1,0));
2784 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2785 emitpcode(poc,popGetAddr(AOP(left),0,0));
2786 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2788 emitpLabel(blbl->key);
2790 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2792 /* if we need to assign a result value */
2793 if ((IS_ITEMP(IC_RESULT(ic)) &&
2794 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2795 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2796 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2799 aopOp(IC_RESULT(ic),ic,FALSE);
2804 assignResultValue(IC_RESULT(ic));
2806 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2809 /* if register bank was saved then unsave them */
2810 if (currFunc && dtype &&
2811 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2812 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2814 /* if we hade saved some registers then
2817 unsaveRegisters (ic);
2821 /*-----------------------------------------------------------------*/
2822 /* resultRemat - result is rematerializable */
2823 /*-----------------------------------------------------------------*/
2824 static int resultRemat (iCode *ic)
2826 // DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2829 if (SKIP_IC(ic) || ic->op == IFX)
2832 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2833 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2834 if (sym->remat && !POINTER_SET(ic))
2841 #if defined(__BORLANDC__) || defined(_MSC_VER)
2842 #define STRCASECMP stricmp
2844 #define STRCASECMP strcasecmp
2848 /*-----------------------------------------------------------------*/
2849 /* inExcludeList - return 1 if the string is in exclude Reg list */
2850 /*-----------------------------------------------------------------*/
2851 static bool inExcludeList(char *s)
2853 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2856 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2857 if (options.excludeRegs[i] &&
2858 STRCASECMP(options.excludeRegs[i],"none") == 0)
2861 for ( i = 0 ; options.excludeRegs[i]; i++) {
2862 if (options.excludeRegs[i] &&
2863 STRCASECMP(s,options.excludeRegs[i]) == 0)
2870 /*-----------------------------------------------------------------*/
2871 /* genFunction - generated code for function entry */
2872 /*-----------------------------------------------------------------*/
2873 static void genFunction (iCode *ic)
2880 DEBUGpic14_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2882 labelOffset += (max_key+4);
2886 /* create the function header */
2887 pic14_emitcode(";","-----------------------------------------");
2888 pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2889 pic14_emitcode(";","-----------------------------------------");
2891 pic14_emitcode("","%s:",sym->rname);
2892 addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2894 ftype = operandType(IC_LEFT(ic));
2896 /* if critical function then turn interrupts off */
2897 if (IFFUNC_ISCRITICAL(ftype))
2898 pic14_emitcode("clr","ea");
2900 /* here we need to generate the equates for the
2901 register bank if required */
2903 if (FUNC_REGBANK(ftype) != rbank) {
2906 rbank = FUNC_REGBANK(ftype);
2907 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2908 if (strcmp(regspic14[i].base,"0") == 0)
2909 pic14_emitcode("","%s = 0x%02x",
2911 8*rbank+regspic14[i].offset);
2913 pic14_emitcode ("","%s = %s + 0x%02x",
2916 8*rbank+regspic14[i].offset);
2921 /* if this is an interrupt service routine */
2922 if (IFFUNC_ISISR(sym->type)) {
2923 /* already done in pic14createInterruptVect() - delete me
2924 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2925 emitpcodeNULLop(POC_NOP);
2926 emitpcodeNULLop(POC_NOP);
2927 emitpcodeNULLop(POC_NOP);
2929 emitpcode(POC_MOVWF, popCopyReg(&pc_wsave));
2930 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2931 emitpcode(POC_CLRF, popCopyReg(&pc_status));
2932 emitpcode(POC_MOVWF, popCopyReg(&pc_ssave));
2933 emitpcode(POC_MOVFW, popCopyReg(&pc_pclath));
2934 emitpcode(POC_MOVWF, popCopyReg(&pc_psave));
2935 emitpcode(POC_CLRF, popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2937 pBlockConvert2ISR(pb);
2938 pic14_hasInterrupt = 1;
2940 if (!inExcludeList("acc"))
2941 pic14_emitcode ("push","acc");
2942 if (!inExcludeList("b"))
2943 pic14_emitcode ("push","b");
2944 if (!inExcludeList("dpl"))
2945 pic14_emitcode ("push","dpl");
2946 if (!inExcludeList("dph"))
2947 pic14_emitcode ("push","dph");
2948 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2950 pic14_emitcode ("push", "dpx");
2951 /* Make sure we're using standard DPTR */
2952 pic14_emitcode ("push", "dps");
2953 pic14_emitcode ("mov", "dps, #0x00");
2954 if (options.stack10bit)
2956 /* This ISR could conceivably use DPTR2. Better save it. */
2957 pic14_emitcode ("push", "dpl1");
2958 pic14_emitcode ("push", "dph1");
2959 pic14_emitcode ("push", "dpx1");
2962 /* if this isr has no bank i.e. is going to
2963 run with bank 0 , then we need to save more
2965 if (!FUNC_REGBANK(sym->type)) {
2967 /* if this function does not call any other
2968 function then we can be economical and
2969 save only those registers that are used */
2970 if (! IFFUNC_HASFCALL(sym->type)) {
2973 /* if any registers used */
2974 if (sym->regsUsed) {
2975 /* save the registers used */
2976 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2977 if (bitVectBitValue(sym->regsUsed,i) ||
2978 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2979 pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);
2984 /* this function has a function call cannot
2985 determines register usage so we will have the
2987 saverbank(0,ic,FALSE);
2992 /* if callee-save to be used for this function
2993 then save the registers being used in this function */
2994 if (IFFUNC_CALLEESAVES(sym->type)) {
2997 /* if any registers used */
2998 if (sym->regsUsed) {
2999 /* save the registers used */
3000 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3001 if (bitVectBitValue(sym->regsUsed,i) ||
3002 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
3003 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
3011 /* set the register bank to the desired value */
3012 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
3013 pic14_emitcode("push","psw");
3014 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);
3017 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3019 if (options.useXstack) {
3020 pic14_emitcode("mov","r0,%s",spname);
3021 pic14_emitcode("mov","a,_bp");
3022 pic14_emitcode("movx","@r0,a");
3023 pic14_emitcode("inc","%s",spname);
3027 /* set up the stack */
3028 pic14_emitcode ("push","_bp"); /* save the callers stack */
3030 pic14_emitcode ("mov","_bp,%s",spname);
3033 /* adjust the stack for the function */
3038 werror(W_STACK_OVERFLOW,sym->name);
3040 if (i > 3 && sym->recvSize < 4) {
3042 pic14_emitcode ("mov","a,sp");
3043 pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3044 pic14_emitcode ("mov","sp,a");
3049 pic14_emitcode("inc","sp");
3054 pic14_emitcode ("mov","a,_spx");
3055 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3056 pic14_emitcode ("mov","_spx,a");
3061 /*-----------------------------------------------------------------*/
3062 /* genEndFunction - generates epilogue for functions */
3063 /*-----------------------------------------------------------------*/
3064 static void genEndFunction (iCode *ic)
3066 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3070 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3072 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3074 pic14_emitcode ("mov","%s,_bp",spname);
3077 /* if use external stack but some variables were
3078 added to the local stack then decrement the
3080 if (options.useXstack && sym->stack) {
3081 pic14_emitcode("mov","a,sp");
3082 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3083 pic14_emitcode("mov","sp,a");
3087 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3088 if (options.useXstack) {
3089 pic14_emitcode("mov","r0,%s",spname);
3090 pic14_emitcode("movx","a,@r0");
3091 pic14_emitcode("mov","_bp,a");
3092 pic14_emitcode("dec","%s",spname);
3096 pic14_emitcode ("pop","_bp");
3100 /* restore the register bank */
3101 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3102 pic14_emitcode ("pop","psw");
3104 if (IFFUNC_ISISR(sym->type)) {
3106 /* now we need to restore the registers */
3107 /* if this isr has no bank i.e. is going to
3108 run with bank 0 , then we need to save more
3110 if (!FUNC_REGBANK(sym->type)) {
3112 /* if this function does not call any other
3113 function then we can be economical and
3114 save only those registers that are used */
3115 if (! IFFUNC_HASFCALL(sym->type)) {
3118 /* if any registers used */
3119 if (sym->regsUsed) {
3120 /* save the registers used */
3121 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3122 if (bitVectBitValue(sym->regsUsed,i) ||
3123 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3124 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3129 /* this function has a function call cannot
3130 determines register usage so we will have the
3132 unsaverbank(0,ic,FALSE);
3136 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3138 if (options.stack10bit)
3140 pic14_emitcode ("pop", "dpx1");
3141 pic14_emitcode ("pop", "dph1");
3142 pic14_emitcode ("pop", "dpl1");
3144 pic14_emitcode ("pop", "dps");
3145 pic14_emitcode ("pop", "dpx");
3147 if (!inExcludeList("dph"))
3148 pic14_emitcode ("pop","dph");
3149 if (!inExcludeList("dpl"))
3150 pic14_emitcode ("pop","dpl");
3151 if (!inExcludeList("b"))
3152 pic14_emitcode ("pop","b");
3153 if (!inExcludeList("acc"))
3154 pic14_emitcode ("pop","acc");
3156 if (IFFUNC_ISCRITICAL(sym->type))
3157 pic14_emitcode("setb","ea");
3160 /* if debug then send end of function */
3161 /* if (options.debug && currFunc) { */
3163 debugFile->writeEndFunction (currFunc, ic, 1);
3166 pic14_emitcode ("reti","");
3167 emitpcode(POC_MOVFW, popCopyReg(&pc_psave));
3168 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
3169 emitpcode(POC_CLRF, popCopyReg(&pc_status));
3170 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3171 emitpcode(POC_MOVWF, popCopyReg(&pc_status));
3172 emitpcode(POC_SWAPF, popCopyReg(&pc_wsave));
3173 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3174 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3175 emitpcodeNULLop(POC_RETFIE);
3178 if (IFFUNC_ISCRITICAL(sym->type))
3179 pic14_emitcode("setb","ea");
3181 if (IFFUNC_CALLEESAVES(sym->type)) {
3184 /* if any registers used */
3185 if (sym->regsUsed) {
3186 /* save the registers used */
3187 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3188 if (bitVectBitValue(sym->regsUsed,i) ||
3189 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3190 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3196 /* if debug then send end of function */
3198 debugFile->writeEndFunction (currFunc, ic, 1);
3201 pic14_emitcode ("return","");
3202 emitpcodeNULLop(POC_RETURN);
3204 /* Mark the end of a function */
3205 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3210 /*-----------------------------------------------------------------*/
3211 /* genRet - generate code for return statement */
3212 /*-----------------------------------------------------------------*/
3213 static void genRet (iCode *ic)
3215 int size,offset = 0;
3219 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3220 /* if we have no return value then
3221 just generate the "ret" */
3225 /* we have something to return then
3226 move the return value into place */
3227 aopOp(IC_LEFT(ic),ic,FALSE);
3228 size = AOP_SIZE(IC_LEFT(ic));
3230 for (offset = 0; offset < size; offset++)
3232 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
3235 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3238 /* generate a jump to the return label
3239 if the next is not the return statement */
3240 if (!(ic->next && ic->next->op == LABEL &&
3241 IC_LABEL(ic->next) == returnLabel)) {
3243 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3248 /*-----------------------------------------------------------------*/
3249 /* genLabel - generates a label */
3250 /*-----------------------------------------------------------------*/
3251 static void genLabel (iCode *ic)
3255 /* special case never generate */
3256 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3257 if (IC_LABEL(ic) == entryLabel)
3260 emitpLabel(IC_LABEL(ic)->key);
3261 pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3264 /*-----------------------------------------------------------------*/
3265 /* genGoto - generates a goto */
3266 /*-----------------------------------------------------------------*/
3268 static void genGoto (iCode *ic)
3272 emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3273 pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3277 /*-----------------------------------------------------------------*/
3278 /* genMultbits :- multiplication of bits */
3279 /*-----------------------------------------------------------------*/
3280 static void genMultbits (operand *left,
3285 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3287 if(!pic14_sameRegs(AOP(result),AOP(right)))
3288 emitpcode(POC_BSF, popGet(AOP(result),0));
3290 emitpcode(POC_BTFSC,popGet(AOP(right),0));
3291 emitpcode(POC_BTFSS,popGet(AOP(left),0));
3292 emitpcode(POC_BCF, popGet(AOP(result),0));
3297 /*-----------------------------------------------------------------*/
3298 /* genMultOneByte : 8 bit multiplication & division */
3299 /*-----------------------------------------------------------------*/
3300 static void genMultOneByte (operand *left,
3304 char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
3312 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3313 DEBUGpic14_AopType(__LINE__,left,right,result);
3314 DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3316 /* (if two literals, the value is computed before) */
3317 /* if one literal, literal on the right */
3318 if (AOP_TYPE(left) == AOP_LIT){
3324 assert (AOP_SIZE(left) == AOP_SIZE(right));
3326 size = min(AOP_SIZE(result),AOP_SIZE(left));
3327 offset = Gstack_base_addr - (2*size - 1);
3329 /* pass right operand as argument */
3330 for (i=0; i < size; i++)
3332 mov2w (AOP(right), i);
3333 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3336 /* pass left operand as argument */
3337 for (i=0; i < size; i++)
3339 mov2w (AOP(left), i);
3340 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3342 assert (offset == Gstack_base_addr);
3344 /* call library routine */
3345 assert (size > 0 && size <= 4);
3346 call_libraryfunc (func[size]);
3349 movwf (AOP(result), size-1);
3350 for (i=0; i < size - 1; i++)
3352 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
3353 movwf (AOP(result), size - 2 - i);
3356 /* now (zero-/sign) extend the result to its size */
3357 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
3360 /*-----------------------------------------------------------------*/
3361 /* genMult - generates code for multiplication */
3362 /*-----------------------------------------------------------------*/
3363 static void genMult (iCode *ic)
3365 operand *left = IC_LEFT(ic);
3366 operand *right = IC_RIGHT(ic);
3367 operand *result= IC_RESULT(ic);
3371 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3372 /* assign the amsops */
3373 aopOp (left,ic,FALSE);
3374 aopOp (right,ic,FALSE);
3375 aopOp (result,ic,TRUE);
3377 DEBUGpic14_AopType(__LINE__,left,right,result);
3379 /* special cases first */
3381 if (AOP_TYPE(left) == AOP_CRY &&
3382 AOP_TYPE(right)== AOP_CRY) {
3383 genMultbits(left,right,result);
3387 /* if both are of size == 1 */
3388 if (AOP_SIZE(left) == 1 &&
3389 AOP_SIZE(right) == 1 ) {
3390 genMultOneByte(left,right,result);
3394 /* should have been converted to function call */
3398 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3399 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3400 freeAsmop(result,NULL,ic,TRUE);
3403 /*-----------------------------------------------------------------*/
3404 /* genDivbits :- division of bits */
3405 /*-----------------------------------------------------------------*/
3406 static void genDivbits (operand *left,
3415 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3416 /* the result must be bit */
3417 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3418 l = aopGet(AOP(left),0,FALSE,FALSE);
3422 pic14_emitcode("div","ab");
3423 pic14_emitcode("rrc","a");
3424 aopPut(AOP(result),"c",0);
3427 /*-----------------------------------------------------------------*/
3428 /* genDivOneByte : 8 bit division */
3429 /*-----------------------------------------------------------------*/
3430 static void genDivOneByte (operand *left,
3437 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3439 assert (AOP_SIZE(result) == 1);
3440 assert (AOP_SIZE(right) == 1);
3441 assert (AOP_SIZE(left) == 1);
3443 size = min(AOP_SIZE(result),AOP_SIZE(left));
3445 if (AOP_TYPE(right) == AOP_LIT)
3447 /* XXX: might add specialized code */
3450 if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3452 /* unsigned division */
3454 mov2w(AOP(right),0);
3455 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3457 call_libraryfunc("__divuchar");
3458 movwf(AOP(result),0);
3463 temp = popGetTempReg();
3464 lbl = newiTempLabel(NULL);
3466 /* XXX: improve this naive approach:
3467 [result] = [a] / [b]
3468 ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
3472 movwf temp // temp <-- left
3473 movf right,W // W <-- right
3477 subwf temp,F // temp <-- temp - W
3478 skipNC // subwf clears CARRY (i.e. sets BORROW) if temp < W
3480 decf result // we just subtract once too often
3483 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3484 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
3487 emitpcode(POC_MOVWF, temp);
3488 mov2w(AOP(right),0);
3489 emitpcode(POC_CLRF, popGet(AOP(result),0));
3491 emitpLabel(lbl->key);
3492 emitpcode(POC_INCF, popGet(AOP(result),0));
3493 emitpcode(POC_SUBWF, temp);
3495 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3496 emitpcode(POC_DECF, popGet(AOP(result),0));
3501 /* signed division */
3502 mov2w(AOP(right),0);
3503 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3505 call_libraryfunc("__divschar");
3506 movwf(AOP(result),0);
3509 /* now performed the signed/unsigned division -- extend result */
3510 addSign(result, 1, !SPEC_USIGN(operandType(result)));
3513 /*-----------------------------------------------------------------*/
3514 /* genDiv - generates code for division */
3515 /*-----------------------------------------------------------------*/
3516 static void genDiv (iCode *ic)
3518 operand *left = IC_LEFT(ic);
3519 operand *right = IC_RIGHT(ic);
3520 operand *result= IC_RESULT(ic);
3523 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3524 /* assign the amsops */
3525 aopOp (left,ic,FALSE);
3526 aopOp (right,ic,FALSE);
3527 aopOp (result,ic,TRUE);
3529 /* special cases first */
3531 if (AOP_TYPE(left) == AOP_CRY &&
3532 AOP_TYPE(right)== AOP_CRY) {
3533 genDivbits(left,right,result);
3537 /* if both are of size == 1 */
3538 if (AOP_SIZE(left) == 1 &&
3539 AOP_SIZE(right) == 1 ) {
3540 genDivOneByte(left,right,result);
3544 /* should have been converted to function call */
3547 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3548 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3549 freeAsmop(result,NULL,ic,TRUE);
3552 /*-----------------------------------------------------------------*/
3553 /* genModbits :- modulus of bits */
3554 /*-----------------------------------------------------------------*/
3555 static void genModbits (operand *left,
3563 /* the result must be bit */
3564 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3565 l = aopGet(AOP(left),0,FALSE,FALSE);
3569 pic14_emitcode("div","ab");
3570 pic14_emitcode("mov","a,b");
3571 pic14_emitcode("rrc","a");
3572 aopPut(AOP(result),"c",0);
3575 /*-----------------------------------------------------------------*/
3576 /* genModOneByte : 8 bit modulus */
3577 /*-----------------------------------------------------------------*/
3578 static void genModOneByte (operand *left,
3585 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3587 assert (AOP_SIZE(result) == 1);
3588 assert (AOP_SIZE(right) == 1);
3589 assert (AOP_SIZE(left) == 1);
3591 size = min(AOP_SIZE(result),AOP_SIZE(left));
3593 if (AOP_TYPE(right) == AOP_LIT)
3595 /* XXX: might add specialized code */
3598 if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3600 /* unsigned division */
3602 mov2w(AOP(right),0);
3603 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3605 call_libraryfunc("__moduchar");
3606 movwf(AOP(result),0);
3611 lbl = newiTempLabel(NULL);
3613 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3615 /* XXX: improve this naive approach:
3616 [result] = [a] % [b]
3617 ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3621 movwf result // result <-- left
3622 movf right,W // W <-- right
3624 subwf result,F // result <-- result - W
3625 skipNC // subwf clears CARRY (i.e. sets BORROW) if result < W
3627 addwf result, F // we just subtract once too often
3630 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3631 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3633 if (!pic14_sameRegs(AOP(left), AOP(result)))
3636 emitpcode(POC_MOVWF, popGet(AOP(result),0));
3638 mov2w(AOP(right),0);
3640 emitpLabel(lbl->key);
3641 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3643 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3644 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3649 /* signed division */
3650 mov2w(AOP(right),0);
3651 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3653 call_libraryfunc("__modschar");
3654 movwf(AOP(result),0);
3657 /* now we performed the signed/unsigned modulus -- extend result */
3658 addSign(result, 1, !SPEC_USIGN(operandType(result)));
3661 /*-----------------------------------------------------------------*/
3662 /* genMod - generates code for division */
3663 /*-----------------------------------------------------------------*/
3664 static void genMod (iCode *ic)
3666 operand *left = IC_LEFT(ic);
3667 operand *right = IC_RIGHT(ic);
3668 operand *result= IC_RESULT(ic);
3671 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3672 /* assign the amsops */
3673 aopOp (left,ic,FALSE);
3674 aopOp (right,ic,FALSE);
3675 aopOp (result,ic,TRUE);
3677 /* special cases first */
3679 if (AOP_TYPE(left) == AOP_CRY &&
3680 AOP_TYPE(right)== AOP_CRY) {
3681 genModbits(left,right,result);
3685 /* if both are of size == 1 */
3686 if (AOP_SIZE(left) == 1 &&
3687 AOP_SIZE(right) == 1 ) {
3688 genModOneByte(left,right,result);
3692 /* should have been converted to function call */
3696 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3697 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3698 freeAsmop(result,NULL,ic,TRUE);
3701 /*-----------------------------------------------------------------*/
3702 /* genIfxJump :- will create a jump depending on the ifx */
3703 /*-----------------------------------------------------------------*/
3705 note: May need to add parameter to indicate when a variable is in bit space.
3707 static void genIfxJump (iCode *ic, char *jval)
3711 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3712 /* if true label then we jump if condition
3714 if ( IC_TRUE(ic) ) {
3716 if(strcmp(jval,"a") == 0)
3718 else if (strcmp(jval,"c") == 0)
3721 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3722 emitpcode(POC_BTFSC, newpCodeOpBit(jval,-1,1));
3725 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3726 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3730 /* false label is present */
3731 if(strcmp(jval,"a") == 0)
3733 else if (strcmp(jval,"c") == 0)
3736 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3737 emitpcode(POC_BTFSS, newpCodeOpBit(jval,-1,1));
3740 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3741 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3746 /* mark the icode as generated */
3751 /*-----------------------------------------------------------------*/
3753 /*-----------------------------------------------------------------*/
3754 static void genSkip(iCode *ifx,int status_bit)
3760 if ( IC_TRUE(ifx) ) {
3761 switch(status_bit) {
3776 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3777 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3781 switch(status_bit) {
3795 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3796 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3803 /*-----------------------------------------------------------------*/
3805 /*-----------------------------------------------------------------*/
3806 static void genSkipc(resolvedIfx *rifx)
3817 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3818 emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3819 rifx->generated = 1;
3823 /*-----------------------------------------------------------------*/
3825 /*-----------------------------------------------------------------*/
3826 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3832 if( (rifx->condition ^ invert_condition) & 1)
3837 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3838 rifx->generated = 1;
3843 /*-----------------------------------------------------------------*/
3845 /*-----------------------------------------------------------------*/
3846 static void genSkipz(iCode *ifx, int condition)
3849 assert (ifx != NULL);
3857 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3859 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3862 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3864 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3870 /*-----------------------------------------------------------------*/
3872 /*-----------------------------------------------------------------*/
3873 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3880 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3882 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3885 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3886 rifx->generated = 1;
3891 /*-----------------------------------------------------------------*/
3892 /* genChkZeroes :- greater or less than comparison */
3893 /* For each byte in a literal that is zero, inclusive or the */
3894 /* the corresponding byte in the operand with W */
3895 /* returns true if any of the bytes are zero */
3896 /*-----------------------------------------------------------------*/
3897 static int genChkZeroes(operand *op, int lit, int size)
3904 i = (lit >> (size*8)) & 0xff;
3908 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3910 emitpcode(POC_IORFW, popGet(AOP(op),size));
3920 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3921 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
3922 #define DEBUGpc emitpComment
3924 /*-----------------------------------------------------------------*/
3925 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
3926 /* aop (if it's NOT a literal) or from lit (if */
3927 /* aop is a literal) */
3928 /*-----------------------------------------------------------------*/
3929 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3930 if (aop->type == AOP_LIT) {
3931 emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3933 emitpcode (POC_MOVFW, popGet (aop, offset));
3937 /* genCmp performs a left < right comparison, stores
3938 * the outcome in result (if != NULL) and generates
3939 * control flow code for the ifx (if != NULL).
3941 * This version leaves in sequences like
3942 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3943 * which should be optmized by the peephole
3944 * optimizer - RN 2005-01-01 */
3945 static void genCmp (operand *left,operand *right,
3946 operand *result, iCode *ifx, int sign)
3956 int invert_result = 0;
3960 assert (AOP_SIZE(left) == AOP_SIZE(right));
3961 assert (left && right);
3963 size = AOP_SIZE(right) - 1;
3964 mask = (0x100UL << (size*8)) - 1;
3965 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3970 resolveIfx (&rIfx, ifx);
3972 /**********************************************************************
3973 * handle bits - bit compares are promoted to int compares seemingly! *
3974 **********************************************************************/
3976 // THIS IS COMPLETELY UNTESTED!
3977 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3978 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3979 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3980 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3983 // 1 < {0,1} is false --> clear C by skipping the next instruction
3984 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3985 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3986 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3987 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3988 emitCLRC; // only skipped for left=0 && right=1
3990 goto correct_result_in_carry;
3994 /*************************************************
3995 * make sure that left is register (or the like) *
3996 *************************************************/
3997 if (!isAOP_REGlike(left)) {
3998 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
3999 assert (isAOP_LIT(left));
4000 assert (isAOP_REGlike(right));
4001 // swap left and right
4002 // left < right <==> right > left <==> (right >= left + 1)
4003 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4005 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4006 // MAXVALUE < right? always false
4007 if (performedLt) emitCLRC; else emitSETC;
4008 goto correct_result_in_carry;
4011 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4012 // that's why we handled it above.
4019 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4020 } else if (isAOP_LIT(right)) {
4021 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4024 assert (isAOP_REGlike(left)); // left must be register or the like
4025 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4027 /*************************************************
4028 * special cases go here *
4029 *************************************************/
4031 if (isAOP_LIT(right)) {
4033 // unsigned comparison to a literal
4034 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4036 // unsigned left < 0? always false
4037 if (performedLt) emitCLRC; else emitSETC;
4038 goto correct_result_in_carry;
4041 // signed comparison to a literal
4042 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4043 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4044 // signed left < 0x80000000? always false
4045 if (performedLt) emitCLRC; else emitSETC;
4046 goto correct_result_in_carry;
4047 } else if (lit == 0) {
4048 // compare left < 0; set CARRY if SIGNBIT(left) is set
4049 if (performedLt) emitSETC; else emitCLRC;
4050 emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
4051 if (performedLt) emitCLRC; else emitSETC;
4052 goto correct_result_in_carry;
4055 } // right is literal
4057 /*************************************************
4058 * perform a general case comparison *
4059 * make sure we get CARRY==1 <==> left >= right *
4060 *************************************************/
4061 // compare most significant bytes
4062 //DEBUGpc ("comparing bytes at offset %d", size);
4064 // unsigned comparison
4065 pic14_mov2w_regOrLit (AOP(right), lit, size);
4066 emitpcode (POC_SUBFW, popGet (AOP(left), size));
4068 // signed comparison
4069 // (add 2^n to both operands then perform an unsigned comparison)
4070 if (isAOP_LIT(right)) {
4071 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4072 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4074 if (litbyte == 0x80) {
4075 // left >= 0x80 -- always true, but more bytes to come
4076 mov2w (AOP(left), size);
4077 emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
4080 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4081 mov2w (AOP(left), size);
4082 emitpcode (POC_ADDLW, popGetLit (0x80));
4083 emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4086 pCodeOp *pctemp = popGetTempReg();
4087 mov2w (AOP(left), size);
4088 emitpcode (POC_ADDLW, popGetLit (0x80));
4089 emitpcode (POC_MOVWF, pctemp);
4090 mov2w (AOP(right), size);
4091 emitpcode (POC_ADDLW, popGetLit (0x80));
4092 emitpcode (POC_SUBFW, pctemp);
4093 popReleaseTempReg(pctemp);
4097 // compare remaining bytes (treat as unsigned case from above)
4098 templbl = newiTempLabel ( NULL );
4101 //DEBUGpc ("comparing bytes at offset %d", offs);
4103 emitpcode (POC_GOTO, popGetLabel (templbl->key));
4104 pic14_mov2w_regOrLit (AOP(right), lit, offs);
4105 emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4107 emitpLabel (templbl->key);
4108 goto result_in_carry;
4112 /****************************************************
4113 * now CARRY contains the result of the comparison: *
4114 * SUBWF sets CARRY iff *
4115 * F-W >= 0 <==> F >= W <==> !(F < W) *
4116 * (F=left, W=right) *
4117 ****************************************************/
4121 // value will be used in the following genSkipc()
4122 rIfx.condition ^= 1;
4125 correct_result_in_carry:
4127 // assign result to variable (if neccessary)
4128 if (result && AOP_TYPE(result) != AOP_CRY) {
4129 //DEBUGpc ("assign result");
4130 size = AOP_SIZE(result);
4132 emitpcode (POC_CLRF, popGet (AOP(result), size));
4134 if (invert_result) {
4136 emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4138 emitpcode (POC_RLF, popGet (AOP(result), 0));
4142 // perform conditional jump
4144 //DEBUGpc ("generate control flow");
4152 /* OLD VERSION -- BUGGY, DO NOT USE */
4154 /*-----------------------------------------------------------------*/
4155 /* genCmp :- greater or less than comparison */
4156 /*-----------------------------------------------------------------*/
4157 static void genCmp (operand *left,operand *right,
4158 operand *result, iCode *ifx, int sign)
4160 int size; //, offset = 0 ;
4161 unsigned long lit = 0L,i = 0;
4162 resolvedIfx rFalseIfx;
4163 // resolvedIfx rTrueIfx;
4167 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4170 DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4171 DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4175 resolveIfx(&rFalseIfx,ifx);
4176 truelbl = newiTempLabel(NULL);
4177 size = max(AOP_SIZE(left),AOP_SIZE(right));
4179 DEBUGpic14_AopType(__LINE__,left,right,result);
4183 /* if literal is on the right then swap with left */
4184 if ((AOP_TYPE(right) == AOP_LIT)) {
4185 operand *tmp = right ;
4186 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4187 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4190 lit = (lit - 1) & mask;
4193 rFalseIfx.condition ^= 1;
4196 } else if ((AOP_TYPE(left) == AOP_LIT)) {
4197 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4201 //if(IC_TRUE(ifx) == NULL)
4202 /* if left & right are bit variables */
4203 if (AOP_TYPE(left) == AOP_CRY &&
4204 AOP_TYPE(right) == AOP_CRY ) {
4205 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4206 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4208 /* subtract right from left if at the
4209 end the carry flag is set then we know that
4210 left is greater than right */
4212 symbol *lbl = newiTempLabel(NULL);
4215 if(AOP_TYPE(right) == AOP_LIT) {
4217 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4219 DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4226 genSkipCond(&rFalseIfx,left,size-1,7);
4228 /* no need to compare to 0...*/
4229 /* NOTE: this is a de-generate compare that most certainly
4230 * creates some dead code. */
4231 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4233 if(ifx) ifx->generated = 1;
4240 //i = (lit >> (size*8)) & 0xff;
4241 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4243 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4245 i = ((0-lit) & 0xff);
4248 /* lit is 0x7f, all signed chars are less than
4249 * this except for 0x7f itself */
4250 emitpcode(POC_XORLW, popGetLit(0x7f));
4251 genSkipz2(&rFalseIfx,0);
4253 emitpcode(POC_ADDLW, popGetLit(0x80));
4254 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4255 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4260 genSkipz2(&rFalseIfx,1);
4262 emitpcode(POC_ADDLW, popGetLit(i));
4263 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4267 if(ifx) ifx->generated = 1;
4271 /* chars are out of the way. now do ints and longs */
4274 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4281 genSkipCond(&rFalseIfx,left,size,7);
4282 if(ifx) ifx->generated = 1;
4287 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4289 //rFalseIfx.condition ^= 1;
4290 //genSkipCond(&rFalseIfx,left,size,7);
4291 //rFalseIfx.condition ^= 1;
4293 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4294 if(rFalseIfx.condition)
4295 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4297 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4299 emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4300 emitpcode(POC_ADDFW, popGet(AOP(left),0));
4301 emitpcode(POC_MOVFW, popGet(AOP(left),1));
4304 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4306 if(rFalseIfx.condition) {
4308 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4314 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4315 emitpLabel(truelbl->key);
4316 if(ifx) ifx->generated = 1;
4323 if( (lit & 0xff) == 0) {
4324 /* lower byte is zero */
4325 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4326 i = ((lit >> 8) & 0xff) ^0x80;
4327 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4328 emitpcode(POC_ADDLW, popGetLit( 0x80));
4329 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4330 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4333 if(ifx) ifx->generated = 1;
4338 /* Special cases for signed longs */
4339 if( (lit & 0xffffff) == 0) {
4340 /* lower byte is zero */
4341 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4342 i = ((lit >> 8*3) & 0xff) ^0x80;
4343 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4344 emitpcode(POC_ADDLW, popGetLit( 0x80));
4345 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4346 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4349 if(ifx) ifx->generated = 1;
4357 if(lit & (0x80 << (size*8))) {
4358 /* lit is negative */
4359 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4361 //genSkipCond(&rFalseIfx,left,size,7);
4363 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4365 if(rFalseIfx.condition)
4366 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4368 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4372 /* lit is positive */
4373 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4374 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4375 if(rFalseIfx.condition)
4376 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4378 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4382 /* There are no more special cases, so perform a general compare */
4384 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4385 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4389 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4391 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4393 //rFalseIfx.condition ^= 1;
4394 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4396 emitpLabel(truelbl->key);
4398 if(ifx) ifx->generated = 1;
4405 /* sign is out of the way. So now do an unsigned compare */
4406 DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4409 /* General case - compare to an unsigned literal on the right.*/
4411 i = (lit >> (size*8)) & 0xff;
4412 emitpcode(POC_MOVLW, popGetLit(i));
4413 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4415 i = (lit >> (size*8)) & 0xff;
4418 emitpcode(POC_MOVLW, popGetLit(i));
4420 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4422 /* this byte of the lit is zero,
4423 *if it's not the last then OR in the variable */
4425 emitpcode(POC_IORFW, popGet(AOP(left),size));
4430 emitpLabel(lbl->key);
4431 //if(emitFinalCheck)
4432 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4434 emitpLabel(truelbl->key);
4436 if(ifx) ifx->generated = 1;
4443 if(AOP_TYPE(left) == AOP_LIT) {
4444 //symbol *lbl = newiTempLabel(NULL);
4446 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4449 DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4452 if((lit == 0) && (sign == 0)){
4455 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4457 emitpcode(POC_IORFW, popGet(AOP(right),--size));
4459 genSkipz2(&rFalseIfx,0);
4460 if(ifx) ifx->generated = 1;
4467 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4468 /* degenerate compare can never be true */
4469 if(rFalseIfx.condition == 0)
4470 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4472 if(ifx) ifx->generated = 1;
4477 /* signed comparisons to a literal byte */
4479 int lp1 = (lit+1) & 0xff;
4481 DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4484 rFalseIfx.condition ^= 1;
4485 genSkipCond(&rFalseIfx,right,0,7);
4488 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4489 emitpcode(POC_XORLW, popGetLit(0x7f));
4490 genSkipz2(&rFalseIfx,1);
4493 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4494 emitpcode(POC_ADDLW, popGetLit(0x80));
4495 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4496 rFalseIfx.condition ^= 1;
4497 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4500 if(ifx) ifx->generated = 1;
4502 /* unsigned comparisons to a literal byte */
4504 switch(lit & 0xff ) {
4506 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4507 genSkipz2(&rFalseIfx,0);
4508 if(ifx) ifx->generated = 1;
4511 genSkipCond(&rFalseIfx,right,0,7);
4512 if(ifx) ifx->generated = 1;
4516 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4517 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4518 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4519 rFalseIfx.condition ^= 1;
4520 if (AOP_TYPE(result) == AOP_CRY) {
4521 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4522 if(ifx) ifx->generated = 1;
4524 DEBUGpic14_emitcode ("; ***","%s %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4525 emitpcode(POC_CLRF, popGet(AOP(result),0));
4526 emitpcode(POC_RLF, popGet(AOP(result),0));
4527 emitpcode(POC_MOVLW, popGetLit(0x01));
4528 emitpcode(POC_XORWF, popGet(AOP(result),0));
4539 /* Size is greater than 1 */
4547 /* this means lit = 0xffffffff, or -1 */
4550 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4551 rFalseIfx.condition ^= 1;
4552 genSkipCond(&rFalseIfx,right,size,7);
4553 if(ifx) ifx->generated = 1;
4560 if(rFalseIfx.condition) {
4561 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4562 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4565 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4567 emitpcode(POC_IORFW, popGet(AOP(right),size));
4571 if(rFalseIfx.condition) {
4572 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4573 emitpLabel(truelbl->key);
4575 rFalseIfx.condition ^= 1;
4576 genSkipCond(&rFalseIfx,right,s,7);
4579 if(ifx) ifx->generated = 1;
4583 if((size == 1) && (0 == (lp1&0xff))) {
4584 /* lower byte of signed word is zero */
4585 DEBUGpic14_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
4586 i = ((lp1 >> 8) & 0xff) ^0x80;
4587 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4588 emitpcode(POC_ADDLW, popGetLit( 0x80));
4589 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4590 rFalseIfx.condition ^= 1;
4591 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4594 if(ifx) ifx->generated = 1;
4598 if(lit & (0x80 << (size*8))) {
4599 /* Lit is less than zero */
4600 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
4601 //rFalseIfx.condition ^= 1;
4602 //genSkipCond(&rFalseIfx,left,size,7);
4603 //rFalseIfx.condition ^= 1;
4604 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4605 //emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4607 if(rFalseIfx.condition)
4608 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4610 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4614 /* Lit is greater than or equal to zero */
4615 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
4616 //rFalseIfx.condition ^= 1;
4617 //genSkipCond(&rFalseIfx,right,size,7);
4618 //rFalseIfx.condition ^= 1;
4620 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4621 //emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4623 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4624 if(rFalseIfx.condition)
4625 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4627 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4632 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4633 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4637 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4639 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4641 rFalseIfx.condition ^= 1;
4642 //rFalseIfx.condition = 1;
4643 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4645 emitpLabel(truelbl->key);
4647 if(ifx) ifx->generated = 1;
4652 /* compare word or long to an unsigned literal on the right.*/
4657 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4660 break; /* handled above */
4663 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4665 emitpcode(POC_IORFW, popGet(AOP(right),size));
4666 genSkipz2(&rFalseIfx,0);
4670 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4672 emitpcode(POC_IORFW, popGet(AOP(right),size));
4675 if(rFalseIfx.condition)
4676 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4678 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4681 emitpcode(POC_MOVLW, popGetLit(lit+1));
4682 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4684 rFalseIfx.condition ^= 1;
4685 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4688 emitpLabel(truelbl->key);
4690 if(ifx) ifx->generated = 1;
4696 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4697 i = (lit >> (size*8)) & 0xff;
4699 emitpcode(POC_MOVLW, popGetLit(i));
4700 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4703 i = (lit >> (size*8)) & 0xff;
4706 emitpcode(POC_MOVLW, popGetLit(i));
4708 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4710 /* this byte of the lit is zero,
4711 *if it's not the last then OR in the variable */
4713 emitpcode(POC_IORFW, popGet(AOP(right),size));
4718 emitpLabel(lbl->key);
4720 rFalseIfx.condition ^= 1;
4721 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4725 emitpLabel(truelbl->key);
4726 if(ifx) ifx->generated = 1;
4730 /* Compare two variables */
4732 DEBUGpic14_emitcode(";sign","%d",sign);
4736 /* Sigh. thus sucks... */
4738 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4739 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4740 emitpcode(POC_MOVLW, popGetLit(0x80));
4741 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4742 emitpcode(POC_XORFW, popGet(AOP(right),size));
4743 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4745 /* Signed char comparison */
4746 /* Special thanks to Nikolai Golovchenko for this snippet */
4747 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4748 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4749 emitpcode(POC_RRFW, popGet(AOP(left),0)); /* could be any register */
4750 emitpcode(POC_XORFW, popGet(AOP(left),0));
4751 emitpcode(POC_XORFW, popGet(AOP(right),0));
4752 emitpcode(POC_ADDLW, popGetLit(0x80));
4754 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4755 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4757 if(ifx) ifx->generated = 1;
4763 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4764 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4768 /* The rest of the bytes of a multi-byte compare */
4772 emitpcode(POC_GOTO, popGetLabel(lbl->key));
4775 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4776 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4781 emitpLabel(lbl->key);
4783 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4784 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
4785 (AOP_TYPE(result) == AOP_REG)) {
4786 emitpcode(POC_CLRF, popGet(AOP(result),0));
4787 emitpcode(POC_RLF, popGet(AOP(result),0));
4789 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4791 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4792 if(ifx) ifx->generated = 1;
4799 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4800 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4801 pic14_outBitC(result);
4803 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4804 /* if the result is used in the next
4805 ifx conditional branch then generate
4806 code a little differently */
4808 genIfxJump (ifx,"c");
4810 pic14_outBitC(result);
4811 /* leave the result in acc */
4817 /*-----------------------------------------------------------------*/
4818 /* genCmpGt :- greater than comparison */
4819 /*-----------------------------------------------------------------*/
4820 static void genCmpGt (iCode *ic, iCode *ifx)
4822 operand *left, *right, *result;
4823 sym_link *letype , *retype;
4827 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4829 right= IC_RIGHT(ic);
4830 result = IC_RESULT(ic);
4832 letype = getSpec(operandType(left));
4833 retype =getSpec(operandType(right));
4834 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4835 /* assign the amsops */
4836 aopOp (left,ic,FALSE);
4837 aopOp (right,ic,FALSE);
4838 aopOp (result,ic,TRUE);
4840 genCmp(right, left, result, ifx, sign);
4842 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4843 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4844 freeAsmop(result,NULL,ic,TRUE);
4847 /*-----------------------------------------------------------------*/
4848 /* genCmpLt - less than comparisons */
4849 /*-----------------------------------------------------------------*/
4850 static void genCmpLt (iCode *ic, iCode *ifx)
4852 operand *left, *right, *result;
4853 sym_link *letype , *retype;
4857 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4859 right= IC_RIGHT(ic);
4860 result = IC_RESULT(ic);
4862 letype = getSpec(operandType(left));
4863 retype =getSpec(operandType(right));
4864 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4866 /* assign the amsops */
4867 aopOp (left,ic,FALSE);
4868 aopOp (right,ic,FALSE);
4869 aopOp (result,ic,TRUE);
4871 genCmp(left, right, result, ifx, sign);
4873 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4874 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4875 freeAsmop(result,NULL,ic,TRUE);
4879 /*-----------------------------------------------------------------*/
4880 /* genc16bit2lit - compare a 16 bit value to a literal */
4881 /*-----------------------------------------------------------------*/
4882 static void genc16bit2lit(operand *op, int lit, int offset)
4887 DEBUGpic14_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
4888 if( (lit&0xff) == 0)
4893 switch( BYTEofLONG(lit,i)) {
4895 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4898 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4901 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4904 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4905 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4910 switch( BYTEofLONG(lit,i)) {
4912 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4916 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4920 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4923 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4925 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4933 /*-----------------------------------------------------------------*/
4934 /* gencjneshort - compare and jump if not equal */
4935 /*-----------------------------------------------------------------*/
4936 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4938 int size = min(AOP_SIZE(left),AOP_SIZE(right));
4943 //unsigned long lit = 0L;
4945 if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4946 emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4949 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4950 DEBUGpic14_AopType(__LINE__,left,right,result);
4952 assert (!pic14_sameRegs (AOP(left), AOP(result)));
4953 assert (!pic14_sameRegs (AOP(right), AOP(result)));
4954 if (AOP_SIZE(result)) {
4955 for (offset = 0; offset < AOP_SIZE(result); offset++)
4956 emitpcode (POC_CLRF, popGet (AOP(result), offset));
4959 assert (AOP_SIZE(left) == AOP_SIZE(right));
4960 //resolveIfx(&rIfx,ifx);
4961 lbl = newiTempLabel (NULL);
4964 mov2w (AOP(right),size);
4965 emitpcode (POC_XORFW, popGet (AOP(left), size));
4969 emitpcode (POC_GOTO, popGetLabel (lbl->key));
4972 emitpLabel (lbl->key);
4973 if (AOP_SIZE(result)) {
4975 emitpcode (POC_INCF, popGet (AOP(result), 0));
4978 genSkipz (ifx, NULL != IC_TRUE(ifx));
4985 DEBUGpic14_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
4986 assert (!pic14_sameRegs (AOP(result), AOP(left)));
4987 assert (!pic14_sameRegs (AOP(result), AOP(right)));
4988 for (offset=0; offset < AOP_SIZE(result); offset++)
4990 emitpcode (POC_CLRF, popGet (AOP(result), offset));
4995 /* if the left side is a literal or
4996 if the right is in a pointer register and left
4998 if ((AOP_TYPE(left) == AOP_LIT) ||
4999 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5004 if(AOP_TYPE(right) == AOP_LIT)
5005 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5007 /* if the right side is a literal then anything goes */
5008 if (AOP_TYPE(right) == AOP_LIT &&
5009 AOP_TYPE(left) != AOP_DIR ) {
5012 genc16bit2lit(left, lit, 0);
5014 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5020 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5021 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5023 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5027 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5035 /* if the right side is in a register or in direct space or
5036 if the left is a pointer register & right is not */
5037 else if (AOP_TYPE(right) == AOP_REG ||
5038 AOP_TYPE(right) == AOP_DIR ||
5039 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5040 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5041 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5042 int lbl_key = lbl->key;
5045 DEBUGpic14_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
5046 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
5047 __FUNCTION__,__LINE__);
5051 /* switch(size) { */
5053 /* genc16bit2lit(left, lit, 0); */
5055 /* emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
5061 if((AOP_TYPE(left) == AOP_DIR) &&
5062 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5064 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5065 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5067 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5069 switch (lit & 0xff) {
5071 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5074 emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
5075 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5076 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5080 emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5081 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5082 //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5083 emitpcode(POC_GOTO,popGetLabel(lbl_key));
5087 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5088 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5093 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5096 if(AOP_TYPE(result) == AOP_CRY) {
5097 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5102 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5104 /* fix me. probably need to check result size too */
5105 //emitpcode(POC_CLRF,popGet(AOP(result),0));
5110 emitpcode(POC_GOTO,popGetLabel(lbl_key));
5120 } else if(AOP_TYPE(right) == AOP_REG &&
5121 AOP_TYPE(left) != AOP_DIR){
5125 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5126 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5127 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5132 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5137 /* right is a pointer reg need both a & b */
5140 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5142 pic14_emitcode("mov","b,%s",l);
5143 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5144 pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
5149 emitpcode(POC_INCF,popGet(AOP(result),0));
5151 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5153 emitpLabel(lbl->key);
5155 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5164 /*-----------------------------------------------------------------*/
5165 /* gencjne - compare and jump if not equal */
5166 /*-----------------------------------------------------------------*/
5167 static void gencjne(operand *left, operand *right, iCode *ifx)
5169 symbol *tlbl = newiTempLabel(NULL);
5171 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5172 gencjneshort(left, right, lbl);
5174 pic14_emitcode("mov","a,%s",one);
5175 pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5176 pic14_emitcode("","%05d_DS_:",lbl->key+100);
5177 pic14_emitcode("clr","a");
5178 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5180 emitpLabel(lbl->key);
5181 emitpLabel(tlbl->key);
5186 /*-----------------------------------------------------------------*/
5187 /* genCmpEq - generates code for equal to */
5188 /*-----------------------------------------------------------------*/
5189 static void genCmpEq (iCode *ic, iCode *ifx)
5191 operand *left, *right, *result;
5193 symbol *false_label;
5196 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5199 DEBUGpic14_emitcode ("; ifx is non-null","");
5201 DEBUGpic14_emitcode ("; ifx is null","");
5203 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5204 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5205 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5207 DEBUGpic14_AopType(__LINE__,left,right,result);
5209 /* if literal, move literal to right */
5210 if (op_isLitLike (IC_LEFT(ic))) {
5211 operand *tmp = right ;
5217 if (ifx && !IC_TRUE(ifx))
5219 assert (IC_FALSE(ifx));
5220 false_label = IC_FALSE(ifx);
5223 size = min(AOP_SIZE(left),AOP_SIZE(right));
5224 assert(!pic14_sameRegs(AOP(result),AOP(left)));
5225 assert(!pic14_sameRegs(AOP(result),AOP(right)));
5227 /* assume left != right */
5230 for (i=0; i < AOP_SIZE(result); i++)
5232 emitpcode(POC_CLRF, popGet(AOP(result),i));
5236 if (AOP_TYPE(right) == AOP_LIT)
5238 unsigned long lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
5240 size = AOP_SIZE(left);
5241 assert(!op_isLitLike(left));
5246 mov2w(AOP(left), 0);
5247 for (i=1; i < size; i++)
5248 emitpcode(POC_IORFW,popGet(AOP(left),i));
5249 /* now Z is set iff `left == right' */
5251 if (!false_label) false_label = newiTempLabel(NULL);
5252 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5256 for (i=0; i < size; i++)
5259 emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
5260 /* now Z is cleared if `left != right' */
5262 if (!false_label) false_label = newiTempLabel(NULL);
5263 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5270 /* right is no literal */
5273 for (i=0; i < size; i++)
5275 mov2w(AOP(right),i);
5276 emitpcode(POC_XORFW,popGet(AOP(left),i));
5277 /* now Z is cleared if `left != right' */
5279 if (!false_label) false_label = newiTempLabel(NULL);
5280 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5284 /* if we reach here, left == right */
5286 if (AOP_SIZE(result) > 0)
5288 emitpcode(POC_INCF, popGet(AOP(result),0));
5291 if (ifx && IC_TRUE(ifx))
5293 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5296 if (false_label && (!ifx || IC_TRUE(ifx)))
5297 emitpLabel(false_label->key);
5299 if (ifx) ifx->generated = 1;
5301 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5302 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5303 freeAsmop(result,NULL,ic,TRUE);
5306 /*-----------------------------------------------------------------*/
5307 /* ifxForOp - returns the icode containing the ifx for operand */
5308 /*-----------------------------------------------------------------*/
5309 static iCode *ifxForOp ( operand *op, iCode *ic )
5312 /* if true symbol then needs to be assigned */
5313 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5314 if (IS_TRUE_SYMOP(op))
5317 /* if this has register type condition and
5318 the next instruction is ifx with the same operand
5319 and live to of the operand is upto the ifx only then */
5321 ic->next->op == IFX &&
5322 IC_COND(ic->next)->key == op->key &&
5323 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5327 ic->next->op == IFX &&
5328 IC_COND(ic->next)->key == op->key) {
5329 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5333 DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5335 ic->next->op == IFX)
5336 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5339 ic->next->op == IFX &&
5340 IC_COND(ic->next)->key == op->key) {
5341 DEBUGpic14_emitcode ("; "," key is okay");
5342 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5343 OP_SYMBOL(op)->liveTo,
5350 /*-----------------------------------------------------------------*/
5351 /* genAndOp - for && operation */
5352 /*-----------------------------------------------------------------*/
5353 static void genAndOp (iCode *ic)
5355 operand *left,*right, *result;
5359 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5360 /* note here that && operations that are in an
5361 if statement are taken away by backPatchLabels
5362 only those used in arthmetic operations remain */
5363 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5364 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5365 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5367 DEBUGpic14_AopType(__LINE__,left,right,result);
5369 emitpcode(POC_MOVFW,popGet(AOP(left),0));
5370 emitpcode(POC_ANDFW,popGet(AOP(right),0));
5371 emitpcode(POC_MOVWF,popGet(AOP(result),0));
5373 /* if both are bit variables */
5374 /* if (AOP_TYPE(left) == AOP_CRY && */
5375 /* AOP_TYPE(right) == AOP_CRY ) { */
5376 /* pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5377 /* pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5378 /* pic14_outBitC(result); */
5380 /* tlbl = newiTempLabel(NULL); */
5381 /* pic14_toBoolean(left); */
5382 /* pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5383 /* pic14_toBoolean(right); */
5384 /* pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5385 /* pic14_outBitAcc(result); */
5388 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5389 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5390 freeAsmop(result,NULL,ic,TRUE);
5394 /*-----------------------------------------------------------------*/
5395 /* genOrOp - for || operation */
5396 /*-----------------------------------------------------------------*/
5399 modified this code, but it doesn't appear to ever get called
5402 static void genOrOp (iCode *ic)
5404 operand *left,*right, *result;
5408 /* note here that || operations that are in an
5409 if statement are taken away by backPatchLabels
5410 only those used in arthmetic operations remain */
5412 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5413 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5414 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5415 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5417 DEBUGpic14_AopType(__LINE__,left,right,result);
5419 for (i=0; i < AOP_SIZE(result); i++)
5421 emitpcode(POC_CLRF, popGet(AOP(result), i));
5424 tlbl = newiTempLabel(NULL);
5425 pic14_toBoolean(left);
5427 emitpcode(POC_GOTO, popGetLabel(tlbl->key));
5428 pic14_toBoolean(right);
5429 emitpLabel(tlbl->key);
5430 /* here Z is clear IFF `left || right' */
5432 emitpcode(POC_INCF, popGet(AOP(result), 0));
5434 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5435 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5436 freeAsmop(result,NULL,ic,TRUE);
5439 /*-----------------------------------------------------------------*/
5440 /* isLiteralBit - test if lit == 2^n */
5441 /*-----------------------------------------------------------------*/
5442 static int isLiteralBit(unsigned long lit)
5444 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5445 0x100L,0x200L,0x400L,0x800L,
5446 0x1000L,0x2000L,0x4000L,0x8000L,
5447 0x10000L,0x20000L,0x40000L,0x80000L,
5448 0x100000L,0x200000L,0x400000L,0x800000L,
5449 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5450 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5454 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5455 for(idx = 0; idx < 32; idx++)
5461 /*-----------------------------------------------------------------*/
5462 /* continueIfTrue - */
5463 /*-----------------------------------------------------------------*/
5464 static void continueIfTrue (iCode *ic)
5467 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5469 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5473 /*-----------------------------------------------------------------*/
5475 /*-----------------------------------------------------------------*/
5476 static void jumpIfTrue (iCode *ic)
5479 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5481 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5485 /*-----------------------------------------------------------------*/
5486 /* jmpTrueOrFalse - */
5487 /*-----------------------------------------------------------------*/
5488 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5491 // ugly but optimized by peephole
5492 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5494 symbol *nlbl = newiTempLabel(NULL);
5495 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5496 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5497 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5498 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5501 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5502 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5507 /*-----------------------------------------------------------------*/
5508 /* genAnd - code for and */
5509 /*-----------------------------------------------------------------*/
5510 static void genAnd (iCode *ic, iCode *ifx)
5512 operand *left, *right, *result;
5514 unsigned long lit = 0L;
5519 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5520 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5521 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5522 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5524 resolveIfx(&rIfx,ifx);
5526 /* if left is a literal & right is not then exchange them */
5527 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5528 AOP_NEEDSACC(left)) {
5529 operand *tmp = right ;
5534 /* if result = right then exchange them */
5535 if(pic14_sameRegs(AOP(result),AOP(right))){
5536 operand *tmp = right ;
5541 /* if right is bit then exchange them */
5542 if (AOP_TYPE(right) == AOP_CRY &&
5543 AOP_TYPE(left) != AOP_CRY){
5544 operand *tmp = right ;
5548 if(AOP_TYPE(right) == AOP_LIT)
5549 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5551 size = AOP_SIZE(result);
5553 DEBUGpic14_AopType(__LINE__,left,right,result);
5556 // result = bit & yy;
5557 if (AOP_TYPE(left) == AOP_CRY){
5558 // c = bit & literal;
5559 if(AOP_TYPE(right) == AOP_LIT){
5561 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5564 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5567 if(size && (AOP_TYPE(result) == AOP_CRY)){
5568 pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5571 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5575 pic14_emitcode("clr","c");
5578 if (AOP_TYPE(right) == AOP_CRY){
5580 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5581 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5584 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5586 pic14_emitcode("rrc","a");
5587 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5593 pic14_outBitC(result);
5595 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5596 genIfxJump(ifx, "c");
5600 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5601 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5602 if((AOP_TYPE(right) == AOP_LIT) &&
5603 (AOP_TYPE(result) == AOP_CRY) &&
5604 (AOP_TYPE(left) != AOP_CRY)){
5605 int posbit = isLiteralBit(lit);
5609 //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5612 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5617 while (posbit > 7) {
5621 emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5622 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5623 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5630 symbol *tlbl = newiTempLabel(NULL);
5631 int sizel = AOP_SIZE(left);
5633 pic14_emitcode("setb","c");
5635 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5636 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5638 if((posbit = isLiteralBit(bytelit)) != 0)
5639 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5641 if(bytelit != 0x0FFL)
5642 pic14_emitcode("anl","a,%s",
5643 aopGet(AOP(right),offset,FALSE,TRUE));
5644 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5649 // bit = left & literal
5651 pic14_emitcode("clr","c");
5652 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5654 // if(left & literal)
5657 jmpTrueOrFalse(ifx, tlbl);
5661 pic14_outBitC(result);
5665 /* if left is same as result */
5666 if(pic14_sameRegs(AOP(result),AOP(left))){
5668 for(;size--; offset++,lit>>=8) {
5669 if(AOP_TYPE(right) == AOP_LIT){
5670 switch(lit & 0xff) {
5672 /* and'ing with 0 has clears the result */
5673 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5676 /* and'ing with 0xff is a nop when the result and left are the same */
5681 int p = my_powof2( (~lit) & 0xff );
5683 /* only one bit is set in the literal, so use a bcf instruction */
5684 emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5687 if(know_W != (int)(lit&0xff))
5688 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5690 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5695 if (AOP_TYPE(left) == AOP_ACC) {
5696 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5698 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5699 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5706 // left & result in different registers
5707 if(AOP_TYPE(result) == AOP_CRY){
5709 // if(size), result in bit
5710 // if(!size && ifx), conditional oper: if(left & right)
5711 symbol *tlbl = newiTempLabel(NULL);
5712 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5714 pic14_emitcode("setb","c");
5716 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5717 pic14_emitcode("anl","a,%s",
5718 aopGet(AOP(left),offset,FALSE,FALSE));
5719 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5724 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5725 pic14_outBitC(result);
5727 jmpTrueOrFalse(ifx, tlbl);
5729 for(;(size--);offset++) {
5731 // result = left & right
5732 if(AOP_TYPE(right) == AOP_LIT){
5733 int t = (lit >> (offset*8)) & 0x0FFL;
5736 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5739 if(AOP_TYPE(left) != AOP_ACC) {
5740 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5742 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5745 if(AOP_TYPE(left) == AOP_ACC) {
5746 emitpcode(POC_ANDLW, popGetLit(t));
5748 emitpcode(POC_MOVLW, popGetLit(t));
5749 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5751 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5756 if (AOP_TYPE(left) == AOP_ACC) {
5757 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5759 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5760 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5762 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5768 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5769 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5770 freeAsmop(result,NULL,ic,TRUE);
5773 /*-----------------------------------------------------------------*/
5774 /* genOr - code for or */
5775 /*-----------------------------------------------------------------*/
5776 static void genOr (iCode *ic, iCode *ifx)
5778 operand *left, *right, *result;
5780 unsigned long lit = 0L;
5783 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5785 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5786 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5787 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5789 DEBUGpic14_AopType(__LINE__,left,right,result);
5791 /* if left is a literal & right is not then exchange them */
5792 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5793 AOP_NEEDSACC(left)) {
5794 operand *tmp = right ;
5799 /* if result = right then exchange them */
5800 if(pic14_sameRegs(AOP(result),AOP(right))){
5801 operand *tmp = right ;
5806 /* if right is bit then exchange them */
5807 if (AOP_TYPE(right) == AOP_CRY &&
5808 AOP_TYPE(left) != AOP_CRY){
5809 operand *tmp = right ;
5814 DEBUGpic14_AopType(__LINE__,left,right,result);
5816 if(AOP_TYPE(right) == AOP_LIT)
5817 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5819 size = AOP_SIZE(result);
5823 if (AOP_TYPE(left) == AOP_CRY){
5824 if(AOP_TYPE(right) == AOP_LIT){
5825 // c = bit & literal;
5827 // lit != 0 => result = 1
5828 if(AOP_TYPE(result) == AOP_CRY){
5830 emitpcode(POC_BSF, popGet(AOP(result),0));
5831 //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5832 // AOP(result)->aopu.aop_dir,
5833 // AOP(result)->aopu.aop_dir);
5835 continueIfTrue(ifx);
5839 // lit == 0 => result = left
5840 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5842 pic14_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5845 if (AOP_TYPE(right) == AOP_CRY){
5846 if(pic14_sameRegs(AOP(result),AOP(left))){
5848 emitpcode(POC_BCF, popGet(AOP(result),0));
5849 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5850 emitpcode(POC_BSF, popGet(AOP(result),0));
5852 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5853 AOP(result)->aopu.aop_dir,
5854 AOP(result)->aopu.aop_dir);
5855 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5856 AOP(right)->aopu.aop_dir,
5857 AOP(right)->aopu.aop_dir);
5858 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5859 AOP(result)->aopu.aop_dir,
5860 AOP(result)->aopu.aop_dir);
5862 if( AOP_TYPE(result) == AOP_ACC) {
5863 emitpcode(POC_MOVLW, popGetLit(0));
5864 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5865 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5866 emitpcode(POC_MOVLW, popGetLit(1));
5870 emitpcode(POC_BCF, popGet(AOP(result),0));
5871 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5872 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5873 emitpcode(POC_BSF, popGet(AOP(result),0));
5875 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5876 AOP(result)->aopu.aop_dir,
5877 AOP(result)->aopu.aop_dir);
5878 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5879 AOP(right)->aopu.aop_dir,
5880 AOP(right)->aopu.aop_dir);
5881 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5882 AOP(left)->aopu.aop_dir,
5883 AOP(left)->aopu.aop_dir);
5884 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5885 AOP(result)->aopu.aop_dir,
5886 AOP(result)->aopu.aop_dir);
5891 symbol *tlbl = newiTempLabel(NULL);
5892 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5895 emitpcode(POC_BCF, popGet(AOP(result),0));
5896 if( AOP_TYPE(right) == AOP_ACC) {
5897 emitpcode(POC_IORLW, popGetLit(0));
5899 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5900 emitpcode(POC_BSF, popGet(AOP(result),0));
5905 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5906 pic14_emitcode(";XXX setb","c");
5907 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5908 AOP(left)->aopu.aop_dir,tlbl->key+100);
5909 pic14_toBoolean(right);
5910 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5911 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5912 jmpTrueOrFalse(ifx, tlbl);
5916 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5923 pic14_outBitC(result);
5925 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5926 genIfxJump(ifx, "c");
5930 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5931 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5932 if((AOP_TYPE(right) == AOP_LIT) &&
5933 (AOP_TYPE(result) == AOP_CRY) &&
5934 (AOP_TYPE(left) != AOP_CRY)){
5936 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5939 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5941 continueIfTrue(ifx);
5944 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5945 // lit = 0, result = boolean(left)
5947 pic14_emitcode(";XXX setb","c");
5948 pic14_toBoolean(right);
5950 symbol *tlbl = newiTempLabel(NULL);
5951 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5953 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5955 genIfxJump (ifx,"a");
5959 pic14_outBitC(result);
5963 /* if left is same as result */
5964 if(pic14_sameRegs(AOP(result),AOP(left))){
5966 for(;size--; offset++,lit>>=8) {
5967 if(AOP_TYPE(right) == AOP_LIT){
5968 if((lit & 0xff) == 0)
5969 /* or'ing with 0 has no effect */
5972 int p = my_powof2(lit & 0xff);
5974 /* only one bit is set in the literal, so use a bsf instruction */
5976 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5978 if(know_W != (int)(lit & 0xff))
5979 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5980 know_W = lit & 0xff;
5981 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5986 if (AOP_TYPE(left) == AOP_ACC) {
5987 emitpcode(POC_IORFW, popGet(AOP(right),offset));
5988 pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5990 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
5991 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5993 pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5994 pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
6000 // left & result in different registers
6001 if(AOP_TYPE(result) == AOP_CRY){
6003 // if(size), result in bit
6004 // if(!size && ifx), conditional oper: if(left | right)
6005 symbol *tlbl = newiTempLabel(NULL);
6006 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6007 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6011 pic14_emitcode(";XXX setb","c");
6013 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6014 pic14_emitcode(";XXX orl","a,%s",
6015 aopGet(AOP(left),offset,FALSE,FALSE));
6016 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6021 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6022 pic14_outBitC(result);
6024 jmpTrueOrFalse(ifx, tlbl);
6025 } else for(;(size--);offset++){
6027 // result = left | right
6028 if(AOP_TYPE(right) == AOP_LIT){
6029 int t = (lit >> (offset*8)) & 0x0FFL;
6032 if (AOP_TYPE(left) != AOP_ACC) {
6033 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
6035 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6039 if (AOP_TYPE(left) == AOP_ACC) {
6040 emitpcode(POC_IORLW, popGetLit(t));
6042 emitpcode(POC_MOVLW, popGetLit(t));
6043 emitpcode(POC_IORFW, popGet(AOP(left),offset));
6045 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6050 // faster than result <- left, anl result,right
6051 // and better if result is SFR
6052 if (AOP_TYPE(left) == AOP_ACC) {
6053 emitpcode(POC_IORFW,popGet(AOP(right),offset));
6055 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6056 emitpcode(POC_IORFW,popGet(AOP(left),offset));
6058 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6063 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6064 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6065 freeAsmop(result,NULL,ic,TRUE);
6068 /*-----------------------------------------------------------------*/
6069 /* genXor - code for xclusive or */
6070 /*-----------------------------------------------------------------*/
6071 static void genXor (iCode *ic, iCode *ifx)
6073 operand *left, *right, *result;
6075 unsigned long lit = 0L;
6078 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6080 aopOp((left = IC_LEFT(ic)),ic,FALSE);
6081 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6082 aopOp((result=IC_RESULT(ic)),ic,TRUE);
6084 /* if left is a literal & right is not ||
6085 if left needs acc & right does not */
6086 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6087 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6088 operand *tmp = right ;
6093 /* if result = right then exchange them */
6094 if(pic14_sameRegs(AOP(result),AOP(right))){
6095 operand *tmp = right ;
6100 /* if right is bit then exchange them */
6101 if (AOP_TYPE(right) == AOP_CRY &&
6102 AOP_TYPE(left) != AOP_CRY){
6103 operand *tmp = right ;
6107 if(AOP_TYPE(right) == AOP_LIT)
6108 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6110 size = AOP_SIZE(result);
6114 if (AOP_TYPE(left) == AOP_CRY){
6115 if(AOP_TYPE(right) == AOP_LIT){
6116 // c = bit & literal;
6118 // lit>>1 != 0 => result = 1
6119 if(AOP_TYPE(result) == AOP_CRY){
6121 {emitpcode(POC_BSF, popGet(AOP(result),offset));
6122 pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6124 continueIfTrue(ifx);
6127 pic14_emitcode("setb","c");
6131 // lit == 0, result = left
6132 if(size && pic14_sameRegs(AOP(result),AOP(left)))
6134 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6136 // lit == 1, result = not(left)
6137 if(size && pic14_sameRegs(AOP(result),AOP(left))){
6138 emitpcode(POC_MOVLW, popGet(AOP(result),offset));
6139 emitpcode(POC_XORWF, popGet(AOP(result),offset));
6140 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6143 assert ( !"incomplete genXor" );
6144 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6145 pic14_emitcode("cpl","c");
6152 symbol *tlbl = newiTempLabel(NULL);
6153 if (AOP_TYPE(right) == AOP_CRY){
6155 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6158 int sizer = AOP_SIZE(right);
6160 // if val>>1 != 0, result = 1
6161 pic14_emitcode("setb","c");
6163 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6165 // test the msb of the lsb
6166 pic14_emitcode("anl","a,#0xfe");
6167 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6171 pic14_emitcode("rrc","a");
6173 pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6174 pic14_emitcode("cpl","c");
6175 pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6180 pic14_outBitC(result);
6182 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6183 genIfxJump(ifx, "c");
6187 if(pic14_sameRegs(AOP(result),AOP(left))){
6188 /* if left is same as result */
6189 for(;size--; offset++) {
6190 if(AOP_TYPE(right) == AOP_LIT){
6191 int t = (lit >> (offset*8)) & 0x0FFL;
6195 if (IS_AOP_PREG(left)) {
6196 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6197 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6198 aopPut(AOP(result),"a",offset);
6200 emitpcode(POC_MOVLW, popGetLit(t));
6201 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6202 pic14_emitcode("xrl","%s,%s",
6203 aopGet(AOP(left),offset,FALSE,TRUE),
6204 aopGet(AOP(right),offset,FALSE,FALSE));
6207 if (AOP_TYPE(left) == AOP_ACC)
6208 pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6210 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6211 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6213 if (IS_AOP_PREG(left)) {
6214 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6215 aopPut(AOP(result),"a",offset);
6217 pic14_emitcode("xrl","%s,a",
6218 aopGet(AOP(left),offset,FALSE,TRUE));
6224 // left & result in different registers
6225 if(AOP_TYPE(result) == AOP_CRY){
6227 // if(size), result in bit
6228 // if(!size && ifx), conditional oper: if(left ^ right)
6229 symbol *tlbl = newiTempLabel(NULL);
6230 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6232 pic14_emitcode("setb","c");
6234 if((AOP_TYPE(right) == AOP_LIT) &&
6235 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6236 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6238 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6239 pic14_emitcode("xrl","a,%s",
6240 aopGet(AOP(left),offset,FALSE,FALSE));
6242 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6247 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6248 pic14_outBitC(result);
6250 jmpTrueOrFalse(ifx, tlbl);
6251 } else for(;(size--);offset++){
6253 // result = left & right
6254 if(AOP_TYPE(right) == AOP_LIT){
6255 int t = (lit >> (offset*8)) & 0x0FFL;
6258 if (AOP_TYPE(left) != AOP_ACC) {
6259 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6261 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6262 pic14_emitcode("movf","%s,w",
6263 aopGet(AOP(left),offset,FALSE,FALSE));
6264 pic14_emitcode("movwf","%s",
6265 aopGet(AOP(result),offset,FALSE,FALSE));
6268 if (AOP_TYPE(left) == AOP_ACC) {
6269 emitpcode(POC_XORLW, popGetLit(t));
6271 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6273 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6276 if (AOP_TYPE(left) == AOP_ACC) {
6277 emitpcode(POC_XORLW, popGetLit(t));
6279 emitpcode(POC_MOVLW, popGetLit(t));
6280 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6282 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6283 pic14_emitcode("movlw","0x%x",t);
6284 pic14_emitcode("xorwf","%s,w",
6285 aopGet(AOP(left),offset,FALSE,FALSE));
6286 pic14_emitcode("movwf","%s",
6287 aopGet(AOP(result),offset,FALSE,FALSE));
6293 // faster than result <- left, anl result,right
6294 // and better if result is SFR
6295 if (AOP_TYPE(left) == AOP_ACC) {
6296 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6298 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6299 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6301 if ( AOP_TYPE(result) != AOP_ACC){
6302 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6308 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6309 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6310 freeAsmop(result,NULL,ic,TRUE);
6313 /*-----------------------------------------------------------------*/
6314 /* genInline - write the inline code out */
6315 /*-----------------------------------------------------------------*/
6316 static void genInline (iCode *ic)
6318 char *buffer, *bp, *bp1;
6321 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6323 _G.inLine += (!options.asmpeep);
6325 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6326 strcpy(buffer,IC_INLINE(ic));
6328 /* emit each line as a code */
6334 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6342 /* print label, use this special format with NULL directive
6343 * to denote that the argument should not be indented with tab */
6344 addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6351 if ((bp1 != bp) && *bp1)
6352 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6356 _G.inLine -= (!options.asmpeep);
6359 /*-----------------------------------------------------------------*/
6360 /* genRRC - rotate right with carry */
6361 /*-----------------------------------------------------------------*/
6362 static void genRRC (iCode *ic)
6364 operand *left , *result ;
6365 int size, offset = 0, same;
6368 /* rotate right with carry */
6370 result=IC_RESULT(ic);
6371 aopOp (left,ic,FALSE);
6372 aopOp (result,ic,FALSE);
6374 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6376 same = pic14_sameRegs(AOP(result),AOP(left));
6378 size = AOP_SIZE(result);
6380 /* get the lsb and put it into the carry */
6381 emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6388 emitpcode(POC_RRF, popGet(AOP(left),offset));
6390 emitpcode(POC_RRFW, popGet(AOP(left),offset));
6391 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6397 freeAsmop(left,NULL,ic,TRUE);
6398 freeAsmop(result,NULL,ic,TRUE);
6401 /*-----------------------------------------------------------------*/
6402 /* genRLC - generate code for rotate left with carry */
6403 /*-----------------------------------------------------------------*/
6404 static void genRLC (iCode *ic)
6406 operand *left , *result ;
6407 int size, offset = 0;
6411 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6412 /* rotate right with carry */
6414 result=IC_RESULT(ic);
6415 aopOp (left,ic,FALSE);
6416 aopOp (result,ic,FALSE);
6418 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6420 same = pic14_sameRegs(AOP(result),AOP(left));
6422 /* move it to the result */
6423 size = AOP_SIZE(result);
6425 /* get the msb and put it into the carry */
6426 emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6433 emitpcode(POC_RLF, popGet(AOP(left),offset));
6435 emitpcode(POC_RLFW, popGet(AOP(left),offset));
6436 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6443 freeAsmop(left,NULL,ic,TRUE);
6444 freeAsmop(result,NULL,ic,TRUE);
6447 /*-----------------------------------------------------------------*/
6448 /* genGetHbit - generates code get highest order bit */
6449 /*-----------------------------------------------------------------*/
6450 static void genGetHbit (iCode *ic)
6452 operand *left, *result;
6454 result=IC_RESULT(ic);
6455 aopOp (left,ic,FALSE);
6456 aopOp (result,ic,FALSE);
6459 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6460 /* get the highest order byte into a */
6461 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6462 if(AOP_TYPE(result) == AOP_CRY){
6463 pic14_emitcode("rlc","a");
6464 pic14_outBitC(result);
6467 pic14_emitcode("rl","a");
6468 pic14_emitcode("anl","a,#0x01");
6469 pic14_outAcc(result);
6473 freeAsmop(left,NULL,ic,TRUE);
6474 freeAsmop(result,NULL,ic,TRUE);
6477 /*-----------------------------------------------------------------*/
6478 /* AccLsh - shift left accumulator by known count */
6479 /* MARK: pic14 always rotates through CARRY! */
6480 /*-----------------------------------------------------------------*/
6481 static void AccLsh (pCodeOp *pcop,int shCount)
6484 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6485 shCount &= 0x0007; // shCount : 0..7
6492 emitpcode(POC_RLF,pcop);
6496 emitpcode(POC_RLF,pcop);
6497 emitpcode(POC_RLF,pcop);
6500 emitpcode(POC_RLF,pcop);
6501 emitpcode(POC_RLF,pcop);
6502 emitpcode(POC_RLF,pcop);
6505 emitpcode(POC_SWAPF,pcop);
6508 emitpcode(POC_SWAPF,pcop);
6509 emitpcode(POC_RLF,pcop);
6512 emitpcode(POC_SWAPF,pcop);
6513 emitpcode(POC_RLF,pcop);
6514 emitpcode(POC_RLF,pcop);
6517 emitpcode(POC_RRFW,pcop);
6518 emitpcode(POC_RRF,pcop);
6521 /* clear invalid bits */
6522 emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6523 emitpcode(POC_ANDWF, pcop);
6526 /*-----------------------------------------------------------------*/
6527 /* AccRsh - shift right accumulator by known count */
6528 /* MARK: pic14 always rotates through CARRY! */
6529 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6530 /* 1: mask out invalid bits (zero-extend) */
6531 /* 2: sign-extend result (pretty slow) */
6532 /*-----------------------------------------------------------------*/
6533 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6536 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6537 shCount &= 0x0007; // shCount : 0..7
6543 /* load sign if needed */
6544 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6545 else if (mask_mode == 1) emitCLRC;
6546 emitpcode(POC_RRF,pcop);
6550 /* load sign if needed */
6551 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6552 emitpcode(POC_RRF,pcop);
6553 /* load sign if needed */
6554 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6555 emitpcode(POC_RRF,pcop);
6556 if (mask_mode == 2) return;
6559 /* load sign if needed */
6560 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6561 emitpcode(POC_RRF,pcop);
6562 /* load sign if needed */
6563 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6564 emitpcode(POC_RRF,pcop);
6565 /* load sign if needed */
6566 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6567 emitpcode(POC_RRF,pcop);
6568 if (mask_mode == 2) return;
6571 emitpcode(POC_SWAPF,pcop);
6574 emitpcode(POC_SWAPF,pcop);
6575 emitpcode(POC_RRF,pcop);
6578 emitpcode(POC_SWAPF,pcop);
6579 emitpcode(POC_RRF,pcop);
6580 emitpcode(POC_RRF,pcop);
6586 emitpcode(POC_RLFW,pcop);
6587 emitpcode(POC_CLRF,pcop);
6589 emitpcode(POC_COMF,pcop);
6592 emitpcode(POC_RLFW,pcop);
6593 emitpcode(POC_RLF,pcop);
6600 /* leave invalid bits undefined */
6604 /* clear invalid bits -- zero-extend */
6605 emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6606 emitpcode(POC_ANDWF, pcop);
6608 if (mask_mode == 2) {
6610 emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6611 emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6612 emitpcode(POC_IORWF, pcop);
6617 /*-----------------------------------------------------------------*/
6618 /* AccSRsh - signed right shift accumulator by known count */
6619 /*-----------------------------------------------------------------*/
6620 static void AccSRsh (int shCount)
6623 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6626 pic14_emitcode("mov","c,acc.7");
6627 pic14_emitcode("rrc","a");
6628 } else if(shCount == 2){
6629 pic14_emitcode("mov","c,acc.7");
6630 pic14_emitcode("rrc","a");
6631 pic14_emitcode("mov","c,acc.7");
6632 pic14_emitcode("rrc","a");
6634 tlbl = newiTempLabel(NULL);
6635 /* rotate right accumulator */
6636 AccRol(8 - shCount);
6637 /* and kill the higher order bits */
6638 pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6639 pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6640 pic14_emitcode("orl","a,#0x%02x",
6641 (unsigned char)~SRMask[shCount]);
6642 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6647 /*-----------------------------------------------------------------*/
6648 /* shiftR1Left2Result - shift right one byte from left to result */
6649 /*-----------------------------------------------------------------*/
6650 static void shiftR1Left2ResultSigned (operand *left, int offl,
6651 operand *result, int offr,
6657 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6659 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6663 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6665 emitpcode(POC_RRF, popGet(AOP(result),offr));
6667 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6668 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6674 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6676 emitpcode(POC_RRF, popGet(AOP(result),offr));
6678 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6679 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6681 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6682 emitpcode(POC_RRF, popGet(AOP(result),offr));
6688 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6690 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6691 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6694 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6695 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6696 emitpcode(POC_ANDLW, popGetLit(0x1f));
6698 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6699 emitpcode(POC_IORLW, popGetLit(0xe0));
6701 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6705 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6706 emitpcode(POC_ANDLW, popGetLit(0x0f));
6707 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6708 emitpcode(POC_IORLW, popGetLit(0xf0));
6709 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6713 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6715 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6716 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6718 emitpcode(POC_RRFW, popGet(AOP(result),offr));
6719 emitpcode(POC_ANDLW, popGetLit(0x07));
6720 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6721 emitpcode(POC_IORLW, popGetLit(0xf8));
6722 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6727 emitpcode(POC_MOVLW, popGetLit(0x00));
6728 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6729 emitpcode(POC_MOVLW, popGetLit(0xfe));
6730 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6731 emitpcode(POC_IORLW, popGetLit(0x01));
6732 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6734 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6735 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6736 emitpcode(POC_DECF, popGet(AOP(result),offr));
6737 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6738 emitpcode(POC_BCF, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6744 emitpcode(POC_MOVLW, popGetLit(0x00));
6745 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6746 emitpcode(POC_MOVLW, popGetLit(0xff));
6747 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6749 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6750 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6751 emitpcode(POC_DECF, popGet(AOP(result),offr));
6759 /*-----------------------------------------------------------------*/
6760 /* shiftR1Left2Result - shift right one byte from left to result */
6761 /*-----------------------------------------------------------------*/
6762 static void shiftR1Left2Result (operand *left, int offl,
6763 operand *result, int offr,
6764 int shCount, int sign)
6769 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6771 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6773 /* Copy the msb into the carry if signed. */
6775 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6785 emitpcode(POC_RRF, popGet(AOP(result),offr));
6787 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6788 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6794 emitpcode(POC_RRF, popGet(AOP(result),offr));
6796 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6797 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6800 emitpcode(POC_RRF, popGet(AOP(result),offr));
6805 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6807 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6808 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6811 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6812 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6813 emitpcode(POC_ANDLW, popGetLit(0x1f));
6814 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6818 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6819 emitpcode(POC_ANDLW, popGetLit(0x0f));
6820 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6824 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6825 emitpcode(POC_ANDLW, popGetLit(0x0f));
6826 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6828 emitpcode(POC_RRF, popGet(AOP(result),offr));
6833 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6834 emitpcode(POC_ANDLW, popGetLit(0x80));
6835 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6836 emitpcode(POC_RLF, popGet(AOP(result),offr));
6837 emitpcode(POC_RLF, popGet(AOP(result),offr));
6842 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6843 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6844 emitpcode(POC_RLF, popGet(AOP(result),offr));
6853 /*-----------------------------------------------------------------*/
6854 /* shiftL1Left2Result - shift left one byte from left to result */
6855 /*-----------------------------------------------------------------*/
6856 static void shiftL1Left2Result (operand *left, int offl,
6857 operand *result, int offr, int shCount)
6863 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6865 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6866 DEBUGpic14_emitcode ("; ***","same = %d",same);
6867 // l = aopGet(AOP(left),offl,FALSE,FALSE);
6869 /* shift left accumulator */
6870 //AccLsh(shCount); // don't comment out just yet...
6871 // aopPut(AOP(result),"a",offr);
6875 /* Shift left 1 bit position */
6876 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6878 emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6880 emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6881 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6885 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6886 emitpcode(POC_ANDLW,popGetLit(0x7e));
6887 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6888 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6891 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6892 emitpcode(POC_ANDLW,popGetLit(0x3e));
6893 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6894 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6895 emitpcode(POC_RLF, popGet(AOP(result),offr));
6898 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6899 emitpcode(POC_ANDLW, popGetLit(0xf0));
6900 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6903 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6904 emitpcode(POC_ANDLW, popGetLit(0xf0));
6905 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6906 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6909 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6910 emitpcode(POC_ANDLW, popGetLit(0x30));
6911 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6912 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6913 emitpcode(POC_RLF, popGet(AOP(result),offr));
6916 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6917 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6918 emitpcode(POC_RRF, popGet(AOP(result),offr));
6922 DEBUGpic14_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6928 /*-----------------------------------------------------------------*/
6929 /* movLeft2Result - move byte from left to result */
6930 /*-----------------------------------------------------------------*/
6931 static void movLeft2Result (operand *left, int offl,
6932 operand *result, int offr)
6936 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6937 if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6938 l = aopGet(AOP(left),offl,FALSE,FALSE);
6940 if (*l == '@' && (IS_AOP_PREG(result))) {
6941 pic14_emitcode("mov","a,%s",l);
6942 aopPut(AOP(result),"a",offr);
6944 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6945 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6950 /*-----------------------------------------------------------------*/
6951 /* shiftLeft_Left2ResultLit - shift left by known count */
6952 /*-----------------------------------------------------------------*/
6954 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6956 int size, same, offr, i;
6958 size = AOP_SIZE(left);
6959 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6961 same = pic14_sameRegs (AOP(left), AOP(result));
6964 shCount = shCount & 0x07;
6970 case 0: /* takes 0 or 2N cycles (for offr==0) */
6971 if (!same || offr) {
6972 for (i=size-1; i >= 0; i--)
6973 movLeft2Result (left, i, result, offr + i);
6977 case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6979 shiftLeft_Left2ResultLit (left, result, 8 * offr);
6980 shiftLeft_Left2ResultLit (result, result, shCount);
6981 return; /* prevent clearing result again */
6984 for (i=0; i < size; i++) {
6985 if (same && !offr) {
6986 emitpcode (POC_RLF, popGet (AOP(left), i));
6988 emitpcode (POC_RLFW, popGet (AOP(left), i));
6989 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6995 case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
6996 /* works in-place/with offr as well */
6997 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
6998 emitpcode (POC_ANDLW, popGetLit (0xF0));
6999 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
7001 for (i = size - 2; i >= 0; i--)
7003 emitpcode (POC_SWAPFW, popGet (AOP(left), i));
7004 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7005 emitpcode (POC_ANDLW, popGetLit (0x0F));
7006 emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
7007 emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
7011 case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
7012 /* works in-place/with offr as well */
7013 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
7014 for (i = size-2; i >= 0; i--) {
7015 emitpcode (POC_RRFW, popGet (AOP(left), i));
7016 emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
7018 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7019 emitpcode (POC_RRF, popGet (AOP(result), offr));
7023 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
7024 shiftLeft_Left2ResultLit (result, result, 1);
7025 return; /* prevent clearing result again */
7031 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7035 /*-----------------------------------------------------------------*/
7036 /* shiftRight_Left2ResultLit - shift right by known count */
7037 /*-----------------------------------------------------------------*/
7039 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
7041 int size, same, offr, i;
7043 size = AOP_SIZE(left);
7044 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7046 same = pic14_sameRegs (AOP(left), AOP(result));
7049 shCount = shCount & 0x07;
7057 case 0: /* takes 0 or 2N cycles (for offr==0) */
7058 if (!same || offr) {
7059 for (i=0; i < size; i++)
7060 movLeft2Result (left, i + offr, result, i);
7064 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7065 emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7067 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7068 shiftRight_Left2ResultLit (result, result, shCount, sign);
7069 return; /* prevent sign-extending result again */
7073 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7076 for (i = size-1; i >= 0; i--) {
7077 if (same && !offr) {
7078 emitpcode (POC_RRF, popGet (AOP(left), i));
7080 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7081 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7087 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7088 /* works in-place/with offr as well */
7089 emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7090 emitpcode (POC_ANDLW, popGetLit (0x0F));
7091 emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7093 for (i = 1; i < size; i++)
7095 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7096 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7097 emitpcode (POC_ANDLW, popGetLit (0xF0));
7098 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7099 emitpcode (POC_XORWF, popGet (AOP(result), i));
7104 emitpcode (POC_MOVLW, popGetLit (0xF0));
7105 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7106 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7110 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7111 /* works in-place/with offr as well */
7112 emitpcode (POC_RLFW, popGet (AOP(left), offr));
7113 for (i = 0; i < size-1; i++) {
7114 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7115 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7117 emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7119 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7122 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7127 shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7128 shiftRight_Left2ResultLit (result, result, 1, sign);
7129 return; /* prevent sign extending result again */
7134 addSign (result, size, sign);
7138 /*-----------------------------------------------------------------*/
7139 /* shiftL2Left2Result - shift left two bytes from left to result */
7140 /*-----------------------------------------------------------------*/
7141 static void shiftL2Left2Result (operand *left, int offl,
7142 operand *result, int offr, int shCount)
7146 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7148 if(pic14_sameRegs(AOP(result), AOP(left))) {
7156 emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7157 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7158 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7162 emitpcode(POC_RLF, popGet(AOP(result),offr));
7163 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7169 emitpcode(POC_MOVLW, popGetLit(0x0f));
7170 emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7171 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7172 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7173 emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7174 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7175 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7177 emitpcode(POC_RLF, popGet(AOP(result),offr));
7178 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7182 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7183 emitpcode(POC_RRF, popGet(AOP(result),offr));
7184 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7185 emitpcode(POC_RRF, popGet(AOP(result),offr));
7186 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7187 emitpcode(POC_ANDLW,popGetLit(0xc0));
7188 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7189 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7190 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7191 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7194 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7195 emitpcode(POC_RRFW, popGet(AOP(result),offr));
7196 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7197 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7198 emitpcode(POC_RRF, popGet(AOP(result),offr));
7208 /* note, use a mov/add for the shift since the mov has a
7209 chance of getting optimized out */
7210 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7211 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7212 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7213 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7214 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7218 emitpcode(POC_RLF, popGet(AOP(result),offr));
7219 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7225 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7226 emitpcode(POC_ANDLW, popGetLit(0xF0));
7227 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7228 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7229 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7230 emitpcode(POC_ANDLW, popGetLit(0xF0));
7231 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7232 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7236 emitpcode(POC_RLF, popGet(AOP(result),offr));
7237 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7241 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7242 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7243 emitpcode(POC_RRFW, popGet(AOP(result),offl));
7244 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7246 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7247 emitpcode(POC_RRF, popGet(AOP(result),offr));
7248 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7249 emitpcode(POC_ANDLW,popGetLit(0xc0));
7250 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7251 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7252 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7253 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7256 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7257 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7258 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7259 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7260 emitpcode(POC_RRF, popGet(AOP(result),offr));
7266 /*-----------------------------------------------------------------*/
7267 /* shiftR2Left2Result - shift right two bytes from left to result */
7268 /*-----------------------------------------------------------------*/
7269 static void shiftR2Left2Result (operand *left, int offl,
7270 operand *result, int offr,
7271 int shCount, int sign)
7276 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7277 same = pic14_sameRegs(AOP(result), AOP(left));
7279 if(same && ((offl + MSB16) == offr)){
7281 /* don't crash result[offr] */
7282 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7283 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7286 movLeft2Result(left,offl, result, offr);
7287 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7290 /* a:x >> shCount (x = lsb(result))*/
7293 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7295 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7304 emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7309 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7310 emitpcode(POC_RRF,popGet(AOP(result),offr));
7312 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7313 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7314 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7315 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7320 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7323 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7324 emitpcode(POC_RRF,popGet(AOP(result),offr));
7331 emitpcode(POC_MOVLW, popGetLit(0xf0));
7332 emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7333 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7335 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7336 emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7337 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7338 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7340 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7341 emitpcode(POC_ANDLW, popGetLit(0x0f));
7342 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7344 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7345 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7346 emitpcode(POC_ANDLW, popGetLit(0xf0));
7347 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7348 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7352 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7353 emitpcode(POC_RRF, popGet(AOP(result),offr));
7357 emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7358 emitpcode(POC_BTFSC,
7359 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7360 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7368 emitpcode(POC_RLF, popGet(AOP(result),offr));
7369 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7371 emitpcode(POC_RLF, popGet(AOP(result),offr));
7372 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7373 emitpcode(POC_RLFW, popGet(AOP(result),offr));
7374 emitpcode(POC_ANDLW,popGetLit(0x03));
7376 emitpcode(POC_BTFSC,
7377 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7378 emitpcode(POC_IORLW,popGetLit(0xfc));
7380 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7381 emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7382 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7383 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7385 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7386 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7387 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7388 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7389 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7390 emitpcode(POC_RLF, popGet(AOP(result),offr));
7391 emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7392 emitpcode(POC_ANDLW,popGetLit(0x03));
7394 emitpcode(POC_BTFSC,
7395 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7396 emitpcode(POC_IORLW,popGetLit(0xfc));
7398 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7399 //emitpcode(POC_RLF, popGet(AOP(result),offr));
7406 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7407 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7408 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7409 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7412 emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7414 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7418 /*-----------------------------------------------------------------*/
7419 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7420 /*-----------------------------------------------------------------*/
7421 static void shiftLLeftOrResult (operand *left, int offl,
7422 operand *result, int offr, int shCount)
7425 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7427 /* shift left accumulator */
7428 AccLsh(left,offl,shCount);
7429 /* or with result */
7430 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7431 assert ( !"broken (modifies left, fails for left==result))" );
7434 /*-----------------------------------------------------------------*/
7435 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7436 /*-----------------------------------------------------------------*/
7437 static void shiftRLeftOrResult (operand *left, int offl,
7438 operand *result, int offr, int shCount)
7441 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7443 /* shift right accumulator */
7444 AccRsh(left,offl,shCount);
7445 /* or with result */
7446 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7447 assert ( !"broken (modifies left, fails for left==result))" );
7450 /*-----------------------------------------------------------------*/
7451 /* genlshOne - left shift a one byte quantity by known count */
7452 /*-----------------------------------------------------------------*/
7453 static void genlshOne (operand *result, operand *left, int shCount)
7456 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7457 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7460 /*-----------------------------------------------------------------*/
7461 /* genlshTwo - left shift two bytes by known amount != 0 */
7462 /*-----------------------------------------------------------------*/
7463 static void genlshTwo (operand *result,operand *left, int shCount)
7468 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7469 size = pic14_getDataSize(result);
7471 /* if shCount >= 8 */
7477 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7479 movLeft2Result(left, LSB, result, MSB16);
7481 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7484 /* 1 <= shCount <= 7 */
7487 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7489 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7493 /*-----------------------------------------------------------------*/
7494 /* shiftLLong - shift left one long from left to result */
7495 /* offl = LSB or MSB16 */
7496 /*-----------------------------------------------------------------*/
7497 static void shiftLLong (operand *left, operand *result, int offr )
7500 int size = AOP_SIZE(result);
7503 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7504 if(size >= LSB+offr){
7505 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7507 pic14_emitcode("add","a,acc");
7508 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7509 size >= MSB16+offr && offr != LSB )
7510 pic14_emitcode("xch","a,%s",
7511 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7513 aopPut(AOP(result),"a",LSB+offr);
7516 if(size >= MSB16+offr){
7517 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7518 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7521 pic14_emitcode("rlc","a");
7522 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7523 size >= MSB24+offr && offr != LSB)
7524 pic14_emitcode("xch","a,%s",
7525 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7527 aopPut(AOP(result),"a",MSB16+offr);
7530 if(size >= MSB24+offr){
7531 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7532 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7535 pic14_emitcode("rlc","a");
7536 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7537 size >= MSB32+offr && offr != LSB )
7538 pic14_emitcode("xch","a,%s",
7539 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7541 aopPut(AOP(result),"a",MSB24+offr);
7544 if(size > MSB32+offr){
7545 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7546 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7549 pic14_emitcode("rlc","a");
7550 aopPut(AOP(result),"a",MSB32+offr);
7553 aopPut(AOP(result),zero,LSB);
7556 /*-----------------------------------------------------------------*/
7557 /* genlshFour - shift four byte by a known amount != 0 */
7558 /*-----------------------------------------------------------------*/
7559 static void genlshFour (operand *result, operand *left, int shCount)
7564 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7565 size = AOP_SIZE(result);
7567 /* if shifting more that 3 bytes */
7568 if (shCount >= 24 ) {
7571 /* lowest order of left goes to the highest
7572 order of the destination */
7573 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7575 movLeft2Result(left, LSB, result, MSB32);
7576 aopPut(AOP(result),zero,LSB);
7577 aopPut(AOP(result),zero,MSB16);
7578 aopPut(AOP(result),zero,MSB32);
7582 /* more than two bytes */
7583 else if ( shCount >= 16 ) {
7584 /* lower order two bytes goes to higher order two bytes */
7586 /* if some more remaining */
7588 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7590 movLeft2Result(left, MSB16, result, MSB32);
7591 movLeft2Result(left, LSB, result, MSB24);
7593 aopPut(AOP(result),zero,MSB16);
7594 aopPut(AOP(result),zero,LSB);
7598 /* if more than 1 byte */
7599 else if ( shCount >= 8 ) {
7600 /* lower order three bytes goes to higher order three bytes */
7604 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7606 movLeft2Result(left, LSB, result, MSB16);
7608 else{ /* size = 4 */
7610 movLeft2Result(left, MSB24, result, MSB32);
7611 movLeft2Result(left, MSB16, result, MSB24);
7612 movLeft2Result(left, LSB, result, MSB16);
7613 aopPut(AOP(result),zero,LSB);
7615 else if(shCount == 1)
7616 shiftLLong(left, result, MSB16);
7618 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7619 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7620 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7621 aopPut(AOP(result),zero,LSB);
7626 /* 1 <= shCount <= 7 */
7627 else if(shCount <= 2){
7628 shiftLLong(left, result, LSB);
7630 shiftLLong(result, result, LSB);
7632 /* 3 <= shCount <= 7, optimize */
7634 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7635 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7636 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7642 /*-----------------------------------------------------------------*/
7643 /* genLeftShiftLiteral - left shifting by known count */
7644 /*-----------------------------------------------------------------*/
7645 static void genLeftShiftLiteral (operand *left,
7650 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7654 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7655 freeAsmop(right,NULL,ic,TRUE);
7657 aopOp(left,ic,FALSE);
7658 aopOp(result,ic,FALSE);
7660 size = getSize(operandType(result));
7663 pic14_emitcode("; shift left ","result %d, left %d",size,
7667 /* I suppose that the left size >= result size */
7670 movLeft2Result(left, size, result, size);
7674 else if(shCount >= (size * 8))
7676 aopPut(AOP(result),zero,size);
7680 genlshOne (result,left,shCount);
7685 genlshTwo (result,left,shCount);
7689 genlshFour (result,left,shCount);
7693 freeAsmop(left,NULL,ic,TRUE);
7694 freeAsmop(result,NULL,ic,TRUE);
7698 /*-----------------------------------------------------------------*
7699 * genMultiAsm - repeat assembly instruction for size of register.
7700 * if endian == 1, then the high byte (i.e base address + size of
7701 * register) is used first else the low byte is used first;
7702 *-----------------------------------------------------------------*/
7703 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7709 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7722 emitpcode(poc, popGet(AOP(reg),offset));
7729 /*-----------------------------------------------------------------*/
7730 /* genLeftShift - generates code for left shifting */
7731 /*-----------------------------------------------------------------*/
7732 static void genLeftShift (iCode *ic)
7734 operand *left,*right, *result;
7736 unsigned long lit = 0L;
7738 symbol *tlbl , *tlbl1;
7742 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7744 right = IC_RIGHT(ic);
7746 result = IC_RESULT(ic);
7748 aopOp(right,ic,FALSE);
7749 aopOp(left,ic,FALSE);
7750 aopOp(result,ic,FALSE);
7753 /* if the shift count is known then do it
7754 as efficiently as possible */
7755 if (AOP_TYPE(right) == AOP_LIT) {
7756 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7760 /* shift count is unknown then we have to form
7761 a loop get the loop count in B : Note: we take
7762 only the lower order byte since shifting
7763 more that 32 bits make no sense anyway, ( the
7764 largest size of an object can be only 32 bits ) */
7766 /* this code fails for RIGHT == RESULT */
7767 assert (!pic14_sameRegs (AOP(right), AOP(result)));
7769 /* now move the left to the result if they are not the
7771 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
7772 AOP_SIZE(result) > 1) {
7774 size = AOP_SIZE(result);
7777 l = aopGet(AOP(left),offset,FALSE,TRUE);
7778 if (*l == '@' && (IS_AOP_PREG(result))) {
7780 pic14_emitcode("mov","a,%s",l);
7781 aopPut(AOP(result),"a",offset);
7783 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
7784 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7785 //aopPut(AOP(result),l,offset);
7791 if(AOP_TYPE(left) == AOP_LIT)
7792 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7794 size = AOP_SIZE(result);
7796 /* if it is only one byte then */
7798 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7799 emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7800 emitpcode(POC_ANDLW, popGetLit(0xf0));
7801 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7802 emitpcode(POC_MOVFW, popGet(AOP(left),0));
7803 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7804 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7805 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7806 emitpcode(POC_RLFW, popGet(AOP(result),0));
7807 emitpcode(POC_ANDLW, popGetLit(0xfe));
7808 emitpcode(POC_ADDFW, popGet(AOP(result),0));
7809 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7810 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7813 tlbl = newiTempLabel(NULL);
7814 if (!pic14_sameRegs(AOP(left),AOP(result))) {
7815 mov2w (AOP(left), 0);
7816 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7819 emitpcode(POC_COMFW, popGet(AOP(right),0));
7820 emitpcode(POC_RRF, popGet(AOP(result),0));
7821 emitpLabel(tlbl->key);
7822 emitpcode(POC_RLF, popGet(AOP(result),0));
7823 emitpcode(POC_ADDLW, popGetLit(1));
7825 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7830 if (pic14_sameRegs(AOP(left),AOP(result))) {
7832 tlbl = newiTempLabel(NULL);
7833 emitpcode(POC_COMFW, popGet(AOP(right),0));
7834 genMultiAsm(POC_RRF, result, size,1);
7835 emitpLabel(tlbl->key);
7836 genMultiAsm(POC_RLF, result, size,0);
7837 emitpcode(POC_ADDLW, popGetLit(1));
7839 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7843 //tlbl = newiTempLabel(NULL);
7845 //tlbl1 = newiTempLabel(NULL);
7847 //reAdjustPreg(AOP(result));
7849 //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7850 //pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7851 //l = aopGet(AOP(result),offset,FALSE,FALSE);
7853 //pic14_emitcode("add","a,acc");
7854 //aopPut(AOP(result),"a",offset++);
7856 // l = aopGet(AOP(result),offset,FALSE,FALSE);
7858 // pic14_emitcode("rlc","a");
7859 // aopPut(AOP(result),"a",offset++);
7861 //reAdjustPreg(AOP(result));
7863 //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7864 //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7867 tlbl = newiTempLabel(NULL);
7868 tlbl1= newiTempLabel(NULL);
7870 size = AOP_SIZE(result);
7873 pctemp = popGetTempReg(); /* grab a temporary working register. */
7875 emitpcode(POC_MOVFW, popGet(AOP(right),0));
7877 /* offset should be 0, 1 or 3 */
7878 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7880 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
7882 emitpcode(POC_MOVWF, pctemp);
7885 emitpLabel(tlbl->key);
7888 emitpcode(POC_RLF, popGet(AOP(result),0));
7890 emitpcode(POC_RLF, popGet(AOP(result),offset++));
7892 emitpcode(POC_DECFSZ, pctemp);
7893 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7894 emitpLabel(tlbl1->key);
7896 popReleaseTempReg(pctemp);
7900 freeAsmop (right,NULL,ic,TRUE);
7901 freeAsmop(left,NULL,ic,TRUE);
7902 freeAsmop(result,NULL,ic,TRUE);
7907 /*-----------------------------------------------------------------*/
7908 /* genrshOne - right shift a one byte quantity by known count */
7909 /*-----------------------------------------------------------------*/
7910 static void genrshOne (operand *result, operand *left,
7911 int shCount, int sign)
7914 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7915 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7918 /*-----------------------------------------------------------------*/
7919 /* genrshTwo - right shift two bytes by known amount != 0 */
7920 /*-----------------------------------------------------------------*/
7921 static void genrshTwo (operand *result,operand *left,
7922 int shCount, int sign)
7925 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7926 /* if shCount >= 8 */
7930 shiftR1Left2Result(left, MSB16, result, LSB,
7933 movLeft2Result(left, MSB16, result, LSB);
7935 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7938 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7939 emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7943 /* 1 <= shCount <= 7 */
7945 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
7948 /*-----------------------------------------------------------------*/
7949 /* shiftRLong - shift right one long from left to result */
7950 /* offl = LSB or MSB16 */
7951 /*-----------------------------------------------------------------*/
7952 static void shiftRLong (operand *left, int offl,
7953 operand *result, int sign)
7958 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7960 size = AOP_SIZE(left);
7961 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7964 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7968 assert (offl >= 0 && offl < size);
7970 same = pic14_sameRegs (AOP(left), AOP(result));
7972 /* perform the shift */
7975 if (same && !offl) {
7976 emitpcode (POC_RRF, popGet (AOP(result), size));
7978 emitpcode (POC_RRFW, popGet (AOP(left), size));
7979 emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7983 addSign (result, AOP_SIZE(left) - offl, sign);
7986 /*-----------------------------------------------------------------*/
7987 /* genrshFour - shift four byte by a known amount != 0 */
7988 /*-----------------------------------------------------------------*/
7989 static void genrshFour (operand *result, operand *left,
7990 int shCount, int sign)
7993 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7994 /* if shifting more that 3 bytes */
7995 if(shCount >= 24 ) {
7998 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8000 movLeft2Result(left, MSB32, result, LSB);
8002 addSign(result, MSB16, sign);
8004 else if(shCount >= 16){
8007 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8009 movLeft2Result(left, MSB24, result, LSB);
8010 movLeft2Result(left, MSB32, result, MSB16);
8012 addSign(result, MSB24, sign);
8014 else if(shCount >= 8){
8017 shiftRLong(left, MSB16, result, sign);
8018 else if(shCount == 0){
8019 movLeft2Result(left, MSB16, result, LSB);
8020 movLeft2Result(left, MSB24, result, MSB16);
8021 movLeft2Result(left, MSB32, result, MSB24);
8022 addSign(result, MSB32, sign);
8025 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8026 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8027 /* the last shift is signed */
8028 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8029 addSign(result, MSB32, sign);
8032 else{ /* 1 <= shCount <= 7 */
8034 shiftRLong(left, LSB, result, sign);
8036 shiftRLong(result, LSB, result, sign);
8039 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8040 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8041 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8046 /*-----------------------------------------------------------------*/
8047 /* genRightShiftLiteral - right shifting by known count */
8048 /*-----------------------------------------------------------------*/
8049 static void genRightShiftLiteral (operand *left,
8055 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8059 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8060 freeAsmop(right,NULL,ic,TRUE);
8062 aopOp(left,ic,FALSE);
8063 aopOp(result,ic,FALSE);
8066 pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8070 lsize = pic14_getDataSize(left);
8071 res_size = pic14_getDataSize(result);
8072 /* test the LEFT size !!! */
8074 /* I suppose that the left size >= result size */
8077 movLeft2Result(left, res_size, result, res_size);
8080 else if(shCount >= (lsize * 8)){
8083 emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8085 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8086 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8091 emitpcode(POC_MOVLW, popGetLit(0));
8092 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8093 emitpcode(POC_MOVLW, popGetLit(0xff));
8095 emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8100 emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8107 genrshOne (result,left,shCount,sign);
8111 genrshTwo (result,left,shCount,sign);
8115 genrshFour (result,left,shCount,sign);
8123 freeAsmop(left,NULL,ic,TRUE);
8124 freeAsmop(result,NULL,ic,TRUE);
8129 /*-----------------------------------------------------------------*/
8130 /* genSignedRightShift - right shift of signed number */
8131 /*-----------------------------------------------------------------*/
8132 static void genSignedRightShift (iCode *ic)
8134 operand *right, *left, *result;
8137 symbol *tlbl, *tlbl1 ;
8140 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8142 /* we do it the hard way put the shift count in b
8143 and loop thru preserving the sign */
8145 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8147 right = IC_RIGHT(ic);
8149 result = IC_RESULT(ic);
8151 aopOp(right,ic,FALSE);
8152 aopOp(left,ic,FALSE);
8153 aopOp(result,ic,FALSE);
8156 if ( AOP_TYPE(right) == AOP_LIT) {
8157 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8158 //genRightShiftLiteral (left,right,result,ic,1);
8161 /* shift count is unknown then we have to form
8162 a loop get the loop count in B : Note: we take
8163 only the lower order byte since shifting
8164 more that 32 bits make no sense anyway, ( the
8165 largest size of an object can be only 32 bits ) */
8167 //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8168 //pic14_emitcode("inc","b");
8169 //freeAsmop (right,NULL,ic,TRUE);
8170 //aopOp(left,ic,FALSE);
8171 //aopOp(result,ic,FALSE);
8173 /* now move the left to the result if they are not the
8175 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
8176 AOP_SIZE(result) > 1) {
8178 size = AOP_SIZE(result);
8182 l = aopGet(AOP(left),offset,FALSE,TRUE);
8183 if (*l == '@' && IS_AOP_PREG(result)) {
8184 pic14_emitcode("mov","a,%s",l);
8185 aopPut(AOP(result),"a",offset);
8187 aopPut(AOP(result),l,offset);
8189 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8190 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8196 /* mov the highest order bit to OVR */
8197 tlbl = newiTempLabel(NULL);
8198 tlbl1= newiTempLabel(NULL);
8200 size = AOP_SIZE(result);
8203 pctemp = popGetTempReg(); /* grab a temporary working register. */
8205 emitpcode(POC_MOVFW, popGet(AOP(right),0));
8207 /* offset should be 0, 1 or 3 */
8208 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8210 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8212 emitpcode(POC_MOVWF, pctemp);
8215 emitpLabel(tlbl->key);
8217 emitpcode(POC_RLFW, popGet(AOP(result),offset));
8218 emitpcode(POC_RRF, popGet(AOP(result),offset));
8221 emitpcode(POC_RRF, popGet(AOP(result),--offset));
8224 emitpcode(POC_DECFSZ, pctemp);
8225 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8226 emitpLabel(tlbl1->key);
8228 popReleaseTempReg(pctemp);
8230 size = AOP_SIZE(result);
8232 pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8233 pic14_emitcode("rlc","a");
8234 pic14_emitcode("mov","ov,c");
8235 /* if it is only one byte then */
8237 l = aopGet(AOP(left),0,FALSE,FALSE);
8239 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8240 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8241 pic14_emitcode("mov","c,ov");
8242 pic14_emitcode("rrc","a");
8243 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8244 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8245 aopPut(AOP(result),"a",0);
8249 reAdjustPreg(AOP(result));
8250 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8251 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8252 pic14_emitcode("mov","c,ov");
8254 l = aopGet(AOP(result),offset,FALSE,FALSE);
8256 pic14_emitcode("rrc","a");
8257 aopPut(AOP(result),"a",offset--);
8259 reAdjustPreg(AOP(result));
8260 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8261 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8266 freeAsmop(left,NULL,ic,TRUE);
8267 freeAsmop(result,NULL,ic,TRUE);
8268 freeAsmop(right,NULL,ic,TRUE);
8272 /*-----------------------------------------------------------------*/
8273 /* loadSignToC - load the operand's sign bit into CARRY */
8274 /*-----------------------------------------------------------------*/
8276 static void loadSignToC (operand *op)
8279 assert (op && AOP(op) && AOP_SIZE(op));
8282 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8286 /*-----------------------------------------------------------------*/
8287 /* genRightShift - generate code for right shifting */
8288 /*-----------------------------------------------------------------*/
8289 static void genGenericShift (iCode *ic, int shiftRight)
8291 operand *right, *left, *result;
8294 symbol *tlbl, *tlbl1, *inverselbl;
8297 /* if signed then we do it the hard way preserve the
8298 sign bit moving it inwards */
8299 retype = getSpec(operandType(IC_RESULT(ic)));
8300 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8302 /* signed & unsigned types are treated the same : i.e. the
8303 signed is NOT propagated inwards : quoting from the
8304 ANSI - standard : "for E1 >> E2, is equivalent to division
8305 by 2**E2 if unsigned or if it has a non-negative value,
8306 otherwise the result is implementation defined ", MY definition
8307 is that the sign does not get propagated */
8309 right = IC_RIGHT(ic);
8311 result = IC_RESULT(ic);
8313 aopOp(right,ic,FALSE);
8314 aopOp(left,ic,FALSE);
8315 aopOp(result,ic,FALSE);
8317 /* if the shift count is known then do it
8318 as efficiently as possible */
8319 if (AOP_TYPE(right) == AOP_LIT) {
8320 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8324 shiftRight = !shiftRight;
8328 shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8330 shiftLeft_Left2ResultLit (left, result, lit);
8331 //genRightShiftLiteral (left,right,result,ic, 0);
8335 /* shift count is unknown then we have to form
8336 a loop get the loop count in B : Note: we take
8337 only the lower order byte since shifting
8338 more that 32 bits make no sense anyway, ( the
8339 largest size of an object can be only 32 bits ) */
8341 /* we must not overwrite the shift counter */
8342 assert (!pic14_sameRegs(AOP(right),AOP(result)));
8344 /* now move the left to the result if they are not the
8346 if (!pic14_sameRegs(AOP(left),AOP(result)))
8348 size = min(AOP_SIZE(result), AOP_SIZE(left));
8350 mov2w(AOP(left), size);
8351 movwf(AOP(result), size);
8353 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8356 tlbl = newiTempLabel(NULL);
8357 tlbl1= newiTempLabel(NULL);
8359 size = AOP_SIZE(result);
8361 mov2w(AOP(right),0);
8362 if (!SPEC_USIGN(operandType(right)))
8364 inverselbl = newiTempLabel(NULL);
8365 /* signed shift count -- invert shift direction for c<0 */
8366 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8367 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8369 emitpcode(POC_SUBLW, popGetLit(0)); /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8370 /* check for `a = b >> c' with `-c == 0' */
8372 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8373 emitpLabel(tlbl->key);
8374 /* propagate the sign bit inwards for SIGNED result */
8375 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8376 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8377 emitpcode(POC_ADDLW, popGetLit(1)); /* clears CARRY (unless W==0 afterwards) */
8379 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8381 if (!SPEC_USIGN(operandType(right)))
8383 symbol *inv_loop = newiTempLabel(NULL);
8385 shiftRight = !shiftRight; /* invert shift direction */
8387 /* we came here from the code above -- we are done */
8388 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8390 /* emit code for shifting N<0 steps, count is already in W */
8391 emitpLabel(inverselbl->key);
8392 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8393 emitpLabel(inv_loop->key);
8394 /* propagate the sign bit inwards for SIGNED result */
8395 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8396 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8397 emitpcode(POC_ADDLW, popGetLit(1));
8399 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8402 emitpLabel(tlbl1->key);
8404 freeAsmop(left,NULL,ic,TRUE);
8405 freeAsmop (right,NULL,ic,TRUE);
8406 freeAsmop(result,NULL,ic,TRUE);
8409 static void genRightShift (iCode *ic)
8411 genGenericShift(ic, 1);
8414 static void genLeftShift (iCode *ic)
8416 genGenericShift(ic, 0);
8419 /*-----------------------------------------------------------------*/
8420 /* SetIrp - Set IRP bit */
8421 /*-----------------------------------------------------------------*/
8422 void SetIrp(operand *result) {
8424 if (AOP_TYPE(result) == AOP_LIT) {
8425 unsigned lit = (unsigned)operandLitValue(result);
8431 if (PCOP(AOP(result))->type == PO_LITERAL) {
8432 int addrs = PCOL(AOP(result))->lit;
8438 emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8439 if(AOP_SIZE(result) > 1) {
8440 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8448 setup_fsr (operand *ptr)
8451 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8453 /* also setup-up IRP */
8457 /*-----------------------------------------------------------------*/
8458 /* emitPtrByteGet - emits code to get a byte into WREG from an */
8459 /* arbitrary pointer (__code, __data, generic) */
8460 /*-----------------------------------------------------------------*/
8462 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8469 if (!alreadyAddressed) setup_fsr (src);
8470 emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8474 assert( AOP_SIZE(src) == 2 );
8476 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8478 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8479 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
8480 call_libraryfunc ("__gptrget1");
8484 assert( AOP_SIZE(src) == 3 );
8486 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8488 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8490 call_libraryfunc ("__gptrget1");
8494 assert( !"unhandled pointer type" );
8499 /*-----------------------------------------------------------------*/
8500 /* emitPtrByteSet - emits code to set a byte from src through a */
8501 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR). */
8502 /*-----------------------------------------------------------------*/
8504 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8511 if (!alreadyAddressed) setup_fsr (dst);
8512 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8516 assert( !"trying to assign to __code pointer" );
8520 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8522 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8524 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8526 call_libraryfunc ("__gptrput1");
8530 assert( !"unhandled pointer type" );
8535 /*-----------------------------------------------------------------*/
8536 /* genUnpackBits - generates code for unpacking bits */
8537 /*-----------------------------------------------------------------*/
8538 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8540 int rsize; /* result size */
8541 sym_link *etype; /* bitfield type information */
8542 int blen; /* bitfield length */
8543 int bstr; /* bitfield starting bit within byte */
8546 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8547 etype = getSpec(operandType(result));
8548 rsize = getSize (operandType (result));
8549 blen = SPEC_BLEN (etype);
8550 bstr = SPEC_BSTR (etype);
8552 /* single bit field case */
8554 if (ifx) { /* that is for an if statement */
8557 resolveIfx(&rIfx,ifx);
8558 if (ptype == -1) /* direct */
8559 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8561 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8562 emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8563 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8567 assert (!pic14_sameRegs (AOP(result), AOP(left)));
8568 for (i=0; i < AOP_SIZE(result); i++)
8569 emitpcode (POC_CLRF, popGet (AOP(result), i));
8574 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8575 /* adjust result below */
8582 emitPtrByteGet (left, ptype, FALSE);
8583 emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8585 /* adjust result below */
8589 assert( !"unhandled pointer type" );
8592 /* move sign-/zero extended bit to result */
8593 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8594 emitpcode (POC_INCF, popGet (AOP(result), 0));
8596 emitpcode (POC_DECF, popGet (AOP(result), 0));
8598 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8602 else if (blen <= 8 && ((blen + bstr) <= 8))
8607 for (i=0; i < AOP_SIZE(result); i++)
8608 emitpcode (POC_CLRF, popGet (AOP(result), i));
8613 mov2w(AOP(left), 0);
8620 emitPtrByteGet (left, ptype, FALSE);
8624 assert( !"unhandled pointer type" );
8628 emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8629 movwf(AOP(result), 0);
8630 AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8632 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8634 /* signed bitfield */
8635 assert (bstr + blen > 0);
8636 emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8637 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8638 emitpcode(POC_IORWF, popGet(AOP(result),0));
8640 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8644 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8648 /*-----------------------------------------------------------------*/
8649 /* genDataPointerGet - generates code when ptr offset is known */
8650 /*-----------------------------------------------------------------*/
8651 static void genDataPointerGet (operand *left,
8655 int size , offset = 0;
8658 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8661 /* optimization - most of the time, left and result are the same
8662 * address, but different types. for the pic code, we could omit
8665 aopOp(result,ic,TRUE);
8667 if (pic14_sameRegs (AOP(left), AOP(result)))
8670 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8672 //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8674 size = AOP_SIZE(result);
8675 if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8679 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8680 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8684 freeAsmop(left,NULL,ic,TRUE);
8685 freeAsmop(result,NULL,ic,TRUE);
8689 /*-----------------------------------------------------------------*/
8690 /* genNearPointerGet - pic14_emitcode for near pointer fetch */
8691 /*-----------------------------------------------------------------*/
8692 static void genNearPointerGet (operand *left,
8697 sym_link *ltype = operandType(left);
8698 sym_link *rtype = operandType(result);
8699 sym_link *retype= getSpec(rtype); /* bitfield type information */
8703 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8706 aopOp(left,ic,FALSE);
8708 /* if left is rematerialisable and
8709 result is not bit variable type and
8710 the left is pointer to data space i.e
8711 lower 128 bytes of space */
8712 if (AOP_TYPE(left) == AOP_PCODE && //AOP_TYPE(left) == AOP_IMMD &&
8713 !IS_BITVAR(retype) &&
8714 PIC_IS_DATA_PTR(ltype)) {
8715 genDataPointerGet (left,result,ic);
8719 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8720 aopOp (result,ic,FALSE);
8722 /* Check if can access directly instead of via a pointer */
8723 if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8724 && AOP_SIZE(result) == 1)
8729 if (IS_BITFIELD(getSpec(operandType(result))))
8731 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8735 /* If the pointer value is not in a the FSR then need to put it in */
8736 /* Must set/reset IRP bit for use with FSR. */
8741 /* if bitfield then unpack the bits */
8743 /* we have can just get the values */
8744 int size = AOP_SIZE(result);
8747 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8751 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8753 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8754 if (AOP_TYPE(result) == AOP_LIT) {
8755 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8757 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8759 if (size && !direct)
8760 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8765 /* now some housekeeping stuff */
8767 /* we had to allocate for this iCode */
8768 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8769 freeAsmop(NULL,aop,ic,TRUE);
8771 /* we did not allocate which means left
8772 already in a pointer register, then
8773 if size > 0 && this could be used again
8774 we have to point it back to where it
8776 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8777 if (AOP_SIZE(result) > 1 &&
8778 !OP_SYMBOL(left)->remat &&
8779 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8781 int size = AOP_SIZE(result) - 1;
8783 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8789 freeAsmop(left,NULL,ic,TRUE);
8790 freeAsmop(result,NULL,ic,TRUE);
8795 /*-----------------------------------------------------------------*/
8796 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch */
8797 /*-----------------------------------------------------------------*/
8798 static void genPagedPointerGet (operand *left,
8805 sym_link *rtype, *retype;
8808 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8810 rtype = operandType(result);
8811 retype= getSpec(rtype);
8813 aopOp(left,ic,FALSE);
8815 /* if the value is already in a pointer register
8816 then don't need anything more */
8817 if (!AOP_INPREG(AOP(left))) {
8818 /* otherwise get a free pointer register */
8820 preg = getFreePtr(ic,&aop,FALSE);
8821 pic14_emitcode("mov","%s,%s",
8823 aopGet(AOP(left),0,FALSE,TRUE));
8824 rname = preg->name ;
8826 rname = aopGet(AOP(left),0,FALSE,FALSE);
8828 freeAsmop(left,NULL,ic,TRUE);
8829 aopOp (result,ic,FALSE);
8831 /* if bitfield then unpack the bits */
8832 if (IS_BITFIELD(retype))
8833 genUnpackBits (result,left,rname,PPOINTER,0);
8835 /* we have can just get the values */
8836 int size = AOP_SIZE(result);
8841 pic14_emitcode("movx","a,@%s",rname);
8842 aopPut(AOP(result),"a",offset);
8847 pic14_emitcode("inc","%s",rname);
8851 /* now some housekeeping stuff */
8853 /* we had to allocate for this iCode */
8854 freeAsmop(NULL,aop,ic,TRUE);
8856 /* we did not allocate which means left
8857 already in a pointer register, then
8858 if size > 0 && this could be used again
8859 we have to point it back to where it
8861 if (AOP_SIZE(result) > 1 &&
8862 !OP_SYMBOL(left)->remat &&
8863 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8865 int size = AOP_SIZE(result) - 1;
8867 pic14_emitcode("dec","%s",rname);
8872 freeAsmop(result,NULL,ic,TRUE);
8877 /*-----------------------------------------------------------------*/
8878 /* genFarPointerGet - gget value from far space */
8879 /*-----------------------------------------------------------------*/
8880 static void genFarPointerGet (operand *left,
8881 operand *result, iCode *ic)
8884 sym_link *retype = getSpec(operandType(result));
8887 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8889 aopOp(left,ic,FALSE);
8891 /* if the operand is already in dptr
8892 then we do nothing else we move the value to dptr */
8893 if (AOP_TYPE(left) != AOP_STR) {
8894 /* if this is remateriazable */
8895 if (AOP_TYPE(left) == AOP_IMMD)
8896 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8897 else { /* we need to get it byte by byte */
8898 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8899 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8900 if (options.model == MODEL_FLAT24)
8902 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8906 /* so dptr know contains the address */
8907 freeAsmop(left,NULL,ic,TRUE);
8908 aopOp(result,ic,FALSE);
8910 /* if bit then unpack */
8911 if (IS_BITFIELD(retype))
8912 genUnpackBits(result,left,"dptr",FPOINTER,0);
8914 size = AOP_SIZE(result);
8918 pic14_emitcode("movx","a,@dptr");
8919 aopPut(AOP(result),"a",offset++);
8921 pic14_emitcode("inc","dptr");
8925 freeAsmop(result,NULL,ic,TRUE);
8930 /*-----------------------------------------------------------------*/
8931 /* genCodePointerGet - get value from code space */
8932 /*-----------------------------------------------------------------*/
8933 static void genCodePointerGet (operand *left,
8934 operand *result, iCode *ic)
8937 sym_link *retype = getSpec(operandType(result));
8939 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8941 aopOp(left,ic,FALSE);
8943 /* if the operand is already in dptr
8944 then we do nothing else we move the value to dptr */
8945 if (AOP_TYPE(left) != AOP_STR) {
8946 /* if this is remateriazable */
8947 if (AOP_TYPE(left) == AOP_IMMD)
8948 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8949 else { /* we need to get it byte by byte */
8950 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8951 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8952 if (options.model == MODEL_FLAT24)
8954 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8958 /* so dptr know contains the address */
8959 freeAsmop(left,NULL,ic,TRUE);
8960 aopOp(result,ic,FALSE);
8962 /* if bit then unpack */
8963 if (IS_BITFIELD(retype))
8964 genUnpackBits(result,left,"dptr",CPOINTER,0);
8966 size = AOP_SIZE(result);
8970 pic14_emitcode("clr","a");
8971 pic14_emitcode("movc","a,@a+dptr");
8972 aopPut(AOP(result),"a",offset++);
8974 pic14_emitcode("inc","dptr");
8978 freeAsmop(result,NULL,ic,TRUE);
8981 /*-----------------------------------------------------------------*/
8982 /* genGenPointerGet - gget value from generic pointer space */
8983 /*-----------------------------------------------------------------*/
8984 static void genGenPointerGet (operand *left,
8985 operand *result, iCode *ic)
8988 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8989 aopOp(left,ic,FALSE);
8990 aopOp(result,ic,FALSE);
8993 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8995 if (IS_BITFIELD(getSpec(operandType(result))))
8997 genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
9002 /* emit call to __gptrget */
9003 char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
9004 int size = AOP_SIZE(result);
9007 assert (size > 0 && size <= 4);
9009 /* pass arguments */
9010 assert (AOP_SIZE(left) == 3);
9011 mov2w(AOP(left), 0);
9012 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9013 mov2w(AOP(left), 1);
9014 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9015 mov2w(AOP(left), 2);
9016 call_libraryfunc (func[size]);
9019 movwf (AOP(result), --size);
9021 emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
9022 movwf (AOP(result), size);
9026 freeAsmop(left,NULL,ic,TRUE);
9027 freeAsmop(result,NULL,ic,TRUE);
9031 /*-----------------------------------------------------------------*/
9032 /* genConstPointerGet - get value from const generic pointer space */
9033 /*-----------------------------------------------------------------*/
9034 static void genConstPointerGet (operand *left,
9035 operand *result, iCode *ic)
9037 //sym_link *retype = getSpec(operandType(result));
9039 symbol *albl, *blbl;//, *clbl;
9046 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9047 aopOp(left,ic,FALSE);
9048 aopOp(result,ic,FALSE);
9050 size = AOP_SIZE(result);
9052 DEBUGpic14_AopType(__LINE__,left,NULL,result);
9054 DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
9056 lit = op_isLitLike (left);
9057 poc = lit ? POC_MOVLW : POC_MOVFW;
9059 if (IS_BITFIELD(getSpec(operandType(result))))
9061 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
9066 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
9067 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
9068 assert (size > 0 && size <= 4);
9071 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9073 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9074 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
9075 call_libraryfunc (func[size]);
9077 movwf(AOP(result),size-1);
9078 for (i = 1; i < size; i++)
9080 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
9081 movwf(AOP(result),size - 1 - i);
9086 freeAsmop(left,NULL,ic,TRUE);
9087 freeAsmop(result,NULL,ic,TRUE);
9090 /*-----------------------------------------------------------------*/
9091 /* genPointerGet - generate code for pointer get */
9092 /*-----------------------------------------------------------------*/
9093 static void genPointerGet (iCode *ic)
9095 operand *left, *result ;
9096 sym_link *type, *etype;
9100 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9103 result = IC_RESULT(ic) ;
9105 /* depending on the type of pointer we need to
9106 move it to the correct pointer register */
9107 type = operandType(left);
9108 etype = getSpec(type);
9110 if (IS_PTR_CONST(type))
9111 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9113 /* if left is of type of pointer then it is simple */
9114 if (IS_PTR(type) && !IS_FUNC(type->next))
9115 p_type = DCL_TYPE(type);
9117 /* we have to go by the storage class */
9118 p_type = PTR_TYPE(SPEC_OCLS(etype));
9120 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9122 if (SPEC_OCLS(etype)->codesp ) {
9123 DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9124 //p_type = CPOINTER ;
9127 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9128 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9129 /*p_type = FPOINTER ;*/
9131 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9132 DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9133 /* p_type = PPOINTER; */
9135 if (SPEC_OCLS(etype) == idata )
9136 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9137 /* p_type = IPOINTER; */
9139 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9140 /* p_type = POINTER ; */
9143 /* now that we have the pointer type we assign
9144 the pointer values */
9150 genNearPointerGet (left,result,ic);
9154 genPagedPointerGet(left,result,ic);
9158 genFarPointerGet (left,result,ic);
9162 genConstPointerGet (left,result,ic);
9166 genGenPointerGet (left,result,ic);
9169 assert ( !"unhandled pointer type" );
9175 /*-----------------------------------------------------------------*/
9176 /* genPackBits - generates code for packed bit storage */
9177 /*-----------------------------------------------------------------*/
9178 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9180 int blen; /* bitfield length */
9181 int bstr; /* bitfield starting bit within byte */
9182 int litval; /* source literal value (if AOP_LIT) */
9183 unsigned char mask; /* bitmask within current byte */
9186 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9188 blen = SPEC_BLEN (etype);
9189 bstr = SPEC_BSTR (etype);
9191 /* If the bitfield length is less than a byte and does not cross byte boundaries */
9192 if ((blen <= 8) && ((bstr + blen) <= 8))
9194 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9195 (unsigned char) (0xFF >> (8 - bstr)));
9197 if (AOP_TYPE (right) == AOP_LIT)
9199 /* Case with a bitfield length <8 and literal source */
9200 int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9207 if (AOP(result)->type == AOP_PCODE)
9208 pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9210 pcop = popGet(AOP(result),0);
9211 emitpcode(lit?POC_BSF:POC_BCF,pcop);
9217 emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9221 assert( !"trying to assign to bitfield via pointer to __code space" );
9225 emitPtrByteGet(result, p_type, FALSE);
9227 emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9229 emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9231 emitPtrByteSet(result, p_type, TRUE);
9235 assert( !"unhandled pointer type" );
9237 } // switch (p_type)
9240 litval = lit << bstr;
9241 litval &= (~mask) & 0x00ff;
9246 mov2w (AOP(result), 0);
9247 if ((litval|mask) != 0x00ff)
9248 emitpcode(POC_ANDLW, popGetLit (mask));
9250 emitpcode(POC_IORLW, popGetLit (litval));
9251 movwf (AOP(result), 0);
9257 emitPtrByteGet(result, p_type, FALSE);
9258 if ((litval|mask) != 0x00ff)
9259 emitpcode(POC_ANDLW, popGetLit (mask));
9261 emitpcode(POC_IORLW, popGetLit (litval));
9262 emitPtrByteSet(result, p_type, TRUE);
9266 assert( !"trying to assign to bitfield via pointer to __code space" );
9270 assert( !"unhandled pointer type" );
9277 /* right is no literal */
9282 /* Note more efficient code, of pre clearing bit then only setting it if required,
9283 * can only be done if it is known that the result is not a SFR */
9284 emitpcode(POC_RRFW,popGet(AOP(right),0));
9286 emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9288 emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9294 emitPtrByteGet (result, p_type, FALSE);
9295 emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9296 emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9297 emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9298 emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9299 emitPtrByteSet (result, p_type, TRUE);
9303 assert( !"trying to assign to bitfield via pointer to __code space" );
9307 assert( !"unhandled pointer type" );
9312 /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9313 pCodeOp *temp = popGetTempReg ();
9315 mov2w (AOP(right), 0);
9317 emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9319 emitpcode(POC_MOVWF, temp);
9321 AccLsh (temp, bstr);
9327 mov2w (AOP(result), 0);
9328 emitpcode(POC_ANDLW, popGetLit (mask));
9329 emitpcode(POC_IORFW, temp);
9330 movwf (AOP(result), 0);
9336 emitPtrByteGet (result, p_type, FALSE);
9337 emitpcode(POC_ANDLW, popGetLit (mask));
9338 emitpcode(POC_IORFW, temp);
9339 emitPtrByteSet (result, p_type, TRUE);
9343 assert( !"trying to assign to bitfield via pointer to __code space" );
9347 assert( !"unhandled pointer type" );
9351 popReleaseTempReg (temp);
9353 } // if (AOP(right)->type != AOP_LIT)
9355 } // if (blen <= 8 && ((blen + bstr) <= 8))
9357 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9361 bitpatternFromVal (value *val)
9368 assert (sizeof (float) == sizeof (uint32_t));
9370 //fprintf (stderr, "%s:%u(%s): val=%lf, type: %d, etype: %d\n", __FILE__, __LINE__, __FUNCTION__, floatFromVal(val), SPEC_NOUN(val->type), SPEC_NOUN(val->etype));
9372 switch (SPEC_NOUN(val->type))
9376 return (unsigned long)floatFromVal (val);
9380 float_long.d = floatFromVal (val);
9381 return float_long.l;
9384 assert( !"unhandled value type" );
9388 float_long.d = floatFromVal (val);
9389 return float_long.l;
9392 /*-----------------------------------------------------------------*/
9393 /* genDataPointerSet - remat pointer to data space */
9394 /*-----------------------------------------------------------------*/
9395 static void genDataPointerSet(operand *right,
9399 int size, offset = 0 ;
9403 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9404 aopOp(right,ic,FALSE);
9405 aopOp(result,ic,FALSE);
9407 assert (IS_SYMOP(result));
9408 assert (IS_PTR(OP_SYM_TYPE(result)));
9410 size = AOP_SIZE(right);
9411 ressize = getSize(OP_SYM_ETYPE(result));
9412 if (size > ressize) size = ressize;
9413 //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9415 //assert( !"what's going on here?" );
9418 if ( AOP_TYPE(result) == AOP_PCODE) {
9419 fprintf(stderr,"genDataPointerSet %s, %d\n",
9420 AOP(result)->aopu.pcop->name,
9421 PCOI(AOP(result)->aopu.pcop)->offset);
9425 // tsd, was l+1 - the underline `_' prefix was being stripped
9427 emitpComment ("%s:%u: size=%d/%d, offset=%i", __FILE__,__LINE__, size, ressize, offset);
9429 if (AOP_TYPE(right) == AOP_LIT) {
9430 /* XXX: might be float... */
9431 unsigned int lit = bitpatternFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9432 lit = lit >> (8*offset);
9433 //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9435 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9436 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9438 emitpcode(POC_CLRF, popGet(AOP(result),offset));
9441 //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9442 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9443 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9449 freeAsmop(right,NULL,ic,TRUE);
9450 freeAsmop(result,NULL,ic,TRUE);
9453 /*-----------------------------------------------------------------*/
9454 /* genNearPointerSet - pic14_emitcode for near pointer put */
9455 /*-----------------------------------------------------------------*/
9456 static void genNearPointerSet (operand *right,
9461 sym_link *ptype = operandType(result);
9462 sym_link *retype = getSpec(operandType(right));
9463 sym_link *letype = getSpec(ptype);
9468 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9469 aopOp(result,ic,FALSE);
9472 /* if the result is rematerializable &
9473 in data space & not a bit variable */
9474 //if (AOP_TYPE(result) == AOP_IMMD &&
9475 if (AOP_TYPE(result) == AOP_PCODE &&
9476 PIC_IS_DATA_PTR(ptype) &&
9477 !IS_BITVAR (retype) &&
9478 !IS_BITVAR (letype)) {
9479 genDataPointerSet (right,result,ic);
9480 freeAsmop(result,NULL,ic,TRUE);
9485 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9486 aopOp(right,ic,FALSE);
9487 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9489 /* Check if can access directly instead of via a pointer */
9490 if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9494 if (IS_BITFIELD (letype))
9496 genPackBits (letype, result, right, direct?-1:POINTER);
9500 /* If the pointer value is not in a the FSR then need to put it in */
9501 /* Must set/reset IRP bit for use with FSR. */
9502 /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9507 /* we have can just get the values */
9508 int size = AOP_SIZE(right);
9511 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9513 char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9515 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9517 if (AOP_TYPE(right) == AOP_LIT) {
9518 emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9520 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9523 emitpcode(POC_MOVWF,popGet(AOP(result),0));
9525 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9527 if (size && !direct)
9528 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9533 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9534 /* now some housekeeping stuff */
9536 /* we had to allocate for this iCode */
9537 freeAsmop(NULL,aop,ic,TRUE);
9539 /* we did not allocate which means left
9540 already in a pointer register, then
9541 if size > 0 && this could be used again
9542 we have to point it back to where it
9544 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9545 if (AOP_SIZE(right) > 1 &&
9546 !OP_SYMBOL(result)->remat &&
9547 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9549 int size = AOP_SIZE(right) - 1;
9551 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9555 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9558 freeAsmop(right,NULL,ic,TRUE);
9559 freeAsmop(result,NULL,ic,TRUE);
9563 /*-----------------------------------------------------------------*/
9564 /* genPagedPointerSet - pic14_emitcode for Paged pointer put */
9565 /*-----------------------------------------------------------------*/
9566 static void genPagedPointerSet (operand *right,
9576 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9578 retype= getSpec(operandType(right));
9580 aopOp(result,ic,FALSE);
9582 /* if the value is already in a pointer register
9583 then don't need anything more */
9584 if (!AOP_INPREG(AOP(result))) {
9585 /* otherwise get a free pointer register */
9587 preg = getFreePtr(ic,&aop,FALSE);
9588 pic14_emitcode("mov","%s,%s",
9590 aopGet(AOP(result),0,FALSE,TRUE));
9591 rname = preg->name ;
9593 rname = aopGet(AOP(result),0,FALSE,FALSE);
9595 freeAsmop(result,NULL,ic,TRUE);
9596 aopOp (right,ic,FALSE);
9598 /* if bitfield then unpack the bits */
9599 if (IS_BITFIELD(retype))
9600 genPackBits (retype,result,right,rname,PPOINTER);
9602 /* we have can just get the values */
9603 int size = AOP_SIZE(right);
9607 l = aopGet(AOP(right),offset,FALSE,TRUE);
9610 pic14_emitcode("movx","@%s,a",rname);
9613 pic14_emitcode("inc","%s",rname);
9619 /* now some housekeeping stuff */
9621 /* we had to allocate for this iCode */
9622 freeAsmop(NULL,aop,ic,TRUE);
9624 /* we did not allocate which means left
9625 already in a pointer register, then
9626 if size > 0 && this could be used again
9627 we have to point it back to where it
9629 if (AOP_SIZE(right) > 1 &&
9630 !OP_SYMBOL(result)->remat &&
9631 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9633 int size = AOP_SIZE(right) - 1;
9635 pic14_emitcode("dec","%s",rname);
9640 freeAsmop(right,NULL,ic,TRUE);
9645 /*-----------------------------------------------------------------*/
9646 /* genFarPointerSet - set value from far space */
9647 /*-----------------------------------------------------------------*/
9648 static void genFarPointerSet (operand *right,
9649 operand *result, iCode *ic)
9652 sym_link *retype = getSpec(operandType(right));
9655 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9656 aopOp(result,ic,FALSE);
9658 /* if the operand is already in dptr
9659 then we do nothing else we move the value to dptr */
9660 if (AOP_TYPE(result) != AOP_STR) {
9661 /* if this is remateriazable */
9662 if (AOP_TYPE(result) == AOP_IMMD)
9663 pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9664 else { /* we need to get it byte by byte */
9665 pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9666 pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9667 if (options.model == MODEL_FLAT24)
9669 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9673 /* so dptr know contains the address */
9674 freeAsmop(result,NULL,ic,TRUE);
9675 aopOp(right,ic,FALSE);
9677 /* if bit then unpack */
9678 if (IS_BITFIELD(retype))
9679 genPackBits(retype,result,right,"dptr",FPOINTER);
9681 size = AOP_SIZE(right);
9685 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9687 pic14_emitcode("movx","@dptr,a");
9689 pic14_emitcode("inc","dptr");
9693 freeAsmop(right,NULL,ic,TRUE);
9697 /*-----------------------------------------------------------------*/
9698 /* genGenPointerSet - set value from generic pointer space */
9699 /*-----------------------------------------------------------------*/
9700 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9702 sym_link *retype = getSpec(operandType(result));
9705 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9706 aopOp(right,ic,FALSE);
9707 aopOp(result,ic,FALSE);
9710 DEBUGpic14_AopType(__LINE__,right,NULL,result);
9712 if (IS_BITFIELD(retype))
9714 genPackBits (retype, result, right, GPOINTER);
9719 /* emit call to __gptrput */
9720 char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9721 int size = AOP_SIZE(right);
9724 assert (size == getSize(OP_SYM_ETYPE(result)));
9725 assert (size > 0 && size <= 4);
9727 /* pass arguments */
9728 /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9734 mov2w_op (right, off);
9735 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9740 assert (AOP_SIZE(result) == 3);
9741 mov2w(AOP(result), 0);
9742 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9743 mov2w(AOP(result), 1);
9744 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9745 mov2w(AOP(result), 2);
9746 call_libraryfunc (func[size]);
9749 freeAsmop(right,NULL,ic,TRUE);
9750 freeAsmop(result,NULL,ic,TRUE);
9753 /*-----------------------------------------------------------------*/
9754 /* genPointerSet - stores the value into a pointer location */
9755 /*-----------------------------------------------------------------*/
9756 static void genPointerSet (iCode *ic)
9758 operand *right, *result ;
9759 sym_link *type, *etype;
9763 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9765 right = IC_RIGHT(ic);
9766 result = IC_RESULT(ic) ;
9768 /* depending on the type of pointer we need to
9769 move it to the correct pointer register */
9770 type = operandType(result);
9771 etype = getSpec(type);
9772 /* if left is of type of pointer then it is simple */
9773 if (IS_PTR(type) && !IS_FUNC(type->next)) {
9774 p_type = DCL_TYPE(type);
9777 /* we have to go by the storage class */
9778 p_type = PTR_TYPE(SPEC_OCLS(etype));
9780 /* if (SPEC_OCLS(etype)->codesp ) { */
9781 /* p_type = CPOINTER ; */
9784 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9785 /* p_type = FPOINTER ; */
9787 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9788 /* p_type = PPOINTER ; */
9790 /* if (SPEC_OCLS(etype) == idata ) */
9791 /* p_type = IPOINTER ; */
9793 /* p_type = POINTER ; */
9796 /* now that we have the pointer type we assign
9797 the pointer values */
9803 genNearPointerSet (right,result,ic);
9807 genPagedPointerSet (right,result,ic);
9811 genFarPointerSet (right,result,ic);
9815 genGenPointerSet (right,result,ic);
9819 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9820 "genPointerSet: illegal pointer type");
9824 /*-----------------------------------------------------------------*/
9825 /* genIfx - generate code for Ifx statement */
9826 /*-----------------------------------------------------------------*/
9827 static void genIfx (iCode *ic, iCode *popIc)
9829 operand *cond = IC_COND(ic);
9833 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9835 aopOp(cond,ic,FALSE);
9837 /* get the value into acc */
9838 if (AOP_TYPE(cond) != AOP_CRY)
9839 pic14_toBoolean(cond);
9843 /* if there was something to be popped then do it */
9849 /* This assumes that CARRY is set iff cond is true */
9852 assert (!IC_FALSE(ic));
9853 emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
9855 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9857 assert (IC_FALSE(ic));
9858 emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
9860 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9864 static int hasWarned = 0;
9867 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
9874 /* now Z is set iff !cond */
9877 assert (!IC_FALSE(ic));
9879 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9882 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9888 /* the result is now in the accumulator */
9889 freeAsmop(cond,NULL,ic,TRUE);
9892 /*-----------------------------------------------------------------*/
9893 /* genAddrOf - generates code for address of */
9894 /*-----------------------------------------------------------------*/
9895 static void genAddrOf (iCode *ic)
9897 operand *right, *result, *left;
9901 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9904 //aopOp(IC_RESULT(ic),ic,FALSE);
9906 aopOp((left=IC_LEFT(ic)),ic,FALSE);
9907 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9908 aopOp((result=IC_RESULT(ic)),ic,TRUE);
9910 DEBUGpic14_AopType(__LINE__,left,right,result);
9911 assert (IS_SYMOP (left));
9913 /* sanity check: generic pointers to code space are not yet supported,
9914 * pionters to codespace must not be assigned addresses of __data values. */
9916 fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9917 fprintf (stderr, "result->type : "); printTypeChain (OP_SYM_TYPE(result), stderr); fprintf (stderr, ", codesp:%d, codeptr:%d, constptr:%d\n", IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(result)))), IS_CODEPTR(OP_SYM_TYPE(result)), IS_PTR_CONST(OP_SYM_TYPE(result)));
9918 fprintf (stderr, "result->etype: "); printTypeChain (OP_SYM_ETYPE(result), stderr); fprintf (stderr, ", codesp:%d, codeptr:%d, constptr:%d\n", IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_ETYPE(result)))), IS_CODEPTR(OP_SYM_ETYPE(result)), IS_PTR_CONST(OP_SYM_ETYPE(result)));
9919 fprintf (stderr, "left->type : "); printTypeChain (OP_SYM_TYPE(left), stderr); fprintf (stderr, ", codesp:%d, codeptr:%d, constptr:%d\n", IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left)))), IS_CODEPTR(OP_SYM_TYPE(left)), IS_PTR_CONST(OP_SYM_TYPE(left)));
9920 fprintf (stderr, "left->etype : "); printTypeChain (OP_SYM_ETYPE(left), stderr); fprintf (stderr, ", codesp:%d, codeptr:%d, constptr:%d\n",IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_ETYPE(left)))), IS_CODEPTR(OP_SYM_ETYPE(left)), IS_PTR_CONST(OP_SYM_ETYPE(left)));
9923 if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9924 fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9925 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9926 OP_SYMBOL(left)->name);
9927 } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9928 fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9929 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9930 OP_SYMBOL(left)->name);
9933 size = AOP_SIZE(IC_RESULT(ic));
9934 if (IS_GENPTR(OP_SYM_TYPE(result))) {
9936 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9941 /* fixing bug #863624, reported from (errolv) */
9942 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9943 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9946 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9947 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9952 if (IS_GENPTR(OP_SYM_TYPE(result)))
9954 /* provide correct tag */
9955 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9956 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9957 movwf (AOP(result), 2);
9960 freeAsmop(left,NULL,ic,FALSE);
9961 freeAsmop(result,NULL,ic,TRUE);
9966 /*-----------------------------------------------------------------*/
9967 /* genFarFarAssign - assignment when both are in far space */
9968 /*-----------------------------------------------------------------*/
9969 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9971 int size = AOP_SIZE(right);
9974 /* first push the right side on to the stack */
9976 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9978 pic14_emitcode ("push","acc");
9981 freeAsmop(right,NULL,ic,FALSE);
9982 /* now assign DPTR to result */
9983 aopOp(result,ic,FALSE);
9984 size = AOP_SIZE(result);
9986 pic14_emitcode ("pop","acc");
9987 aopPut(AOP(result),"a",--offset);
9989 freeAsmop(result,NULL,ic,FALSE);
9994 /*-----------------------------------------------------------------*/
9995 /* genAssign - generate code for assignment */
9996 /*-----------------------------------------------------------------*/
9997 static void genAssign (iCode *ic)
9999 operand *result, *right;
10000 int size, offset,know_W;
10001 unsigned long lit = 0L;
10003 result = IC_RESULT(ic);
10004 right = IC_RIGHT(ic) ;
10007 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10009 /* if they are the same */
10010 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10013 aopOp(right,ic,FALSE);
10014 aopOp(result,ic,TRUE);
10016 DEBUGpic14_AopType(__LINE__,NULL,right,result);
10018 /* if they are the same registers */
10019 if (pic14_sameRegs(AOP(right),AOP(result)))
10022 /* special case: assign from __code */
10023 if (!IS_ITEMP(right) /* --> iTemps never reside in __code */
10024 && IS_SYMOP (right) /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
10025 && !IS_FUNC(OP_SYM_TYPE(right)) /* --> we would want its address instead of the first instruction */
10026 && !IS_CODEPTR(OP_SYM_TYPE(right)) /* --> get symbols address instread */
10027 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
10029 emitpComment ("genAssign from CODESPACE");
10030 genConstPointerGet (right, result, ic);
10034 /* just for symmetry reasons... */
10035 if (!IS_ITEMP(result)
10036 && IS_SYMOP (result)
10037 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
10039 assert ( !"cannot write to CODESPACE" );
10042 /* if the result is a bit */
10043 if (AOP_TYPE(result) == AOP_CRY) {
10045 /* if the right size is a literal then
10046 we know what the value is */
10047 if (AOP_TYPE(right) == AOP_LIT) {
10049 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10050 popGet(AOP(result),0));
10052 if (((int) operandLitValue(right)))
10053 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10054 AOP(result)->aopu.aop_dir,
10055 AOP(result)->aopu.aop_dir);
10057 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10058 AOP(result)->aopu.aop_dir,
10059 AOP(result)->aopu.aop_dir);
10063 /* the right is also a bit variable */
10064 if (AOP_TYPE(right) == AOP_CRY) {
10065 emitpcode(POC_BCF, popGet(AOP(result),0));
10066 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10067 emitpcode(POC_BSF, popGet(AOP(result),0));
10069 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10070 AOP(result)->aopu.aop_dir,
10071 AOP(result)->aopu.aop_dir);
10072 pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
10073 AOP(right)->aopu.aop_dir,
10074 AOP(right)->aopu.aop_dir);
10075 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10076 AOP(result)->aopu.aop_dir,
10077 AOP(result)->aopu.aop_dir);
10081 /* we need to or */
10082 emitpcode(POC_BCF, popGet(AOP(result),0));
10083 pic14_toBoolean(right);
10085 emitpcode(POC_BSF, popGet(AOP(result),0));
10086 //aopPut(AOP(result),"a",0);
10090 /* bit variables done */
10092 size = AOP_SIZE(result);
10094 if(AOP_TYPE(right) == AOP_LIT)
10095 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10097 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
10098 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10099 if(aopIdx(AOP(result),0) == 4) {
10100 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10101 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10102 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10105 DEBUGpic14_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
10110 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10111 if(AOP_TYPE(right) == AOP_LIT) {
10113 if(know_W != (int)(lit&0xff))
10114 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10116 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10118 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10122 } else if (AOP_TYPE(right) == AOP_CRY) {
10123 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10125 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10126 emitpcode(POC_INCF, popGet(AOP(result),0));
10129 mov2w_op (right, offset);
10130 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10138 freeAsmop (right,NULL,ic,FALSE);
10139 freeAsmop (result,NULL,ic,TRUE);
10142 /*-----------------------------------------------------------------*/
10143 /* genJumpTab - genrates code for jump table */
10144 /*-----------------------------------------------------------------*/
10145 static void genJumpTab (iCode *ic)
10151 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10153 aopOp(IC_JTCOND(ic),ic,FALSE);
10154 /* get the condition into accumulator */
10155 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10157 /* multiply by three */
10158 pic14_emitcode("add","a,acc");
10159 pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10161 jtab = newiTempLabel(NULL);
10162 pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10163 pic14_emitcode("jmp","@a+dptr");
10164 pic14_emitcode("","%05d_DS_:",jtab->key+100);
10166 emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10167 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10168 emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10169 emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10171 emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10172 emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10173 emitpLabel(jtab->key);
10175 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10177 /* now generate the jump labels */
10178 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10179 jtab = setNextItem(IC_JTLABELS(ic))) {
10180 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10181 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10187 /*-----------------------------------------------------------------*/
10188 /* genMixedOperation - gen code for operators between mixed types */
10189 /*-----------------------------------------------------------------*/
10191 TSD - Written for the PIC port - but this unfortunately is buggy.
10192 This routine is good in that it is able to efficiently promote
10193 types to different (larger) sizes. Unfortunately, the temporary
10194 variables that are optimized out by this routine are sometimes
10195 used in other places. So until I know how to really parse the
10196 iCode tree, I'm going to not be using this routine :(.
10198 static int genMixedOperation (iCode *ic)
10202 operand *result = IC_RESULT(ic);
10203 sym_link *ctype = operandType(IC_LEFT(ic));
10204 operand *right = IC_RIGHT(ic);
10210 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10212 pic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10218 nextright = IC_RIGHT(nextic);
10219 nextleft = IC_LEFT(nextic);
10220 nextresult = IC_RESULT(nextic);
10222 aopOp(right,ic,FALSE);
10223 aopOp(result,ic,FALSE);
10224 aopOp(nextright, nextic, FALSE);
10225 aopOp(nextleft, nextic, FALSE);
10226 aopOp(nextresult, nextic, FALSE);
10228 if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10230 operand *t = right;
10234 pic14_emitcode(";remove right +","");
10236 } else if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10238 operand *t = right;
10242 pic14_emitcode(";remove left +","");
10246 big = AOP_SIZE(nextleft);
10247 small = AOP_SIZE(nextright);
10249 switch(nextic->op) {
10252 pic14_emitcode(";optimize a +","");
10253 /* if unsigned or not an integral type */
10254 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10255 pic14_emitcode(";add a bit to something","");
10258 pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10260 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10261 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10262 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10264 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10272 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10273 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10274 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10277 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10279 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10280 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10281 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10282 pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10283 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10286 pic14_emitcode("rlf","known_zero,w");
10293 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10294 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10295 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10297 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10307 freeAsmop(right,NULL,ic,TRUE);
10308 freeAsmop(result,NULL,ic,TRUE);
10309 freeAsmop(nextright,NULL,ic,TRUE);
10310 freeAsmop(nextleft,NULL,ic,TRUE);
10312 nextic->generated = 1;
10319 /*-----------------------------------------------------------------*/
10320 /* genCast - gen code for casting */
10321 /*-----------------------------------------------------------------*/
10322 static void genCast (iCode *ic)
10324 operand *result = IC_RESULT(ic);
10325 sym_link *restype = operandType(result);
10326 sym_link *rtype = operandType(IC_RIGHT(ic));
10327 operand *right = IC_RIGHT(ic);
10331 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10332 /* if they are equivalent then do nothing */
10333 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10336 aopOp(right,ic,FALSE) ;
10337 aopOp(result,ic,FALSE);
10339 DEBUGpic14_AopType(__LINE__,NULL,right,result);
10341 /* if the result is a bit */
10342 if (AOP_TYPE(result) == AOP_CRY) {
10343 assert(!"assigning to bit variables is not supported");
10346 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10348 size = AOP_SIZE(result);
10350 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10352 emitpcode(POC_CLRF, popGet(AOP(result),0));
10353 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10354 emitpcode(POC_INCF, popGet(AOP(result),0));
10357 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
10362 if (IS_PTR(restype))
10364 operand *result = IC_RESULT(ic);
10365 //operand *left = IC_LEFT(ic);
10366 operand *right = IC_RIGHT(ic);
10369 /* copy common part */
10370 int max, size = AOP_SIZE(result);
10371 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10372 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10374 /* warn if we discard generic opinter tag */
10375 if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10377 //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10383 mov2w_op (right, size);
10384 movwf (AOP(result), size);
10387 /* upcast into generic pointer type? */
10388 if (IS_GENPTR(restype)
10389 && (size < AOP_SIZE(result))
10390 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10392 //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10395 switch (DCL_TYPE(rtype))
10397 case POINTER: /* __data */
10398 case FPOINTER: /* __data */
10399 assert (AOP_SIZE(right) == 2);
10400 tag = GPTRTAG_DATA;
10403 case CPOINTER: /* __code */
10404 assert (AOP_SIZE(right) == 2);
10405 tag = GPTRTAG_CODE;
10408 case GPOINTER: /* unknown destination, __data or __code */
10409 /* assume __data space (address of immediate) */
10410 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10411 if (AOP(right)->code)
10412 tag = GPTRTAG_CODE;
10414 tag = GPTRTAG_DATA;
10418 assert (!"unhandled pointer type");
10421 /* convert other values into pointers to __data space */
10422 tag = GPTRTAG_DATA;
10425 assert (AOP_SIZE(result) == 3);
10427 emitpcode(POC_CLRF, popGet(AOP(result), 2));
10429 emitpcode(POC_MOVLW, popGetLit(tag));
10430 movwf(AOP(result), 2);
10433 addSign(result, max, 0);
10438 /* if they are the same size : or less */
10439 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10441 /* if they are in the same place */
10442 if (pic14_sameRegs(AOP(right),AOP(result)))
10445 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10446 if (IS_PTR_CONST(rtype))
10447 DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10448 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10449 DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10451 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10452 emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10453 emitpcode(POC_MOVWF, popGet(AOP(result),0));
10454 emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10455 emitpcode(POC_MOVWF, popGet(AOP(result),1));
10456 if(AOP_SIZE(result) <2)
10457 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10461 /* if they in different places then copy */
10462 size = AOP_SIZE(result);
10465 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10466 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10468 //aopPut(AOP(result),
10469 // aopGet(AOP(right),offset,FALSE,FALSE),
10478 /* so we now know that the size of destination is greater
10479 than the size of the source.
10480 Now, if the next iCode is an operator then we might be
10481 able to optimize the operation without performing a cast.
10483 if(0 && genMixedOperation(ic)) {
10484 /* XXX: cannot optimize: must copy regs! */
10488 /* we move to result for the size of source */
10489 size = AOP_SIZE(right);
10492 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10493 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10497 addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10500 freeAsmop(right,NULL,ic,TRUE);
10501 freeAsmop(result,NULL,ic,TRUE);
10505 /*-----------------------------------------------------------------*/
10506 /* genDjnz - generate decrement & jump if not zero instrucion */
10507 /*-----------------------------------------------------------------*/
10508 static int genDjnz (iCode *ic, iCode *ifx)
10510 symbol *lbl, *lbl1;
10512 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10517 /* if the if condition has a false label
10518 then we cannot save */
10522 /* if the minus is not of the form
10524 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10525 !IS_OP_LITERAL(IC_RIGHT(ic)))
10528 if (operandLitValue(IC_RIGHT(ic)) != 1)
10531 /* if the size of this greater than one then no
10533 if (getSize(operandType(IC_RESULT(ic))) > 1)
10536 /* otherwise we can save BIG */
10537 lbl = newiTempLabel(NULL);
10538 lbl1= newiTempLabel(NULL);
10540 aopOp(IC_RESULT(ic),ic,FALSE);
10542 if (IS_AOP_PREG(IC_RESULT(ic))) {
10543 pic14_emitcode("dec","%s",
10544 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10545 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10546 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10550 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10551 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10553 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10554 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10557 /* pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10558 /* pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10559 /* pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10560 /* pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10563 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10564 ifx->generated = 1;
10568 /*-----------------------------------------------------------------*/
10569 /* genReceive - generate code for a receive iCode */
10570 /*-----------------------------------------------------------------*/
10571 static void genReceive (iCode *ic)
10574 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10576 if (isOperandInFarSpace(IC_RESULT(ic)) &&
10577 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10578 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10580 int size = getSize(operandType(IC_RESULT(ic)));
10581 int offset = fReturnSizePic - size;
10583 pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10584 fReturn[fReturnSizePic - offset - 1] : "acc"));
10587 aopOp(IC_RESULT(ic),ic,FALSE);
10588 size = AOP_SIZE(IC_RESULT(ic));
10591 pic14_emitcode ("pop","acc");
10592 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10597 aopOp(IC_RESULT(ic),ic,FALSE);
10599 assignResultValue(IC_RESULT(ic));
10602 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10605 /*-----------------------------------------------------------------*/
10606 /* genDummyRead - generate code for dummy read of volatiles */
10607 /*-----------------------------------------------------------------*/
10609 genDummyRead (iCode * ic)
10612 pic14_emitcode ("; genDummyRead","");
10613 pic14_emitcode ("; not implemented","");
10618 /*-----------------------------------------------------------------*/
10619 /* genpic14Code - generate code for pic14 based controllers */
10620 /*-----------------------------------------------------------------*/
10622 * At this point, ralloc.c has gone through the iCode and attempted
10623 * to optimize in a way suitable for a PIC. Now we've got to generate
10624 * PIC instructions that correspond to the iCode.
10626 * Once the instructions are generated, we'll pass through both the
10627 * peep hole optimizer and the pCode optimizer.
10628 *-----------------------------------------------------------------*/
10630 void genpic14Code (iCode *lic)
10637 lineHead = lineCurr = NULL;
10639 pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10642 /* if debug information required */
10643 if (options.debug && currFunc) {
10645 debugFile->writeFunction (currFunc, lic);
10650 for (ic = lic ; ic ; ic = ic->next ) {
10652 //DEBUGpic14_emitcode(";ic","");
10653 //fprintf (stderr, "in ic loop\n");
10654 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10655 //ic->lineno, printCLine(ic->filename, ic->lineno));
10657 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10659 //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10660 cline = printCLine (ic->filename, ic->lineno);
10661 if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10662 addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10663 //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10666 if (options.iCodeInAsm) {
10667 emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10669 /* if the result is marked as
10670 spilt and rematerializable or code for
10671 this has already been generated then
10673 if (resultRemat(ic) || ic->generated )
10676 /* depending on the operation */
10695 /* IPOP happens only when trying to restore a
10696 spilt live range, if there is an ifx statement
10697 following this pop then the if statement might
10698 be using some of the registers being popped which
10699 would destory the contents of the register so
10700 we need to check for this condition and handle it */
10702 ic->next->op == IFX &&
10703 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10704 genIfx (ic->next,ic);
10722 genEndFunction (ic);
10742 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10759 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
10763 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10770 /* note these two are xlated by algebraic equivalence
10771 during parsing SDCC.y */
10772 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10773 "got '>=' or '<=' shouldn't have come here");
10777 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10789 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10793 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10797 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10821 genRightShift (ic);
10824 case GET_VALUE_AT_ADDRESS:
10829 if (POINTER_SET(ic))
10856 addSet(&_G.sendSet,ic);
10859 case DUMMY_READ_VOLATILE:
10864 fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10871 /* now we are ready to call the
10872 peep hole optimizer */
10873 if (!options.nopeep) {
10874 peepHole (&lineHead);
10876 /* now do the actual printing */
10877 printLine (lineHead,codeOutFile);
10880 DFPRINTF((stderr,"printing pBlock\n\n"));
10881 printpBlock(stdout,pb);
10887 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10888 * (meaning: representing its own address) or not (referencing its contents).
10889 * This can only be decided based on the operand's type. */
10891 aop_isLitLike (asmop *aop)
10894 if (aop->type == AOP_LIT) return 1;
10895 if (aop->type == AOP_IMMD) return 1;
10896 if ((aop->type == AOP_PCODE) &&
10897 ((aop->aopu.pcop->type == PO_LITERAL)))
10899 /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10900 * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10907 op_isLitLike (operand *op)
10910 if (aop_isLitLike (AOP(op))) return 1;
10911 if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10912 if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;