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 -------------------------------------------------------------------------*/
42 #include "SDCCglobl.h"
46 #include "SDCCpeeph.h"
51 /* When changing these, you must also update the assembler template
52 * in device/lib/libsdcc/macros.inc */
53 #define GPTRTAG_DATA 0x00
54 #define GPTRTAG_CODE 0x80
56 /* The PIC port(s) need not differentiate between POINTER and FPOINTER. */
57 #define PIC_IS_DATA_PTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
58 #define PIC_IS_FARPTR(x) (PIC_IS_DATA_PTR(x))
60 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
61 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
62 void genMult8X8_8 (operand *, operand *,operand *);
63 extern void printpBlock(FILE *of, pBlock *pb);
65 static int labelOffset=0;
66 extern int debug_verbose;
67 extern int pic14_hasInterrupt;
68 //static int optimized_for_speed = 0;
70 /* max_key keeps track of the largest label number used in
71 a function. This is then used to adjust the label offset
72 for the next function.
75 static int GpsuedoStkPtr=0;
77 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
78 extern char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
79 unsigned int pic14aopLiteral (value *val, int offset);
80 const char *AopType(short type);
82 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0x00ff)
84 /* this is the down and dirty file with all kinds of
85 kludgy & hacky stuff. This is what it is all about
86 CODE GENERATION for a specific MCU . some of the
87 routines may be reusable, will have to see */
89 static char *zero = "#0x00";
90 static char *one = "#0x01";
91 static char *spname = "sp";
93 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
94 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
95 static char **fReturn = fReturnpic14;
97 //static char *accUse[] = {"a","b"};
99 //static short rbank = -1;
111 /* Resolved ifx structure. This structure stores information
112 about an iCode ifx that makes it easier to generate code.
114 typedef struct resolvedIfx {
115 symbol *lbl; /* pointer to a label */
116 int condition; /* true or false ifx */
117 int generated; /* set true when the code associated with the ifx
121 extern int pic14_ptrRegReq ;
122 extern int pic14_nRegs;
123 extern FILE *codeOutFile;
124 static void saverbank (int, iCode *,bool);
126 static lineNode *lineHead = NULL;
127 static lineNode *lineCurr = NULL;
130 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
131 0xE0, 0xC0, 0x80, 0x00};
132 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
133 0x07, 0x03, 0x01, 0x00};
138 /*-----------------------------------------------------------------*/
139 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
140 /* exponent of 2 is returned, otherwise -1 is */
142 /* note that this is similar to the function `powof2' in SDCCsymt */
146 /*-----------------------------------------------------------------*/
147 static int my_powof2 (unsigned long num)
150 if( (num & (num-1)) == 0) {
163 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
166 DEBUGpic14_emitcode ("; ","line = %d result %s=%s, size=%d, left %s=%s, size=%d, right %s=%s, size=%d",
168 ((result) ? AopType(AOP_TYPE(result)) : "-"),
169 ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
170 ((result) ? AOP_SIZE(result) : 0),
171 ((left) ? AopType(AOP_TYPE(left)) : "-"),
172 ((left) ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
173 ((left) ? AOP_SIZE(left) : 0),
174 ((right) ? AopType(AOP_TYPE(right)) : "-"),
175 ((right) ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
176 ((right) ? AOP_SIZE(right) : 0));
180 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
183 DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
185 ((result) ? AopType(AOP_TYPE(result)) : "-"),
186 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
187 ((left) ? AopType(AOP_TYPE(left)) : "-"),
188 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
189 ((right) ? AopType(AOP_TYPE(right)) : "-"),
190 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
194 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
197 char lb[INITIAL_INLINEASM];
198 unsigned char *lbp = (unsigned char *)lb;
200 if(!debug_verbose && !options.debug)
207 sprintf(lb,"%s\t",inst);
209 sprintf(lb,"%s",inst);
210 vsprintf(lb+(strlen(lb)),fmt,ap);
214 while (isspace(*lbp)) lbp++;
217 lineCurr = (lineCurr ?
218 connectLine(lineCurr,newLineNode(lb)) :
219 (lineHead = newLineNode(lb)));
220 lineCurr->isInline = _G.inLine;
221 lineCurr->isDebug = _G.debugLine;
223 addpCode2pBlock(pb,newpCodeCharP(lb));
228 static void Safe_vsnprintf (char *buf, size_t size, const char *fmt, va_list ap)
230 #if defined (HAVE_VSNPRINTF)
231 vsnprintf (buf, size, fmt, ap);
232 #elif defined (HAVE_VSPRINTF)
233 vsprintf (buf, size, fmt, ap);
234 if (strlen (buf) >= size)
236 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
238 #elif defined (HAVE_SNPRINTF)
239 snprintf (buf, size, "vs(n)printf required");
240 #elif defined (HAVE_SRINTF)
241 sprintf (buf, "vs(n)printf required");
242 if (strlen (buf) >= size)
244 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
247 assert ( !"neither vsnprintf nor vsprintf is present -- unable to proceed" );
251 void emitpComment (const char *fmt, ...)
258 Safe_vsnprintf (buffer, 4096, fmt, va);
259 //fprintf (stderr, "%s\n" ,buffer);
260 addpCode2pBlock (pb, newpCodeCharP (buffer));
263 Safe_vsnprintf (buffer, 4096, fmt, va);
264 fprintf (stderr, "No current pBlock -- discarding comment [%s]\n", buffer);
270 void emitpLabel(int key)
272 addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
275 /* gen.h defines a macro emitpcode that should be used to call emitpcode
276 * as this allows for easy debugging (ever asked the question: where was
277 * this instruction geenrated? Here is the answer... */
278 void emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
281 addpCode2pBlock(pb,newpCode(poc,pcop));
283 DEBUGpic14_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
286 void emitpcodeNULLop(PIC_OPCODE poc)
289 addpCode2pBlock(pb,newpCode(poc,NULL));
294 /*-----------------------------------------------------------------*/
295 /* pic14_emitcode - writes the code into a file : for now it is simple */
296 /*-----------------------------------------------------------------*/
297 void pic14_emitcode (char *inst,char *fmt, ...)
300 char lb[INITIAL_INLINEASM];
301 unsigned char *lbp = (unsigned char *)lb;
307 sprintf(lb,"%s\t",inst);
309 sprintf(lb,"%s",inst);
310 vsprintf(lb+(strlen(lb)),fmt,ap);
314 while (isspace(*lbp)) lbp++;
317 lineCurr = (lineCurr ?
318 connectLine(lineCurr,newLineNode(lb)) :
319 (lineHead = newLineNode(lb)));
320 lineCurr->isInline = _G.inLine;
321 lineCurr->isDebug = _G.debugLine;
324 addpCode2pBlock(pb,newpCodeCharP(lb));
329 /*-----------------------------------------------------------------*/
330 /* pic14_emitDebuggerSymbol - associate the current code location */
331 /* with a debugger symbol */
332 /*-----------------------------------------------------------------*/
334 pic14_emitDebuggerSymbol (char * debugSym)
337 pic14_emitcode ("", ";%s ==.", debugSym);
342 /*-----------------------------------------------------------------*/
343 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
344 /*-----------------------------------------------------------------*/
345 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
347 bool r0iu = FALSE , r1iu = FALSE;
348 bool r0ou = FALSE , r1ou = FALSE;
350 /* the logic: if r0 & r1 used in the instruction
351 then we are in trouble otherwise */
353 /* first check if r0 & r1 are used by this
354 instruction, in which case we are in trouble */
355 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
356 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
361 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
362 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
364 /* if no usage of r0 then return it */
365 if (!r0iu && !r0ou) {
366 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
367 (*aopp)->type = AOP_R0;
369 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
372 /* if no usage of r1 then return it */
373 if (!r1iu && !r1ou) {
374 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
375 (*aopp)->type = AOP_R1;
377 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
380 /* now we know they both have usage */
381 /* if r0 not used in this instruction */
383 /* push it if not already pushed */
385 //pic14_emitcode ("push","%s",
386 // pic14_regWithIdx(R0_IDX)->dname);
390 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
391 (*aopp)->type = AOP_R0;
393 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
396 /* if r1 not used then */
399 /* push it if not already pushed */
401 //pic14_emitcode ("push","%s",
402 // pic14_regWithIdx(R1_IDX)->dname);
406 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
407 (*aopp)->type = AOP_R1;
408 return pic14_regWithIdx(R1_IDX);
412 /* I said end of world but not quite end of world yet */
413 /* if this is a result then we can push it on the stack*/
415 (*aopp)->type = AOP_STK;
419 /* other wise this is true end of the world */
420 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
421 "getFreePtr should never reach here");
426 /*-----------------------------------------------------------------*/
427 /* newAsmop - creates a new asmOp */
428 /*-----------------------------------------------------------------*/
429 asmop *newAsmop (short type)
433 aop = Safe_calloc(1,sizeof(asmop));
438 static void genSetDPTR(int n)
442 pic14_emitcode(";", "Select standard DPTR");
443 pic14_emitcode("mov", "dps, #0x00");
447 pic14_emitcode(";", "Select alternate DPTR");
448 pic14_emitcode("mov", "dps, #0x01");
452 /*-----------------------------------------------------------------*/
453 /* resolveIfx - converts an iCode ifx into a form more useful for */
454 /* generating code */
455 /*-----------------------------------------------------------------*/
456 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
461 // DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
463 resIfx->condition = 1; /* assume that the ifx is true */
464 resIfx->generated = 0; /* indicate that the ifx has not been used */
467 resIfx->lbl = NULL; /* this is wrong: newiTempLabel(NULL); / * oops, there is no ifx. so create a label */
469 DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
470 __FUNCTION__,__LINE__,resIfx->lbl->key);
474 resIfx->lbl = IC_TRUE(ifx);
476 resIfx->lbl = IC_FALSE(ifx);
477 resIfx->condition = 0;
481 DEBUGpic14_emitcode("; ***","ifx true is non-null");
483 DEBUGpic14_emitcode("; ***","ifx false is non-null");
487 // DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
490 /*-----------------------------------------------------------------*/
491 /* pointerCode - returns the code for a pointer type */
492 /*-----------------------------------------------------------------*/
494 static int pointerCode (sym_link *etype)
497 return PTR_TYPE(SPEC_OCLS(etype));
502 /*-----------------------------------------------------------------*/
503 /* aopForSym - for a true symbol */
504 /*-----------------------------------------------------------------*/
505 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
508 memmap *space= SPEC_OCLS(sym->etype);
510 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
511 /* if already has one */
516 /* assign depending on the storage class */
517 /* if it is on the stack or indirectly addressable */
518 /* space we need to assign either r0 or r1 to it */
519 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
520 sym->aop = aop = newAsmop(0);
521 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
522 aop->size = getSize(sym->type);
524 /* now assign the address of the variable to
525 the pointer register */
526 if (aop->type != AOP_STK) {
530 pic14_emitcode("push","acc");
532 pic14_emitcode("mov","a,_bp");
533 pic14_emitcode("add","a,#0x%02x",
535 ((char)(sym->stack - _G.nRegsSaved )) :
536 ((char)sym->stack)) & 0xff);
537 pic14_emitcode("mov","%s,a",
538 aop->aopu.aop_ptr->name);
541 pic14_emitcode("pop","acc");
543 pic14_emitcode("mov","%s,#%s",
544 aop->aopu.aop_ptr->name,
546 aop->paged = space->paged;
548 aop->aopu.aop_stk = sym->stack;
552 if (sym->onStack && options.stack10bit)
554 /* It's on the 10 bit stack, which is located in
558 //DEBUGpic14_emitcode(";","%d",__LINE__);
561 pic14_emitcode("push","acc");
563 pic14_emitcode("mov","a,_bp");
564 pic14_emitcode("add","a,#0x%02x",
566 ((char)(sym->stack - _G.nRegsSaved )) :
567 ((char)sym->stack)) & 0xff);
570 pic14_emitcode ("mov","dpx1,#0x40");
571 pic14_emitcode ("mov","dph1,#0x00");
572 pic14_emitcode ("mov","dpl1, a");
576 pic14_emitcode("pop","acc");
578 sym->aop = aop = newAsmop(AOP_DPTR2);
579 aop->size = getSize(sym->type);
584 //DEBUGpic14_emitcode(";","%d",__LINE__);
585 /* if in bit space */
586 if (IN_BITSPACE(space)) {
587 sym->aop = aop = newAsmop (AOP_CRY);
588 aop->aopu.aop_dir = sym->rname ;
589 aop->size = getSize(sym->type);
590 //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
593 /* if it is in direct space */
594 if (IN_DIRSPACE(space)) {
595 sym->aop = aop = newAsmop (AOP_DIR);
596 aop->aopu.aop_dir = sym->rname ;
597 aop->size = getSize(sym->type);
598 DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
602 /* special case for a function */
603 if (IS_FUNC(sym->type)) {
605 sym->aop = aop = newAsmop(AOP_PCODE);
606 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
607 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
608 PCOI(aop->aopu.pcop)->_function = 1;
609 PCOI(aop->aopu.pcop)->index = 0;
610 aop->size = FPTRSIZE;
612 sym->aop = aop = newAsmop(AOP_IMMD);
613 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
614 strcpy(aop->aopu.aop_immd,sym->rname);
615 aop->size = FPTRSIZE;
617 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
621 if (IS_ARRAY(sym->type)) {
622 sym->aop = aop = newAsmop(AOP_PCODE);
623 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
624 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
625 PCOI(aop->aopu.pcop)->_function = 0;
626 PCOI(aop->aopu.pcop)->index = 0;
627 aop->size = getSize(sym->etype) * DCL_ELEM(sym->type);
629 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
633 /* only remaining is far space */
634 /* in which case DPTR gets the address */
635 sym->aop = aop = newAsmop(AOP_PCODE);
637 aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
638 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
639 PCOI(aop->aopu.pcop)->index = 0;
641 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
642 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
644 allocDirReg (IC_LEFT(ic));
646 aop->size = FPTRSIZE;
648 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
649 sym->aop = aop = newAsmop(AOP_DPTR);
650 pic14_emitcode ("mov","dptr,#%s", sym->rname);
651 aop->size = getSize(sym->type);
653 DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
656 /* if it is in code space */
657 if (IN_CODESPACE(space))
663 /*-----------------------------------------------------------------*/
664 /* aopForRemat - rematerialzes an object */
665 /*-----------------------------------------------------------------*/
666 static asmop *aopForRemat (operand *op) // x symbol *sym)
668 symbol *sym = OP_SYMBOL(op);
670 asmop *aop = newAsmop(AOP_PCODE);
674 ic = sym->rematiCode;
676 DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
677 if(IS_OP_POINTER(op)) {
678 DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
682 val += (int) operandLitValue(IC_RIGHT(ic));
683 } else if (ic->op == '-') {
684 val -= (int) operandLitValue(IC_RIGHT(ic));
688 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
691 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
692 aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
693 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
694 PCOI(aop->aopu.pcop)->index = val;
696 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
697 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
698 val, IS_PTR_CONST(operandType(op)));
700 // DEBUGpic14_emitcode(";","aop type %s",AopType(AOP_TYPE(IC_LEFT(ic))));
702 allocDirReg (IC_LEFT(ic));
707 int aopIdx (asmop *aop, int offset)
712 if(aop->type != AOP_REG)
715 return aop->aopu.aop_reg[offset]->rIdx;
718 /*-----------------------------------------------------------------*/
719 /* regsInCommon - two operands have some registers in common */
720 /*-----------------------------------------------------------------*/
721 static bool regsInCommon (operand *op1, operand *op2)
726 /* if they have registers in common */
727 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
730 sym1 = OP_SYMBOL(op1);
731 sym2 = OP_SYMBOL(op2);
733 if (sym1->nRegs == 0 || sym2->nRegs == 0)
736 for (i = 0 ; i < sym1->nRegs ; i++) {
741 for (j = 0 ; j < sym2->nRegs ;j++ ) {
745 if (sym2->regs[j] == sym1->regs[i])
753 /*-----------------------------------------------------------------*/
754 /* operandsEqu - equivalent */
755 /*-----------------------------------------------------------------*/
756 static bool operandsEqu ( operand *op1, operand *op2)
760 /* if they not symbols */
761 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
764 sym1 = OP_SYMBOL(op1);
765 sym2 = OP_SYMBOL(op2);
767 /* if both are itemps & one is spilt
768 and the other is not then false */
769 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
770 sym1->isspilt != sym2->isspilt )
773 /* if they are the same */
777 if (sym1->rname[0] && sym2->rname[0]
778 && strcmp (sym1->rname, sym2->rname) == 0)
782 /* if left is a tmp & right is not */
786 (sym1->usl.spillLoc == sym2))
793 (sym2->usl.spillLoc == sym1))
799 /*-----------------------------------------------------------------*/
800 /* pic14_sameRegs - two asmops have the same registers */
801 /*-----------------------------------------------------------------*/
802 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
809 if (aop1->type != AOP_REG ||
810 aop2->type != AOP_REG )
813 if (aop1->size != aop2->size )
816 for (i = 0 ; i < aop1->size ; i++ )
817 if (aop1->aopu.aop_reg[i] !=
818 aop2->aopu.aop_reg[i] )
824 /*-----------------------------------------------------------------*/
825 /* aopOp - allocates an asmop for an operand : */
826 /*-----------------------------------------------------------------*/
827 void aopOp (operand *op, iCode *ic, bool result)
836 /* if this a literal */
837 if (IS_OP_LITERAL(op)) {
838 op->aop = aop = newAsmop(AOP_LIT);
839 aop->aopu.aop_lit = op->operand.valOperand;
840 aop->size = getSize(operandType(op));
845 sym_link *type = operandType(op);
846 if(IS_PTR_CONST(type))
847 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
850 /* if already has a asmop then continue */
854 /* if the underlying symbol has a aop */
855 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
856 DEBUGpic14_emitcode(";","%d",__LINE__);
857 op->aop = OP_SYMBOL(op)->aop;
861 /* if this is a true symbol */
862 if (IS_TRUE_SYMOP(op)) {
863 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
864 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
868 /* this is a temporary : this has
874 e) can be a return use only */
879 /* if the type is a conditional */
880 if (sym->regType == REG_CND) {
881 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
886 /* if it is spilt then two situations
888 b) has a spill location */
889 if (sym->isspilt || sym->nRegs == 0) {
891 DEBUGpic14_emitcode(";","%d",__LINE__);
892 /* rematerialize it NOW */
895 sym->aop = op->aop = aop = aopForRemat (op);
896 aop->size = getSize(sym->type);
897 //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
902 /* WREG is not usable as an ordinary operand with PIC architecture,
903 * one might introduce a scratch register that can be used to make
904 * WREG accesible as an operand... disable WREG for now */
907 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
908 aop->size = getSize(sym->type);
909 for ( i = 0 ; i < 2 ; i++ )
910 aop->aopu.aop_str[i] = accUse[i];
911 DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
917 if(sym->isptr) { // && sym->uptr
918 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
919 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
921 //PCOI(aop->aopu.pcop)->_const = 0;
922 //PCOI(aop->aopu.pcop)->index = 0;
924 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
925 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
927 //allocDirReg (IC_LEFT(ic));
929 aop->size = getSize(sym->type);
930 DEBUGpic14_emitcode(";","%d",__LINE__);
937 aop = op->aop = sym->aop = newAsmop(AOP_STR);
938 aop->size = getSize(sym->type);
939 for ( i = 0 ; i < fReturnSizePic ; i++ )
940 aop->aopu.aop_str[i] = fReturn[i];
942 DEBUGpic14_emitcode(";","%d",__LINE__);
947 /* else spill location */
948 if (sym->usl.spillLoc)
950 asmop *oldAsmOp = NULL;
952 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
954 /* force a new aop if sizes differ */
955 oldAsmOp = sym->usl.spillLoc->aop;
956 sym->usl.spillLoc->aop = NULL;
958 DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
959 __FUNCTION__,__LINE__,
960 sym->usl.spillLoc->rname,
961 sym->rname, sym->usl.spillLoc->offset);
963 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
964 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
966 /* Don't reuse the new aop, go with the last one */
967 sym->usl.spillLoc->aop = oldAsmOp;
969 //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
970 aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname,
972 sym->usl.spillLoc->offset);
973 aop->size = getSize(sym->type);
980 sym_link *type = operandType(op);
981 if(IS_PTR_CONST(type))
982 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
985 /* must be in a register */
986 DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
987 sym->aop = op->aop = aop = newAsmop(AOP_REG);
988 aop->size = sym->nRegs;
989 for ( i = 0 ; i < sym->nRegs ;i++)
990 aop->aopu.aop_reg[i] = sym->regs[i];
993 /*-----------------------------------------------------------------*/
994 /* freeAsmop - free up the asmop given to an operand */
995 /*----------------------------------------------------------------*/
996 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1013 /* depending on the asmop type only three cases need work AOP_RO
1014 , AOP_R1 && AOP_STK */
1016 switch (aop->type) {
1020 pic14_emitcode ("pop","ar0");
1024 bitVectUnSetBit(ic->rUsed,R0_IDX);
1030 pic14_emitcode ("pop","ar1");
1034 bitVectUnSetBit(ic->rUsed,R1_IDX);
1040 int stk = aop->aopu.aop_stk + aop->size;
1041 bitVectUnSetBit(ic->rUsed,R0_IDX);
1042 bitVectUnSetBit(ic->rUsed,R1_IDX);
1044 getFreePtr(ic,&aop,FALSE);
1046 if (options.stack10bit)
1048 /* I'm not sure what to do here yet... */
1051 "*** Warning: probably generating bad code for "
1052 "10 bit stack mode.\n");
1056 pic14_emitcode ("mov","a,_bp");
1057 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1058 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1060 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1064 pic14_emitcode("pop","acc");
1065 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1067 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1070 freeAsmop(op,NULL,ic,TRUE);
1072 pic14_emitcode("pop","ar0");
1077 pic14_emitcode("pop","ar1");
1085 /* all other cases just dealloc */
1089 OP_SYMBOL(op)->aop = NULL;
1090 /* if the symbol has a spill */
1092 SPIL_LOC(op)->aop = NULL;
1097 /*-----------------------------------------------------------------*/
1098 /* aopGet - for fetching value of the aop */
1099 /*-----------------------------------------------------------------*/
1100 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1105 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1106 /* offset is greater than
1108 if (offset > (aop->size - 1) &&
1109 aop->type != AOP_LIT)
1112 /* depending on type */
1113 switch (aop->type) {
1117 DEBUGpic14_emitcode(";","%d",__LINE__);
1118 /* if we need to increment it */
1119 while (offset > aop->coff) {
1120 pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);
1124 while (offset < aop->coff) {
1125 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1129 aop->coff = offset ;
1131 pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1132 return (dname ? "acc" : "a");
1134 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1135 rs = Safe_calloc(1,strlen(s)+1);
1141 DEBUGpic14_emitcode(";","%d",__LINE__);
1142 if (aop->type == AOP_DPTR2)
1147 while (offset > aop->coff) {
1148 pic14_emitcode ("inc","dptr");
1152 while (offset < aop->coff) {
1153 pic14_emitcode("lcall","__decdptr");
1159 pic14_emitcode("clr","a");
1160 pic14_emitcode("movc","a,@a+dptr");
1163 pic14_emitcode("movx","a,@dptr");
1166 if (aop->type == AOP_DPTR2)
1171 return (dname ? "acc" : "a");
1176 sprintf (s,"%s",aop->aopu.aop_immd);
1179 sprintf(s,"(%s >> %d)",
1184 aop->aopu.aop_immd);
1185 DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1186 rs = Safe_calloc(1,strlen(s)+1);
1192 sprintf(s,"(%s + %d)",
1195 DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1197 sprintf(s,"%s",aop->aopu.aop_dir);
1198 rs = Safe_calloc(1,strlen(s)+1);
1204 // return aop->aopu.aop_reg[offset]->dname;
1206 return aop->aopu.aop_reg[offset]->name;
1209 //pic14_emitcode(";","%d",__LINE__);
1210 return aop->aopu.aop_dir;
1213 DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1214 return "AOP_accumulator_bug";
1217 sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1218 rs = Safe_calloc(1,strlen(s)+1);
1223 aop->coff = offset ;
1224 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1227 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1229 return aop->aopu.aop_str[offset];
1233 pCodeOp *pcop = aop->aopu.pcop;
1234 DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1237 DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
1238 sprintf(s,"(%s+%d)", pcop->name,offset);
1240 DEBUGpic14_emitcode(";","%s",pcop->name);
1241 sprintf(s,"%s", pcop->name);
1244 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1247 rs = Safe_calloc(1,strlen(s)+1);
1253 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1254 "aopget got unsupported aop->type");
1259 /*-----------------------------------------------------------------*/
1260 /* popGetTempReg - create a new temporary pCodeOp */
1261 /*-----------------------------------------------------------------*/
1262 pCodeOp *popGetTempReg(void)
1267 pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1268 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1269 PCOR(pcop)->r->wasUsed=1;
1270 PCOR(pcop)->r->isFree=0;
1276 /*-----------------------------------------------------------------*/
1277 /* popReleaseTempReg - create a new temporary pCodeOp */
1278 /*-----------------------------------------------------------------*/
1279 void popReleaseTempReg(pCodeOp *pcop)
1282 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1283 PCOR(pcop)->r->isFree = 1;
1286 /*-----------------------------------------------------------------*/
1287 /* popGetLabel - create a new pCodeOp of type PO_LABEL */
1288 /*-----------------------------------------------------------------*/
1289 pCodeOp *popGetLabel(unsigned int key)
1292 DEBUGpic14_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1294 if(key>(unsigned int)max_key)
1297 return newpCodeOpLabel(NULL,key+100+labelOffset);
1300 /*-------------------------------------------------------------------*/
1301 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1302 /*-------------------------------------------------------------------*/
1303 pCodeOp *popGetHighLabel(unsigned int key)
1306 pcop = popGetLabel(key);
1307 PCOLAB(pcop)->offset = 1;
1311 /*-----------------------------------------------------------------*/
1312 /* popGetLit - asm operator to pcode operator conversion */
1313 /*-----------------------------------------------------------------*/
1314 pCodeOp *popGetLit(unsigned int lit)
1317 return newpCodeOpLit((unsigned char)lit);
1320 /*-----------------------------------------------------------------*/
1321 /* popGetImmd - asm operator to pcode immediate conversion */
1322 /*-----------------------------------------------------------------*/
1323 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1326 return newpCodeOpImmd(name, offset,index, 0, is_func);
1329 extern set *externs;
1331 /*-----------------------------------------------------------------*/
1332 /* popGetWithString - asm operator to pcode operator conversion */
1333 /*-----------------------------------------------------------------*/
1334 pCodeOp *popGetWithString(char *str, int isExtern)
1340 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1344 pcop = newpCodeOp(str,PO_STR);
1345 PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1350 pCodeOp *popGetExternal (char *str)
1352 pCodeOp *pcop = popGetWithString (str, 1);
1358 for (sym = setFirstItem (externs); !found && sym; sym = setNextItem (externs))
1360 if (!strcmp (str, sym->rname))
1366 sym = newSymbol(str, 0);
1367 strncpy(sym->rname, str, SDCC_NAME_MAX);
1368 addSet (&externs, sym);
1374 /*-----------------------------------------------------------------*/
1375 /* popRegFromString - */
1376 /*-----------------------------------------------------------------*/
1377 pCodeOp *popRegFromString(char *str, int size, int offset)
1380 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1381 pcop->type = PO_DIR;
1383 DEBUGpic14_emitcode(";","%d",__LINE__);
1388 pcop->name = Safe_calloc(1,strlen(str)+1);
1389 strcpy(pcop->name,str);
1391 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1393 PCOR(pcop)->r = dirregWithName(pcop->name);
1394 if(PCOR(pcop)->r == NULL) {
1395 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1396 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1397 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1399 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1401 PCOR(pcop)->instance = offset;
1406 /*-----------------------------------------------------------------*/
1407 /*-----------------------------------------------------------------*/
1408 pCodeOp *popRegFromIdx(int rIdx)
1412 DEBUGpic14_emitcode ("; ***","%s,%d , rIdx=0x%x",
1413 __FUNCTION__,__LINE__,rIdx);
1415 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1417 PCOR(pcop)->rIdx = rIdx;
1418 PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1419 PCOR(pcop)->r->isFree = 0;
1420 PCOR(pcop)->r->wasUsed = 1;
1422 pcop->type = PCOR(pcop)->r->pc_type;
1428 /*-----------------------------------------------------------------*/
1429 /* popGet - asm operator to pcode operator conversion */
1430 /*-----------------------------------------------------------------*/
1431 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1433 //char *s = buffer ;
1438 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1439 /* offset is greater than
1444 /* XXX: still needed for BIT operands (AOP_CRY) */
1445 if (offset > (aop->size - 1) &&
1446 aop->type != AOP_LIT)
1447 return NULL; //zero;
1449 /* depending on type */
1450 switch (aop->type) {
1457 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1461 DEBUGpic14_emitcode(";","%d",__LINE__);
1462 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1465 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1467 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1468 pcop->type = PO_DIR;
1470 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1471 strcpy(pcop->name,aop->aopu.aop_dir);
1472 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1473 if(PCOR(pcop)->r == NULL) {
1474 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1475 PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1476 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1478 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1480 PCOR(pcop)->instance = offset;
1488 assert (offset < aop->size);
1489 rIdx = aop->aopu.aop_reg[offset]->rIdx;
1491 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1492 PCOR(pcop)->rIdx = rIdx;
1493 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1494 PCOR(pcop)->r->wasUsed=1;
1495 PCOR(pcop)->r->isFree=0;
1497 PCOR(pcop)->instance = offset;
1498 pcop->type = PCOR(pcop)->r->pc_type;
1499 //rs = aop->aopu.aop_reg[offset]->name;
1500 DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1505 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1506 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1507 //if(PCOR(pcop)->r == NULL)
1508 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1512 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1515 DEBUGpic14_emitcode(";","%d %s",__LINE__,aop->aopu.aop_str[offset]);
1516 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1518 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1519 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1520 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1521 pcop->type = PCOR(pcop)->r->pc_type;
1522 pcop->name = PCOR(pcop)->r->name;
1529 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1531 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1532 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1533 switch (aop->aopu.pcop->type)
1536 pcop = pCodeOpCopy (aop->aopu.pcop);
1537 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1538 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1539 PCOI(pcop)->index += offset;
1540 //PCOI(pcop)->offset = 0;
1543 pcop = pCodeOpCopy (aop->aopu.pcop);
1544 PCOR(pcop)->instance = offset;
1547 assert ( !"unhandled pCode type" );
1553 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1554 "popGet got unsupported aop->type");
1558 /*-----------------------------------------------------------------*/
1559 /* popGetAddr - access the low/high word of a symbol (immediate) */
1560 /* (for non-PO_IMMEDIATEs this is the same as popGet) */
1561 /*-----------------------------------------------------------------*/
1562 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1564 if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1566 pCodeOp *pcop = aop->aopu.pcop;
1567 assert (offset <= GPTRSIZE);
1569 /* special case: index >= 2 should return GPOINTER-style values */
1572 pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1576 pcop = pCodeOpCopy (pcop);
1577 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1578 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1579 PCOI(pcop)->offset += offset;
1580 PCOI(pcop)->index += index;
1581 //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);
1584 return popGet (aop, offset + index);
1588 /*-----------------------------------------------------------------*/
1589 /* aopPut - puts a string for a aop */
1590 /*-----------------------------------------------------------------*/
1591 void aopPut (asmop *aop, char *s, int offset)
1596 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1598 if (aop->size && offset > ( aop->size - 1)) {
1599 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1600 "aopPut got offset > aop->size");
1604 /* will assign value to value */
1605 /* depending on where it is ofcourse */
1606 switch (aop->type) {
1609 sprintf(d,"(%s + %d)",
1610 aop->aopu.aop_dir,offset);
1611 fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1614 sprintf(d,"%s",aop->aopu.aop_dir);
1617 DEBUGpic14_emitcode(";","%d",__LINE__);
1619 pic14_emitcode("movf","%s,w",s);
1620 pic14_emitcode("movwf","%s",d);
1623 pic14_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
1624 if(offset >= aop->size) {
1625 emitpcode(POC_CLRF,popGet(aop,offset));
1628 emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
1631 emitpcode(POC_MOVWF,popGet(aop,offset));
1637 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1638 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1641 strcmp(s,"r0") == 0 ||
1642 strcmp(s,"r1") == 0 ||
1643 strcmp(s,"r2") == 0 ||
1644 strcmp(s,"r3") == 0 ||
1645 strcmp(s,"r4") == 0 ||
1646 strcmp(s,"r5") == 0 ||
1647 strcmp(s,"r6") == 0 ||
1648 strcmp(s,"r7") == 0 )
1649 pic14_emitcode("mov","%s,%s ; %d",
1650 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1654 if(strcmp(s,"W")==0 )
1655 pic14_emitcode("movf","%s,w ; %d",s,__LINE__);
1657 pic14_emitcode("movwf","%s",
1658 aop->aopu.aop_reg[offset]->name);
1660 if(strcmp(s,zero)==0) {
1661 emitpcode(POC_CLRF,popGet(aop,offset));
1663 } else if(strcmp(s,"W")==0) {
1664 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1665 pcop->type = PO_GPR_REGISTER;
1667 PCOR(pcop)->rIdx = -1;
1668 PCOR(pcop)->r = NULL;
1670 DEBUGpic14_emitcode(";","%d",__LINE__);
1671 pcop->name = Safe_strdup(s);
1672 emitpcode(POC_MOVFW,pcop);
1673 emitpcode(POC_MOVWF,popGet(aop,offset));
1674 } else if(strcmp(s,one)==0) {
1675 emitpcode(POC_CLRF,popGet(aop,offset));
1676 emitpcode(POC_INCF,popGet(aop,offset));
1678 emitpcode(POC_MOVWF,popGet(aop,offset));
1686 if (aop->type == AOP_DPTR2)
1692 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1693 "aopPut writting to code space");
1697 while (offset > aop->coff) {
1699 pic14_emitcode ("inc","dptr");
1702 while (offset < aop->coff) {
1704 pic14_emitcode("lcall","__decdptr");
1709 /* if not in accumulater */
1712 pic14_emitcode ("movx","@dptr,a");
1714 if (aop->type == AOP_DPTR2)
1722 while (offset > aop->coff) {
1724 pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1726 while (offset < aop->coff) {
1728 pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1734 pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1739 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1741 if (strcmp(s,"r0") == 0 ||
1742 strcmp(s,"r1") == 0 ||
1743 strcmp(s,"r2") == 0 ||
1744 strcmp(s,"r3") == 0 ||
1745 strcmp(s,"r4") == 0 ||
1746 strcmp(s,"r5") == 0 ||
1747 strcmp(s,"r6") == 0 ||
1748 strcmp(s,"r7") == 0 ) {
1750 sprintf(buffer,"a%s",s);
1751 pic14_emitcode("mov","@%s,%s",
1752 aop->aopu.aop_ptr->name,buffer);
1754 pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1759 if (strcmp(s,"a") == 0)
1760 pic14_emitcode("push","acc");
1762 pic14_emitcode("push","%s",s);
1767 /* if bit variable */
1768 if (!aop->aopu.aop_dir) {
1769 pic14_emitcode("clr","a");
1770 pic14_emitcode("rlc","a");
1773 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1776 pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1779 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1781 lbl = newiTempLabel(NULL);
1783 if (strcmp(s,"a")) {
1786 pic14_emitcode("clr","c");
1787 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1788 pic14_emitcode("cpl","c");
1789 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1790 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1797 if (strcmp(aop->aopu.aop_str[offset],s))
1798 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1803 if (!offset && (strcmp(s,"acc") == 0))
1806 if (strcmp(aop->aopu.aop_str[offset],s))
1807 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1811 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1812 "aopPut got unsupported aop->type");
1818 /*-----------------------------------------------------------------*/
1819 /* mov2w_op - generate either a MOVLW or MOVFW based operand type */
1820 /*-----------------------------------------------------------------*/
1821 static void mov2w_op (operand *op, int offset)
1826 /* for PO_IMMEDIATEs: use address or value? */
1827 if (op_isLitLike (op))
1829 /* access address of op */
1830 if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
1831 if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
1833 if (offset == GPTRSIZE-1)
1834 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1836 emitpcode (POC_MOVLW, popGetLit (0));
1839 emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
1841 /* access value stored in op */
1842 mov2w (AOP(op), offset);
1847 /*-----------------------------------------------------------------*/
1848 /* mov2w - generate either a MOVLW or MOVFW based operand type */
1849 /*-----------------------------------------------------------------*/
1850 void mov2w (asmop *aop, int offset)
1856 DEBUGpic14_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
1858 if ( aop_isLitLike (aop) )
1859 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1861 emitpcode(POC_MOVFW,popGet(aop,offset));
1865 static void movwf (asmop *op, int offset)
1867 emitpcode (POC_MOVWF, popGet(op, offset));
1870 static pCodeOp *get_argument_pcop (int idx)
1872 assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1873 return popRegFromIdx (Gstack_base_addr - (idx - 1));
1876 static pCodeOp *get_return_val_pcop (int offset)
1878 assert (offset > 0 && "the most significant byte is returned via WREG");
1879 return popRegFromIdx (Gstack_base_addr - (offset - 1));
1882 static void pass_argument (operand *op, int offset, int idx)
1885 mov2w_op (op, offset);
1887 emitpcode(POC_MOVWF, get_argument_pcop (idx));
1890 static void get_returnvalue (operand *op, int offset, int idx)
1893 emitpcode(POC_MOVFW, get_return_val_pcop (idx));
1894 movwf(AOP(op), offset);
1897 static void call_libraryfunc (char *name)
1899 /* library code might reside in different page... */
1900 emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1901 /* call the library function */
1902 emitpcode (POC_CALL, popGetExternal (name));
1903 /* might return from different page... */
1904 emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1907 /*-----------------------------------------------------------------*/
1908 /* reAdjustPreg - points a register back to where it should */
1909 /*-----------------------------------------------------------------*/
1910 static void reAdjustPreg (asmop *aop)
1914 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1916 if ((size = aop->size) <= 1)
1919 switch (aop->type) {
1923 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1927 if (aop->type == AOP_DPTR2)
1933 pic14_emitcode("lcall","__decdptr");
1936 if (aop->type == AOP_DPTR2)
1949 /*-----------------------------------------------------------------*/
1950 /* opIsGptr: returns non-zero if the passed operand is */
1951 /* a generic pointer type. */
1952 /*-----------------------------------------------------------------*/
1953 static int opIsGptr(operand *op)
1955 sym_link *type = operandType(op);
1957 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1958 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1966 /*-----------------------------------------------------------------*/
1967 /* pic14_getDataSize - get the operand data size */
1968 /*-----------------------------------------------------------------*/
1969 int pic14_getDataSize(operand *op)
1973 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1976 size = getSize(OP_SYM_ETYPE(op));
1978 //return AOP_SIZE(op);
1980 // tsd- in the pic port, the genptr size is 1, so this code here
1981 // fails. ( in the 8051 port, the size was 4).
1983 size = AOP_SIZE(op);
1984 if (IS_GENPTR(OP_SYM_TYPE(op)))
1986 sym_link *type = operandType(op);
1987 if (IS_GENPTR(type))
1989 /* generic pointer; arithmetic operations
1990 * should ignore the high byte (pointer type).
1993 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2000 /*-----------------------------------------------------------------*/
2001 /* pic14_outAcc - output Acc */
2002 /*-----------------------------------------------------------------*/
2003 void pic14_outAcc(operand *result)
2006 DEBUGpic14_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2007 DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
2010 size = pic14_getDataSize(result);
2012 emitpcode(POC_MOVWF,popGet(AOP(result),0));
2015 /* unsigned or positive */
2017 emitpcode(POC_CLRF,popGet(AOP(result),offset++));
2022 /*-----------------------------------------------------------------*/
2023 /* pic14_outBitC - output a bit C */
2024 /*-----------------------------------------------------------------*/
2025 void pic14_outBitC(operand *result)
2028 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2029 /* if the result is bit */
2030 if (AOP_TYPE(result) == AOP_CRY)
2031 aopPut(AOP(result),"c",0);
2033 pic14_emitcode("clr","a ; %d", __LINE__);
2034 pic14_emitcode("rlc","a");
2035 pic14_outAcc(result);
2039 /*-----------------------------------------------------------------*/
2040 /* pic14_toBoolean - emit code for orl a,operator(sizeop) */
2041 /*-----------------------------------------------------------------*/
2042 void pic14_toBoolean(operand *oper)
2044 int size = AOP_SIZE(oper);
2047 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2052 /* MOVFW does not load the flags... */
2053 if (AOP_TYPE(oper) == AOP_ACC) {
2054 emitpcode(POC_IORLW, popGetLit(0));
2057 emitpcode(POC_MOVLW, popGetLit(0));
2061 if ( AOP_TYPE(oper) != AOP_ACC) {
2062 emitpcode(POC_MOVFW,popGet(AOP(oper),0));
2067 while (offset < size) {
2068 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
2070 /* Z is set iff (oper == 0) */
2074 /*-----------------------------------------------------------------*/
2075 /* genNot - generate code for ! operation */
2076 /*-----------------------------------------------------------------*/
2077 static void genNot (iCode *ic)
2084 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2085 /* assign asmOps to operand & result */
2086 aopOp (IC_LEFT(ic),ic,FALSE);
2087 aopOp (IC_RESULT(ic),ic,TRUE);
2089 DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2090 /* if in bit space then a special case */
2091 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2092 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2093 emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
2094 emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
2096 emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
2097 emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
2098 emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
2103 size = AOP_SIZE(IC_LEFT(ic));
2104 mov2w (AOP(IC_LEFT(ic)),0);
2107 if (op_isLitLike (IC_LEFT(ic)))
2108 emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
2110 emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
2112 emitpcode(POC_MOVLW, popGetLit (0));
2114 emitpcode(POC_MOVLW, popGetLit (1));
2115 movwf(AOP(IC_RESULT(ic)), 0);
2117 for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
2119 emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
2124 /* release the aops */
2125 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2126 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2130 /*-----------------------------------------------------------------*/
2131 /* genCpl - generate code for complement */
2132 /*-----------------------------------------------------------------*/
2133 static void genCpl (iCode *ic)
2135 operand *left, *result;
2140 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2141 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2142 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2144 /* if both are in bit space then
2146 if (AOP_TYPE(result) == AOP_CRY &&
2147 AOP_TYPE(left) == AOP_CRY ) {
2149 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir);
2150 pic14_emitcode("cpl","c");
2151 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir);
2155 size = AOP_SIZE(result);
2156 if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
2159 if(AOP_TYPE(left) == AOP_ACC)
2160 emitpcode(POC_XORLW, popGetLit(0xff));
2162 emitpcode(POC_COMFW,popGet(AOP(left),offset));
2164 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
2167 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2171 /* release the aops */
2172 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2173 freeAsmop(result,NULL,ic,TRUE);
2176 /*-----------------------------------------------------------------*/
2177 /* genUminusFloat - unary minus for floating points */
2178 /*-----------------------------------------------------------------*/
2179 static void genUminusFloat(operand *op,operand *result)
2181 int size ,offset =0 ;
2186 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2187 /* for this we just need to flip the
2188 first it then copy the rest in place */
2189 size = AOP_SIZE(op) - 1;
2190 l = aopGet(AOP(op),3,FALSE,FALSE);
2194 pic14_emitcode("cpl","acc.7");
2195 aopPut(AOP(result),"a",3);
2199 aopGet(AOP(op),offset,FALSE,FALSE),
2205 /*-----------------------------------------------------------------*/
2206 /* genUminus - unary minus code generation */
2207 /*-----------------------------------------------------------------*/
2208 static void genUminus (iCode *ic)
2211 sym_link *optype, *rtype;
2215 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2217 aopOp(IC_LEFT(ic),ic,FALSE);
2218 aopOp(IC_RESULT(ic),ic,TRUE);
2220 /* if both in bit space then special
2222 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2223 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2225 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0));
2226 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2227 emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0));
2232 optype = operandType(IC_LEFT(ic));
2233 rtype = operandType(IC_RESULT(ic));
2235 /* if float then do float stuff */
2236 if (IS_FLOAT(optype)) {
2237 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2241 /* otherwise subtract from zero by taking the 2's complement */
2242 size = AOP_SIZE(IC_LEFT(ic));
2244 for(i=0; i<size; i++) {
2245 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2246 emitpcode(POC_COMF, popGet(AOP(IC_LEFT(ic)),i));
2248 emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2249 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2253 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0));
2254 for(i=1; i<size; i++) {
2256 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),i));
2260 /* release the aops */
2261 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2262 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2265 /*-----------------------------------------------------------------*/
2266 /* saveRegisters - will look for a call and save the registers */
2267 /*-----------------------------------------------------------------*/
2268 static void saveRegisters(iCode *lic)
2277 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2279 for (ic = lic ; ic ; ic = ic->next)
2280 if (ic->op == CALL || ic->op == PCALL)
2284 fprintf(stderr,"found parameter push with no function call\n");
2288 /* if the registers have been saved already then
2290 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2293 /* find the registers in use at this time
2294 and push them away to safety */
2295 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2299 if (options.useXstack) {
2300 if (bitVectBitValue(rsave,R0_IDX))
2301 pic14_emitcode("mov","b,r0");
2302 pic14_emitcode("mov","r0,%s",spname);
2303 for (i = 0 ; i < pic14_nRegs ; i++) {
2304 if (bitVectBitValue(rsave,i)) {
2306 pic14_emitcode("mov","a,b");
2308 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2309 pic14_emitcode("movx","@r0,a");
2310 pic14_emitcode("inc","r0");
2313 pic14_emitcode("mov","%s,r0",spname);
2314 if (bitVectBitValue(rsave,R0_IDX))
2315 pic14_emitcode("mov","r0,b");
2317 //for (i = 0 ; i < pic14_nRegs ; i++) {
2318 // if (bitVectBitValue(rsave,i))
2319 // pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2322 dtype = operandType(IC_LEFT(ic));
2323 if (currFunc && dtype &&
2324 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2325 IFFUNC_ISISR(currFunc->type) &&
2328 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2331 /*-----------------------------------------------------------------*/
2332 /* unsaveRegisters - pop the pushed registers */
2333 /*-----------------------------------------------------------------*/
2334 static void unsaveRegisters (iCode *ic)
2341 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2342 /* find the registers in use at this time
2343 and push them away to safety */
2344 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2347 if (options.useXstack) {
2348 pic14_emitcode("mov","r0,%s",spname);
2349 for (i = pic14_nRegs ; i >= 0 ; i--) {
2350 if (bitVectBitValue(rsave,i)) {
2351 pic14_emitcode("dec","r0");
2352 pic14_emitcode("movx","a,@r0");
2354 pic14_emitcode("mov","b,a");
2356 pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2360 pic14_emitcode("mov","%s,r0",spname);
2361 if (bitVectBitValue(rsave,R0_IDX))
2362 pic14_emitcode("mov","r0,b");
2364 //for (i = pic14_nRegs ; i >= 0 ; i--) {
2365 // if (bitVectBitValue(rsave,i))
2366 // pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2372 /*-----------------------------------------------------------------*/
2374 /*-----------------------------------------------------------------*/
2375 static void pushSide(operand * oper, int size)
2379 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2381 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2382 if (AOP_TYPE(oper) != AOP_REG &&
2383 AOP_TYPE(oper) != AOP_DIR &&
2385 pic14_emitcode("mov","a,%s",l);
2386 pic14_emitcode("push","acc");
2388 pic14_emitcode("push","%s",l);
2393 /*-----------------------------------------------------------------*/
2394 /* assignResultValue - */
2395 /*-----------------------------------------------------------------*/
2396 static void assignResultValue(operand * oper)
2398 int size = AOP_SIZE(oper);
2403 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2405 DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2407 /* assign MSB first (passed via WREG) */
2409 get_returnvalue (oper, size, offset + GpsuedoStkPtr);
2415 /*-----------------------------------------------------------------*/
2416 /* genIpush - genrate code for pushing this gets a little complex */
2417 /*-----------------------------------------------------------------*/
2418 static void genIpush (iCode *ic)
2422 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2424 int size, offset = 0 ;
2428 /* if this is not a parm push : ie. it is spill push
2429 and spill push is always done on the local stack */
2430 if (!ic->parmPush) {
2432 /* and the item is spilt then do nothing */
2433 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2436 aopOp(IC_LEFT(ic),ic,FALSE);
2437 size = AOP_SIZE(IC_LEFT(ic));
2438 /* push it on the stack */
2440 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2445 pic14_emitcode("push","%s",l);
2450 /* this is a paramter push: in this case we call
2451 the routine to find the call and save those
2452 registers that need to be saved */
2455 /* then do the push */
2456 aopOp(IC_LEFT(ic),ic,FALSE);
2459 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2460 size = AOP_SIZE(IC_LEFT(ic));
2463 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2464 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
2465 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2467 pic14_emitcode("mov","a,%s",l);
2468 pic14_emitcode("push","acc");
2470 pic14_emitcode("push","%s",l);
2473 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2477 /*-----------------------------------------------------------------*/
2478 /* genIpop - recover the registers: can happen only for spilling */
2479 /*-----------------------------------------------------------------*/
2480 static void genIpop (iCode *ic)
2484 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2485 assert (!"genIpop -- unimplemented");
2490 /* if the temp was not pushed then */
2491 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2494 aopOp(IC_LEFT(ic),ic,FALSE);
2495 size = AOP_SIZE(IC_LEFT(ic));
2498 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2501 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2505 /*-----------------------------------------------------------------*/
2506 /* unsaverbank - restores the resgister bank from stack */
2507 /*-----------------------------------------------------------------*/
2508 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2512 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2518 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2520 if (options.useXstack) {
2522 r = getFreePtr(ic,&aop,FALSE);
2525 pic14_emitcode("mov","%s,_spx",r->name);
2526 pic14_emitcode("movx","a,@%s",r->name);
2527 pic14_emitcode("mov","psw,a");
2528 pic14_emitcode("dec","%s",r->name);
2531 pic14_emitcode ("pop","psw");
2534 for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2535 if (options.useXstack) {
2536 pic14_emitcode("movx","a,@%s",r->name);
2537 //pic14_emitcode("mov","(%s+%d),a",
2538 // regspic14[i].base,8*bank+regspic14[i].offset);
2539 pic14_emitcode("dec","%s",r->name);
2542 pic14_emitcode("pop",""); //"(%s+%d)",
2543 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2546 if (options.useXstack) {
2548 pic14_emitcode("mov","_spx,%s",r->name);
2549 freeAsmop(NULL,aop,ic,TRUE);
2555 /*-----------------------------------------------------------------*/
2556 /* saverbank - saves an entire register bank on the stack */
2557 /*-----------------------------------------------------------------*/
2558 static void saverbank (int bank, iCode *ic, bool pushPsw)
2562 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2568 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2569 if (options.useXstack) {
2572 r = getFreePtr(ic,&aop,FALSE);
2573 pic14_emitcode("mov","%s,_spx",r->name);
2577 for (i = 0 ; i < pic14_nRegs ;i++) {
2578 if (options.useXstack) {
2579 pic14_emitcode("inc","%s",r->name);
2580 //pic14_emitcode("mov","a,(%s+%d)",
2581 // regspic14[i].base,8*bank+regspic14[i].offset);
2582 pic14_emitcode("movx","@%s,a",r->name);
2584 pic14_emitcode("push","");// "(%s+%d)",
2585 //regspic14[i].base,8*bank+regspic14[i].offset);
2589 if (options.useXstack) {
2590 pic14_emitcode("mov","a,psw");
2591 pic14_emitcode("movx","@%s,a",r->name);
2592 pic14_emitcode("inc","%s",r->name);
2593 pic14_emitcode("mov","_spx,%s",r->name);
2594 freeAsmop (NULL,aop,ic,TRUE);
2597 pic14_emitcode("push","psw");
2599 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2605 /*-----------------------------------------------------------------*/
2606 /* genCall - generates a call statement */
2607 /*-----------------------------------------------------------------*/
2608 static void genCall (iCode *ic)
2617 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2619 /* if caller saves & we have not saved then */
2623 /* if we are calling a function that is not using
2624 the same register bank then we need to save the
2625 destination registers on the stack */
2626 dtype = operandType(IC_LEFT(ic));
2627 if (currFunc && dtype &&
2628 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2629 IFFUNC_ISISR(currFunc->type) &&
2632 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2634 /* if send set is not empty the assign */
2637 /* For the Pic port, there is no data stack.
2638 * So parameters passed to functions are stored
2639 * in registers. (The pCode optimizer will get
2640 * rid of most of these :).
2642 int psuedoStkPtr=-1;
2643 int firstTimeThruLoop = 1;
2645 _G.sendSet = reverseSet(_G.sendSet);
2647 /* First figure how many parameters are getting passed */
2648 for (sic = setFirstItem(_G.sendSet) ; sic ;
2649 sic = setNextItem(_G.sendSet)) {
2651 aopOp(IC_LEFT(sic),sic,FALSE);
2652 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2653 freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2656 for (sic = setFirstItem(_G.sendSet) ; sic ;
2657 sic = setNextItem(_G.sendSet)) {
2658 int size, offset = 0;
2660 aopOp(IC_LEFT(sic),sic,FALSE);
2661 size = AOP_SIZE(IC_LEFT(sic));
2664 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2665 AopType(AOP_TYPE(IC_LEFT(sic))));
2667 if(!firstTimeThruLoop) {
2668 /* If this is not the first time we've been through the loop
2669 * then we need to save the parameter in a temporary
2670 * register. The last byte of the last parameter is
2672 emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2675 firstTimeThruLoop=0;
2677 mov2w_op (IC_LEFT(sic), offset);
2680 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2685 sym = OP_SYMBOL(IC_LEFT(ic));
2686 name = sym->rname[0] ? sym->rname : sym->name;
2687 isExtern = IS_EXTERN(sym->etype);
2689 emitpcode(POC_PAGESEL,popGetWithString(name,1)); /* Extern functions maybe on another page - must call pagesel */
2691 emitpcode(POC_CALL,popGetWithString(name,isExtern));
2693 emitpcode(POC_PAGESEL,popGetWithString("$",0)); /* May have returned from another page - must call pagesel to restore PCLATH before next goto or call instruction */
2696 /* if we need assign a result value */
2697 if ((IS_ITEMP(IC_RESULT(ic)) &&
2698 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2699 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2700 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2703 aopOp(IC_RESULT(ic),ic,FALSE);
2706 assignResultValue(IC_RESULT(ic));
2708 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2709 AopType(AOP_TYPE(IC_RESULT(ic))));
2711 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2714 /* if register bank was saved then pop them */
2716 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2718 /* if we hade saved some registers then unsave them */
2719 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2720 unsaveRegisters (ic);
2725 /*-----------------------------------------------------------------*/
2726 /* genPcall - generates a call by pointer statement */
2727 /*-----------------------------------------------------------------*/
2728 static void genPcall (iCode *ic)
2731 symbol *albl = newiTempLabel(NULL);
2732 symbol *blbl = newiTempLabel(NULL);
2739 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2740 /* if caller saves & we have not saved then */
2744 /* if we are calling a function that is not using
2745 the same register bank then we need to save the
2746 destination registers on the stack */
2747 dtype = operandType(IC_LEFT(ic));
2748 if (currFunc && dtype &&
2749 IFFUNC_ISISR(currFunc->type) &&
2750 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2751 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2754 aopOp(left,ic,FALSE);
2755 DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2757 poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2759 pushSide(IC_LEFT(ic), FPTRSIZE);
2761 /* if send set is not empty, assign parameters */
2764 DEBUGpic14_emitcode ("; ***","%s %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2765 /* no way to pass args - W always gets used to make the call */
2767 /* first idea - factor out a common helper function and call it.
2768 But don't know how to get it generated only once in its own block
2770 if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2773 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2774 DEBUGpic14_emitcode ("; ***","%s %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2775 buffer = Safe_calloc(1,strlen(rname)+16);
2776 sprintf(buffer, "%s_goto_helper", rname);
2777 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2781 emitpcode(POC_CALL,popGetLabel(albl->key));
2782 pcop = popGetLabel(blbl->key);
2783 emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
2784 emitpcode(POC_GOTO,pcop);
2785 emitpLabel(albl->key);
2787 emitpcode(poc,popGetAddr(AOP(left),1,0));
2788 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2789 emitpcode(poc,popGetAddr(AOP(left),0,0));
2790 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2792 emitpLabel(blbl->key);
2794 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2796 /* if we need to assign a result value */
2797 if ((IS_ITEMP(IC_RESULT(ic)) &&
2798 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2799 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2800 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2803 aopOp(IC_RESULT(ic),ic,FALSE);
2808 assignResultValue(IC_RESULT(ic));
2810 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2813 /* if register bank was saved then unsave them */
2814 if (currFunc && dtype &&
2815 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2816 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2818 /* if we hade saved some registers then
2821 unsaveRegisters (ic);
2825 /*-----------------------------------------------------------------*/
2826 /* resultRemat - result is rematerializable */
2827 /*-----------------------------------------------------------------*/
2828 static int resultRemat (iCode *ic)
2830 // DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2833 if (SKIP_IC(ic) || ic->op == IFX)
2836 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2837 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2838 if (sym->remat && !POINTER_SET(ic))
2845 #if defined(__BORLANDC__) || defined(_MSC_VER)
2846 #define STRCASECMP stricmp
2848 #define STRCASECMP strcasecmp
2852 /*-----------------------------------------------------------------*/
2853 /* inExcludeList - return 1 if the string is in exclude Reg list */
2854 /*-----------------------------------------------------------------*/
2855 static bool inExcludeList(char *s)
2857 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2860 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2861 if (options.excludeRegs[i] &&
2862 STRCASECMP(options.excludeRegs[i],"none") == 0)
2865 for ( i = 0 ; options.excludeRegs[i]; i++) {
2866 if (options.excludeRegs[i] &&
2867 STRCASECMP(s,options.excludeRegs[i]) == 0)
2874 /*-----------------------------------------------------------------*/
2875 /* genFunction - generated code for function entry */
2876 /*-----------------------------------------------------------------*/
2877 static void genFunction (iCode *ic)
2884 DEBUGpic14_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2886 labelOffset += (max_key+4);
2890 /* create the function header */
2891 pic14_emitcode(";","-----------------------------------------");
2892 pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2893 pic14_emitcode(";","-----------------------------------------");
2895 pic14_emitcode("","%s:",sym->rname);
2896 addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2898 ftype = operandType(IC_LEFT(ic));
2900 /* if critical function then turn interrupts off */
2901 if (IFFUNC_ISCRITICAL(ftype))
2902 pic14_emitcode("clr","ea");
2904 /* here we need to generate the equates for the
2905 register bank if required */
2907 if (FUNC_REGBANK(ftype) != rbank) {
2910 rbank = FUNC_REGBANK(ftype);
2911 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2912 if (strcmp(regspic14[i].base,"0") == 0)
2913 pic14_emitcode("","%s = 0x%02x",
2915 8*rbank+regspic14[i].offset);
2917 pic14_emitcode ("","%s = %s + 0x%02x",
2920 8*rbank+regspic14[i].offset);
2925 /* if this is an interrupt service routine */
2926 if (IFFUNC_ISISR(sym->type)) {
2927 /* already done in pic14createInterruptVect() - delete me
2928 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2929 emitpcodeNULLop(POC_NOP);
2930 emitpcodeNULLop(POC_NOP);
2931 emitpcodeNULLop(POC_NOP);
2933 emitpcode(POC_MOVWF, popCopyReg(&pc_wsave));
2934 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2935 emitpcode(POC_CLRF, popCopyReg(&pc_status));
2936 emitpcode(POC_MOVWF, popCopyReg(&pc_ssave));
2937 emitpcode(POC_MOVFW, popCopyReg(&pc_pclath));
2938 emitpcode(POC_MOVWF, popCopyReg(&pc_psave));
2939 emitpcode(POC_CLRF, popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2941 pBlockConvert2ISR(pb);
2942 pic14_hasInterrupt = 1;
2944 if (!inExcludeList("acc"))
2945 pic14_emitcode ("push","acc");
2946 if (!inExcludeList("b"))
2947 pic14_emitcode ("push","b");
2948 if (!inExcludeList("dpl"))
2949 pic14_emitcode ("push","dpl");
2950 if (!inExcludeList("dph"))
2951 pic14_emitcode ("push","dph");
2952 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2954 pic14_emitcode ("push", "dpx");
2955 /* Make sure we're using standard DPTR */
2956 pic14_emitcode ("push", "dps");
2957 pic14_emitcode ("mov", "dps, #0x00");
2958 if (options.stack10bit)
2960 /* This ISR could conceivably use DPTR2. Better save it. */
2961 pic14_emitcode ("push", "dpl1");
2962 pic14_emitcode ("push", "dph1");
2963 pic14_emitcode ("push", "dpx1");
2966 /* if this isr has no bank i.e. is going to
2967 run with bank 0 , then we need to save more
2969 if (!FUNC_REGBANK(sym->type)) {
2971 /* if this function does not call any other
2972 function then we can be economical and
2973 save only those registers that are used */
2974 if (! IFFUNC_HASFCALL(sym->type)) {
2977 /* if any registers used */
2978 if (sym->regsUsed) {
2979 /* save the registers used */
2980 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2981 if (bitVectBitValue(sym->regsUsed,i) ||
2982 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2983 pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);
2988 /* this function has a function call cannot
2989 determines register usage so we will have the
2991 saverbank(0,ic,FALSE);
2996 /* if callee-save to be used for this function
2997 then save the registers being used in this function */
2998 if (IFFUNC_CALLEESAVES(sym->type)) {
3001 /* if any registers used */
3002 if (sym->regsUsed) {
3003 /* save the registers used */
3004 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3005 if (bitVectBitValue(sym->regsUsed,i) ||
3006 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
3007 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
3015 /* set the register bank to the desired value */
3016 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
3017 pic14_emitcode("push","psw");
3018 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);
3021 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3023 if (options.useXstack) {
3024 pic14_emitcode("mov","r0,%s",spname);
3025 pic14_emitcode("mov","a,_bp");
3026 pic14_emitcode("movx","@r0,a");
3027 pic14_emitcode("inc","%s",spname);
3031 /* set up the stack */
3032 pic14_emitcode ("push","_bp"); /* save the callers stack */
3034 pic14_emitcode ("mov","_bp,%s",spname);
3037 /* adjust the stack for the function */
3042 werror(W_STACK_OVERFLOW,sym->name);
3044 if (i > 3 && sym->recvSize < 4) {
3046 pic14_emitcode ("mov","a,sp");
3047 pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3048 pic14_emitcode ("mov","sp,a");
3053 pic14_emitcode("inc","sp");
3058 pic14_emitcode ("mov","a,_spx");
3059 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3060 pic14_emitcode ("mov","_spx,a");
3065 /*-----------------------------------------------------------------*/
3066 /* genEndFunction - generates epilogue for functions */
3067 /*-----------------------------------------------------------------*/
3068 static void genEndFunction (iCode *ic)
3070 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3074 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3076 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3078 pic14_emitcode ("mov","%s,_bp",spname);
3081 /* if use external stack but some variables were
3082 added to the local stack then decrement the
3084 if (options.useXstack && sym->stack) {
3085 pic14_emitcode("mov","a,sp");
3086 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3087 pic14_emitcode("mov","sp,a");
3091 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3092 if (options.useXstack) {
3093 pic14_emitcode("mov","r0,%s",spname);
3094 pic14_emitcode("movx","a,@r0");
3095 pic14_emitcode("mov","_bp,a");
3096 pic14_emitcode("dec","%s",spname);
3100 pic14_emitcode ("pop","_bp");
3104 /* restore the register bank */
3105 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3106 pic14_emitcode ("pop","psw");
3108 if (IFFUNC_ISISR(sym->type)) {
3110 /* now we need to restore the registers */
3111 /* if this isr has no bank i.e. is going to
3112 run with bank 0 , then we need to save more
3114 if (!FUNC_REGBANK(sym->type)) {
3116 /* if this function does not call any other
3117 function then we can be economical and
3118 save only those registers that are used */
3119 if (! IFFUNC_HASFCALL(sym->type)) {
3122 /* if any registers used */
3123 if (sym->regsUsed) {
3124 /* save the registers used */
3125 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3126 if (bitVectBitValue(sym->regsUsed,i) ||
3127 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3128 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3133 /* this function has a function call cannot
3134 determines register usage so we will have the
3136 unsaverbank(0,ic,FALSE);
3140 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3142 if (options.stack10bit)
3144 pic14_emitcode ("pop", "dpx1");
3145 pic14_emitcode ("pop", "dph1");
3146 pic14_emitcode ("pop", "dpl1");
3148 pic14_emitcode ("pop", "dps");
3149 pic14_emitcode ("pop", "dpx");
3151 if (!inExcludeList("dph"))
3152 pic14_emitcode ("pop","dph");
3153 if (!inExcludeList("dpl"))
3154 pic14_emitcode ("pop","dpl");
3155 if (!inExcludeList("b"))
3156 pic14_emitcode ("pop","b");
3157 if (!inExcludeList("acc"))
3158 pic14_emitcode ("pop","acc");
3160 if (IFFUNC_ISCRITICAL(sym->type))
3161 pic14_emitcode("setb","ea");
3164 /* if debug then send end of function */
3165 /* if (options.debug && currFunc) { */
3167 debugFile->writeEndFunction (currFunc, ic, 1);
3170 pic14_emitcode ("reti","");
3171 emitpcode(POC_MOVFW, popCopyReg(&pc_psave));
3172 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
3173 emitpcode(POC_CLRF, popCopyReg(&pc_status));
3174 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3175 emitpcode(POC_MOVWF, popCopyReg(&pc_status));
3176 emitpcode(POC_SWAPF, popCopyReg(&pc_wsave));
3177 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3178 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3179 emitpcodeNULLop(POC_RETFIE);
3182 if (IFFUNC_ISCRITICAL(sym->type))
3183 pic14_emitcode("setb","ea");
3185 if (IFFUNC_CALLEESAVES(sym->type)) {
3188 /* if any registers used */
3189 if (sym->regsUsed) {
3190 /* save the registers used */
3191 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3192 if (bitVectBitValue(sym->regsUsed,i) ||
3193 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3194 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3200 /* if debug then send end of function */
3202 debugFile->writeEndFunction (currFunc, ic, 1);
3205 pic14_emitcode ("return","");
3206 emitpcodeNULLop(POC_RETURN);
3208 /* Mark the end of a function */
3209 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3214 /*-----------------------------------------------------------------*/
3215 /* genRet - generate code for return statement */
3216 /*-----------------------------------------------------------------*/
3217 static void genRet (iCode *ic)
3219 int size,offset = 0;
3223 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3224 /* if we have no return value then
3225 just generate the "ret" */
3229 /* we have something to return then
3230 move the return value into place */
3231 aopOp(IC_LEFT(ic),ic,FALSE);
3232 size = AOP_SIZE(IC_LEFT(ic));
3234 for (offset = 0; offset < size; offset++)
3236 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
3239 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3242 /* generate a jump to the return label
3243 if the next is not the return statement */
3244 if (!(ic->next && ic->next->op == LABEL &&
3245 IC_LABEL(ic->next) == returnLabel)) {
3247 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3252 /*-----------------------------------------------------------------*/
3253 /* genLabel - generates a label */
3254 /*-----------------------------------------------------------------*/
3255 static void genLabel (iCode *ic)
3259 /* special case never generate */
3260 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3261 if (IC_LABEL(ic) == entryLabel)
3264 emitpLabel(IC_LABEL(ic)->key);
3265 pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3268 /*-----------------------------------------------------------------*/
3269 /* genGoto - generates a goto */
3270 /*-----------------------------------------------------------------*/
3272 static void genGoto (iCode *ic)
3276 emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3277 pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3281 /*-----------------------------------------------------------------*/
3282 /* genMultbits :- multiplication of bits */
3283 /*-----------------------------------------------------------------*/
3284 static void genMultbits (operand *left,
3289 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3291 if(!pic14_sameRegs(AOP(result),AOP(right)))
3292 emitpcode(POC_BSF, popGet(AOP(result),0));
3294 emitpcode(POC_BTFSC,popGet(AOP(right),0));
3295 emitpcode(POC_BTFSS,popGet(AOP(left),0));
3296 emitpcode(POC_BCF, popGet(AOP(result),0));
3301 /*-----------------------------------------------------------------*/
3302 /* genMultOneByte : 8 bit multiplication & division */
3303 /*-----------------------------------------------------------------*/
3304 static void genMultOneByte (operand *left,
3308 char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
3316 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3317 DEBUGpic14_AopType(__LINE__,left,right,result);
3318 DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3320 /* (if two literals, the value is computed before) */
3321 /* if one literal, literal on the right */
3322 if (AOP_TYPE(left) == AOP_LIT){
3328 assert (AOP_SIZE(left) == AOP_SIZE(right));
3330 size = min(AOP_SIZE(result),AOP_SIZE(left));
3331 offset = Gstack_base_addr - (2*size - 1);
3333 /* pass right operand as argument */
3334 for (i=0; i < size; i++)
3336 mov2w (AOP(right), i);
3337 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3340 /* pass left operand as argument */
3341 for (i=0; i < size; i++)
3343 mov2w (AOP(left), i);
3344 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3346 assert (offset == Gstack_base_addr);
3348 /* call library routine */
3349 assert (size > 0 && size <= 4);
3350 call_libraryfunc (func[size]);
3353 movwf (AOP(result), size-1);
3354 for (i=0; i < size - 1; i++)
3356 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
3357 movwf (AOP(result), size - 2 - i);
3360 /* now (zero-/sign) extend the result to its size */
3361 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
3364 /*-----------------------------------------------------------------*/
3365 /* genMult - generates code for multiplication */
3366 /*-----------------------------------------------------------------*/
3367 static void genMult (iCode *ic)
3369 operand *left = IC_LEFT(ic);
3370 operand *right = IC_RIGHT(ic);
3371 operand *result= IC_RESULT(ic);
3375 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3376 /* assign the amsops */
3377 aopOp (left,ic,FALSE);
3378 aopOp (right,ic,FALSE);
3379 aopOp (result,ic,TRUE);
3381 DEBUGpic14_AopType(__LINE__,left,right,result);
3383 /* special cases first */
3385 if (AOP_TYPE(left) == AOP_CRY &&
3386 AOP_TYPE(right)== AOP_CRY) {
3387 genMultbits(left,right,result);
3391 /* if both are of size == 1 */
3392 if (AOP_SIZE(left) == 1 &&
3393 AOP_SIZE(right) == 1 ) {
3394 genMultOneByte(left,right,result);
3398 /* should have been converted to function call */
3402 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3403 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3404 freeAsmop(result,NULL,ic,TRUE);
3407 /*-----------------------------------------------------------------*/
3408 /* genDivbits :- division of bits */
3409 /*-----------------------------------------------------------------*/
3410 static void genDivbits (operand *left,
3419 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3420 /* the result must be bit */
3421 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3422 l = aopGet(AOP(left),0,FALSE,FALSE);
3426 pic14_emitcode("div","ab");
3427 pic14_emitcode("rrc","a");
3428 aopPut(AOP(result),"c",0);
3431 /*-----------------------------------------------------------------*/
3432 /* genDivOneByte : 8 bit division */
3433 /*-----------------------------------------------------------------*/
3434 static void genDivOneByte (operand *left,
3441 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3443 assert (AOP_SIZE(result) == 1);
3444 assert (AOP_SIZE(right) == 1);
3445 assert (AOP_SIZE(left) == 1);
3447 size = min(AOP_SIZE(result),AOP_SIZE(left));
3449 if (AOP_TYPE(right) == AOP_LIT)
3451 /* XXX: might add specialized code */
3454 if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3456 /* unsigned division */
3458 mov2w(AOP(right),0);
3459 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3461 call_libraryfunc("__divuchar");
3462 movwf(AOP(result),0);
3467 temp = popGetTempReg();
3468 lbl = newiTempLabel(NULL);
3470 /* XXX: improve this naive approach:
3471 [result] = [a] / [b]
3472 ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
3476 movwf temp // temp <-- left
3477 movf right,W // W <-- right
3481 subwf temp,F // temp <-- temp - W
3482 skipNC // subwf clears CARRY (i.e. sets BORROW) if temp < W
3484 decf result // we just subtract once too often
3487 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3488 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
3491 emitpcode(POC_MOVWF, temp);
3492 mov2w(AOP(right),0);
3493 emitpcode(POC_CLRF, popGet(AOP(result),0));
3495 emitpLabel(lbl->key);
3496 emitpcode(POC_INCF, popGet(AOP(result),0));
3497 emitpcode(POC_SUBWF, temp);
3499 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3500 emitpcode(POC_DECF, popGet(AOP(result),0));
3505 /* signed division */
3506 mov2w(AOP(right),0);
3507 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3509 call_libraryfunc("__divschar");
3510 movwf(AOP(result),0);
3513 /* now performed the signed/unsigned division -- extend result */
3514 addSign(result, 1, !SPEC_USIGN(operandType(result)));
3517 /*-----------------------------------------------------------------*/
3518 /* genDiv - generates code for division */
3519 /*-----------------------------------------------------------------*/
3520 static void genDiv (iCode *ic)
3522 operand *left = IC_LEFT(ic);
3523 operand *right = IC_RIGHT(ic);
3524 operand *result= IC_RESULT(ic);
3527 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3528 /* assign the amsops */
3529 aopOp (left,ic,FALSE);
3530 aopOp (right,ic,FALSE);
3531 aopOp (result,ic,TRUE);
3533 /* special cases first */
3535 if (AOP_TYPE(left) == AOP_CRY &&
3536 AOP_TYPE(right)== AOP_CRY) {
3537 genDivbits(left,right,result);
3541 /* if both are of size == 1 */
3542 if (AOP_SIZE(left) == 1 &&
3543 AOP_SIZE(right) == 1 ) {
3544 genDivOneByte(left,right,result);
3548 /* should have been converted to function call */
3551 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3552 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3553 freeAsmop(result,NULL,ic,TRUE);
3556 /*-----------------------------------------------------------------*/
3557 /* genModbits :- modulus of bits */
3558 /*-----------------------------------------------------------------*/
3559 static void genModbits (operand *left,
3567 /* the result must be bit */
3568 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3569 l = aopGet(AOP(left),0,FALSE,FALSE);
3573 pic14_emitcode("div","ab");
3574 pic14_emitcode("mov","a,b");
3575 pic14_emitcode("rrc","a");
3576 aopPut(AOP(result),"c",0);
3579 /*-----------------------------------------------------------------*/
3580 /* genModOneByte : 8 bit modulus */
3581 /*-----------------------------------------------------------------*/
3582 static void genModOneByte (operand *left,
3589 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3591 assert (AOP_SIZE(result) == 1);
3592 assert (AOP_SIZE(right) == 1);
3593 assert (AOP_SIZE(left) == 1);
3595 size = min(AOP_SIZE(result),AOP_SIZE(left));
3597 if (AOP_TYPE(right) == AOP_LIT)
3599 /* XXX: might add specialized code */
3602 if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3604 /* unsigned division */
3606 mov2w(AOP(right),0);
3607 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3609 call_libraryfunc("__moduchar");
3610 movwf(AOP(result),0);
3615 lbl = newiTempLabel(NULL);
3617 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3619 /* XXX: improve this naive approach:
3620 [result] = [a] % [b]
3621 ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3625 movwf result // result <-- left
3626 movf right,W // W <-- right
3628 subwf result,F // result <-- result - W
3629 skipNC // subwf clears CARRY (i.e. sets BORROW) if result < W
3631 addwf result, F // we just subtract once too often
3634 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3635 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3637 if (!pic14_sameRegs(AOP(left), AOP(result)))
3640 emitpcode(POC_MOVWF, popGet(AOP(result),0));
3642 mov2w(AOP(right),0);
3644 emitpLabel(lbl->key);
3645 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3647 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3648 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3653 /* signed division */
3654 mov2w(AOP(right),0);
3655 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3657 call_libraryfunc("__modschar");
3658 movwf(AOP(result),0);
3661 /* now we performed the signed/unsigned modulus -- extend result */
3662 addSign(result, 1, !SPEC_USIGN(operandType(result)));
3665 /*-----------------------------------------------------------------*/
3666 /* genMod - generates code for division */
3667 /*-----------------------------------------------------------------*/
3668 static void genMod (iCode *ic)
3670 operand *left = IC_LEFT(ic);
3671 operand *right = IC_RIGHT(ic);
3672 operand *result= IC_RESULT(ic);
3675 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3676 /* assign the amsops */
3677 aopOp (left,ic,FALSE);
3678 aopOp (right,ic,FALSE);
3679 aopOp (result,ic,TRUE);
3681 /* special cases first */
3683 if (AOP_TYPE(left) == AOP_CRY &&
3684 AOP_TYPE(right)== AOP_CRY) {
3685 genModbits(left,right,result);
3689 /* if both are of size == 1 */
3690 if (AOP_SIZE(left) == 1 &&
3691 AOP_SIZE(right) == 1 ) {
3692 genModOneByte(left,right,result);
3696 /* should have been converted to function call */
3700 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3701 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3702 freeAsmop(result,NULL,ic,TRUE);
3705 /*-----------------------------------------------------------------*/
3706 /* genIfxJump :- will create a jump depending on the ifx */
3707 /*-----------------------------------------------------------------*/
3709 note: May need to add parameter to indicate when a variable is in bit space.
3711 static void genIfxJump (iCode *ic, char *jval)
3715 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3716 /* if true label then we jump if condition
3718 if ( IC_TRUE(ic) ) {
3720 if(strcmp(jval,"a") == 0)
3722 else if (strcmp(jval,"c") == 0)
3725 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3726 emitpcode(POC_BTFSC, newpCodeOpBit(jval,-1,1));
3729 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3730 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3734 /* false label is present */
3735 if(strcmp(jval,"a") == 0)
3737 else if (strcmp(jval,"c") == 0)
3740 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3741 emitpcode(POC_BTFSS, newpCodeOpBit(jval,-1,1));
3744 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3745 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3750 /* mark the icode as generated */
3755 /*-----------------------------------------------------------------*/
3757 /*-----------------------------------------------------------------*/
3758 static void genSkip(iCode *ifx,int status_bit)
3764 if ( IC_TRUE(ifx) ) {
3765 switch(status_bit) {
3780 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3781 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3785 switch(status_bit) {
3799 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3800 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3807 /*-----------------------------------------------------------------*/
3809 /*-----------------------------------------------------------------*/
3810 static void genSkipc(resolvedIfx *rifx)
3821 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3822 emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3823 rifx->generated = 1;
3827 /*-----------------------------------------------------------------*/
3829 /*-----------------------------------------------------------------*/
3830 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3836 if( (rifx->condition ^ invert_condition) & 1)
3841 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3842 rifx->generated = 1;
3847 /*-----------------------------------------------------------------*/
3849 /*-----------------------------------------------------------------*/
3850 static void genSkipz(iCode *ifx, int condition)
3853 assert (ifx != NULL);
3861 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3863 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3866 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3868 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3874 /*-----------------------------------------------------------------*/
3876 /*-----------------------------------------------------------------*/
3877 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3884 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3886 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3889 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3890 rifx->generated = 1;
3895 /*-----------------------------------------------------------------*/
3896 /* genChkZeroes :- greater or less than comparison */
3897 /* For each byte in a literal that is zero, inclusive or the */
3898 /* the corresponding byte in the operand with W */
3899 /* returns true if any of the bytes are zero */
3900 /*-----------------------------------------------------------------*/
3901 static int genChkZeroes(operand *op, int lit, int size)
3908 i = (lit >> (size*8)) & 0xff;
3912 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3914 emitpcode(POC_IORFW, popGet(AOP(op),size));
3924 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3925 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
3926 #define DEBUGpc emitpComment
3928 /*-----------------------------------------------------------------*/
3929 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
3930 /* aop (if it's NOT a literal) or from lit (if */
3931 /* aop is a literal) */
3932 /*-----------------------------------------------------------------*/
3933 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3934 if (aop->type == AOP_LIT) {
3935 emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3937 emitpcode (POC_MOVFW, popGet (aop, offset));
3941 /* genCmp performs a left < right comparison, stores
3942 * the outcome in result (if != NULL) and generates
3943 * control flow code for the ifx (if != NULL).
3945 * This version leaves in sequences like
3946 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3947 * which should be optmized by the peephole
3948 * optimizer - RN 2005-01-01 */
3949 static void genCmp (operand *left,operand *right,
3950 operand *result, iCode *ifx, int sign)
3960 int invert_result = 0;
3964 assert (AOP_SIZE(left) == AOP_SIZE(right));
3965 assert (left && right);
3967 size = AOP_SIZE(right) - 1;
3968 mask = (0x100UL << (size*8)) - 1;
3969 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3974 resolveIfx (&rIfx, ifx);
3976 /**********************************************************************
3977 * handle bits - bit compares are promoted to int compares seemingly! *
3978 **********************************************************************/
3980 // THIS IS COMPLETELY UNTESTED!
3981 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3982 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3983 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3984 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3987 // 1 < {0,1} is false --> clear C by skipping the next instruction
3988 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3989 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3990 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3991 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3992 emitCLRC; // only skipped for left=0 && right=1
3994 goto correct_result_in_carry;
3998 /*************************************************
3999 * make sure that left is register (or the like) *
4000 *************************************************/
4001 if (!isAOP_REGlike(left)) {
4002 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4003 assert (isAOP_LIT(left));
4004 assert (isAOP_REGlike(right));
4005 // swap left and right
4006 // left < right <==> right > left <==> (right >= left + 1)
4007 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4009 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4010 // MAXVALUE < right? always false
4011 if (performedLt) emitCLRC; else emitSETC;
4012 goto correct_result_in_carry;
4015 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4016 // that's why we handled it above.
4023 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4024 } else if (isAOP_LIT(right)) {
4025 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4028 assert (isAOP_REGlike(left)); // left must be register or the like
4029 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4031 /*************************************************
4032 * special cases go here *
4033 *************************************************/
4035 if (isAOP_LIT(right)) {
4037 // unsigned comparison to a literal
4038 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4040 // unsigned left < 0? always false
4041 if (performedLt) emitCLRC; else emitSETC;
4042 goto correct_result_in_carry;
4045 // signed comparison to a literal
4046 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4047 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4048 // signed left < 0x80000000? always false
4049 if (performedLt) emitCLRC; else emitSETC;
4050 goto correct_result_in_carry;
4051 } else if (lit == 0) {
4052 // compare left < 0; set CARRY if SIGNBIT(left) is set
4053 if (performedLt) emitSETC; else emitCLRC;
4054 emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
4055 if (performedLt) emitCLRC; else emitSETC;
4056 goto correct_result_in_carry;
4059 } // right is literal
4061 /*************************************************
4062 * perform a general case comparison *
4063 * make sure we get CARRY==1 <==> left >= right *
4064 *************************************************/
4065 // compare most significant bytes
4066 //DEBUGpc ("comparing bytes at offset %d", size);
4068 // unsigned comparison
4069 pic14_mov2w_regOrLit (AOP(right), lit, size);
4070 emitpcode (POC_SUBFW, popGet (AOP(left), size));
4072 // signed comparison
4073 // (add 2^n to both operands then perform an unsigned comparison)
4074 if (isAOP_LIT(right)) {
4075 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4076 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4078 if (litbyte == 0x80) {
4079 // left >= 0x80 -- always true, but more bytes to come
4080 mov2w (AOP(left), size);
4081 emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
4084 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4085 mov2w (AOP(left), size);
4086 emitpcode (POC_ADDLW, popGetLit (0x80));
4087 emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4090 pCodeOp *pctemp = popGetTempReg();
4091 mov2w (AOP(left), size);
4092 emitpcode (POC_ADDLW, popGetLit (0x80));
4093 emitpcode (POC_MOVWF, pctemp);
4094 mov2w (AOP(right), size);
4095 emitpcode (POC_ADDLW, popGetLit (0x80));
4096 emitpcode (POC_SUBFW, pctemp);
4097 popReleaseTempReg(pctemp);
4101 // compare remaining bytes (treat as unsigned case from above)
4102 templbl = newiTempLabel ( NULL );
4105 //DEBUGpc ("comparing bytes at offset %d", offs);
4107 emitpcode (POC_GOTO, popGetLabel (templbl->key));
4108 pic14_mov2w_regOrLit (AOP(right), lit, offs);
4109 emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4111 emitpLabel (templbl->key);
4112 goto result_in_carry;
4116 /****************************************************
4117 * now CARRY contains the result of the comparison: *
4118 * SUBWF sets CARRY iff *
4119 * F-W >= 0 <==> F >= W <==> !(F < W) *
4120 * (F=left, W=right) *
4121 ****************************************************/
4125 // value will be used in the following genSkipc()
4126 rIfx.condition ^= 1;
4129 correct_result_in_carry:
4131 // assign result to variable (if neccessary)
4132 if (result && AOP_TYPE(result) != AOP_CRY) {
4133 //DEBUGpc ("assign result");
4134 size = AOP_SIZE(result);
4136 emitpcode (POC_CLRF, popGet (AOP(result), size));
4138 if (invert_result) {
4140 emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4142 emitpcode (POC_RLF, popGet (AOP(result), 0));
4146 // perform conditional jump
4148 //DEBUGpc ("generate control flow");
4156 /* OLD VERSION -- BUGGY, DO NOT USE */
4158 /*-----------------------------------------------------------------*/
4159 /* genCmp :- greater or less than comparison */
4160 /*-----------------------------------------------------------------*/
4161 static void genCmp (operand *left,operand *right,
4162 operand *result, iCode *ifx, int sign)
4164 int size; //, offset = 0 ;
4165 unsigned long lit = 0L,i = 0;
4166 resolvedIfx rFalseIfx;
4167 // resolvedIfx rTrueIfx;
4171 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4174 DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4175 DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4179 resolveIfx(&rFalseIfx,ifx);
4180 truelbl = newiTempLabel(NULL);
4181 size = max(AOP_SIZE(left),AOP_SIZE(right));
4183 DEBUGpic14_AopType(__LINE__,left,right,result);
4187 /* if literal is on the right then swap with left */
4188 if ((AOP_TYPE(right) == AOP_LIT)) {
4189 operand *tmp = right ;
4190 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4191 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4194 lit = (lit - 1) & mask;
4197 rFalseIfx.condition ^= 1;
4200 } else if ((AOP_TYPE(left) == AOP_LIT)) {
4201 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4205 //if(IC_TRUE(ifx) == NULL)
4206 /* if left & right are bit variables */
4207 if (AOP_TYPE(left) == AOP_CRY &&
4208 AOP_TYPE(right) == AOP_CRY ) {
4209 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4210 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4212 /* subtract right from left if at the
4213 end the carry flag is set then we know that
4214 left is greater than right */
4216 symbol *lbl = newiTempLabel(NULL);
4219 if(AOP_TYPE(right) == AOP_LIT) {
4221 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4223 DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4230 genSkipCond(&rFalseIfx,left,size-1,7);
4232 /* no need to compare to 0...*/
4233 /* NOTE: this is a de-generate compare that most certainly
4234 * creates some dead code. */
4235 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4237 if(ifx) ifx->generated = 1;
4244 //i = (lit >> (size*8)) & 0xff;
4245 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4247 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4249 i = ((0-lit) & 0xff);
4252 /* lit is 0x7f, all signed chars are less than
4253 * this except for 0x7f itself */
4254 emitpcode(POC_XORLW, popGetLit(0x7f));
4255 genSkipz2(&rFalseIfx,0);
4257 emitpcode(POC_ADDLW, popGetLit(0x80));
4258 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4259 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4264 genSkipz2(&rFalseIfx,1);
4266 emitpcode(POC_ADDLW, popGetLit(i));
4267 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4271 if(ifx) ifx->generated = 1;
4275 /* chars are out of the way. now do ints and longs */
4278 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4285 genSkipCond(&rFalseIfx,left,size,7);
4286 if(ifx) ifx->generated = 1;
4291 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4293 //rFalseIfx.condition ^= 1;
4294 //genSkipCond(&rFalseIfx,left,size,7);
4295 //rFalseIfx.condition ^= 1;
4297 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4298 if(rFalseIfx.condition)
4299 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4301 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4303 emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4304 emitpcode(POC_ADDFW, popGet(AOP(left),0));
4305 emitpcode(POC_MOVFW, popGet(AOP(left),1));
4308 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4310 if(rFalseIfx.condition) {
4312 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4318 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4319 emitpLabel(truelbl->key);
4320 if(ifx) ifx->generated = 1;
4327 if( (lit & 0xff) == 0) {
4328 /* lower byte is zero */
4329 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4330 i = ((lit >> 8) & 0xff) ^0x80;
4331 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4332 emitpcode(POC_ADDLW, popGetLit( 0x80));
4333 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4334 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4337 if(ifx) ifx->generated = 1;
4342 /* Special cases for signed longs */
4343 if( (lit & 0xffffff) == 0) {
4344 /* lower byte is zero */
4345 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4346 i = ((lit >> 8*3) & 0xff) ^0x80;
4347 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4348 emitpcode(POC_ADDLW, popGetLit( 0x80));
4349 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4350 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4353 if(ifx) ifx->generated = 1;
4361 if(lit & (0x80 << (size*8))) {
4362 /* lit is negative */
4363 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4365 //genSkipCond(&rFalseIfx,left,size,7);
4367 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4369 if(rFalseIfx.condition)
4370 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4372 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4376 /* lit is positive */
4377 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4378 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4379 if(rFalseIfx.condition)
4380 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4382 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4386 /* There are no more special cases, so perform a general compare */
4388 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4389 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4393 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4395 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4397 //rFalseIfx.condition ^= 1;
4398 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4400 emitpLabel(truelbl->key);
4402 if(ifx) ifx->generated = 1;
4409 /* sign is out of the way. So now do an unsigned compare */
4410 DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4413 /* General case - compare to an unsigned literal on the right.*/
4415 i = (lit >> (size*8)) & 0xff;
4416 emitpcode(POC_MOVLW, popGetLit(i));
4417 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4419 i = (lit >> (size*8)) & 0xff;
4422 emitpcode(POC_MOVLW, popGetLit(i));
4424 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4426 /* this byte of the lit is zero,
4427 *if it's not the last then OR in the variable */
4429 emitpcode(POC_IORFW, popGet(AOP(left),size));
4434 emitpLabel(lbl->key);
4435 //if(emitFinalCheck)
4436 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4438 emitpLabel(truelbl->key);
4440 if(ifx) ifx->generated = 1;
4447 if(AOP_TYPE(left) == AOP_LIT) {
4448 //symbol *lbl = newiTempLabel(NULL);
4450 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4453 DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4456 if((lit == 0) && (sign == 0)){
4459 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4461 emitpcode(POC_IORFW, popGet(AOP(right),--size));
4463 genSkipz2(&rFalseIfx,0);
4464 if(ifx) ifx->generated = 1;
4471 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4472 /* degenerate compare can never be true */
4473 if(rFalseIfx.condition == 0)
4474 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4476 if(ifx) ifx->generated = 1;
4481 /* signed comparisons to a literal byte */
4483 int lp1 = (lit+1) & 0xff;
4485 DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4488 rFalseIfx.condition ^= 1;
4489 genSkipCond(&rFalseIfx,right,0,7);
4492 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4493 emitpcode(POC_XORLW, popGetLit(0x7f));
4494 genSkipz2(&rFalseIfx,1);
4497 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4498 emitpcode(POC_ADDLW, popGetLit(0x80));
4499 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4500 rFalseIfx.condition ^= 1;
4501 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4504 if(ifx) ifx->generated = 1;
4506 /* unsigned comparisons to a literal byte */
4508 switch(lit & 0xff ) {
4510 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4511 genSkipz2(&rFalseIfx,0);
4512 if(ifx) ifx->generated = 1;
4515 genSkipCond(&rFalseIfx,right,0,7);
4516 if(ifx) ifx->generated = 1;
4520 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4521 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4522 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4523 rFalseIfx.condition ^= 1;
4524 if (AOP_TYPE(result) == AOP_CRY) {
4525 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4526 if(ifx) ifx->generated = 1;
4528 DEBUGpic14_emitcode ("; ***","%s %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4529 emitpcode(POC_CLRF, popGet(AOP(result),0));
4530 emitpcode(POC_RLF, popGet(AOP(result),0));
4531 emitpcode(POC_MOVLW, popGetLit(0x01));
4532 emitpcode(POC_XORWF, popGet(AOP(result),0));
4543 /* Size is greater than 1 */
4551 /* this means lit = 0xffffffff, or -1 */
4554 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4555 rFalseIfx.condition ^= 1;
4556 genSkipCond(&rFalseIfx,right,size,7);
4557 if(ifx) ifx->generated = 1;
4564 if(rFalseIfx.condition) {
4565 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4566 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4569 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4571 emitpcode(POC_IORFW, popGet(AOP(right),size));
4575 if(rFalseIfx.condition) {
4576 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4577 emitpLabel(truelbl->key);
4579 rFalseIfx.condition ^= 1;
4580 genSkipCond(&rFalseIfx,right,s,7);
4583 if(ifx) ifx->generated = 1;
4587 if((size == 1) && (0 == (lp1&0xff))) {
4588 /* lower byte of signed word is zero */
4589 DEBUGpic14_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
4590 i = ((lp1 >> 8) & 0xff) ^0x80;
4591 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4592 emitpcode(POC_ADDLW, popGetLit( 0x80));
4593 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4594 rFalseIfx.condition ^= 1;
4595 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4598 if(ifx) ifx->generated = 1;
4602 if(lit & (0x80 << (size*8))) {
4603 /* Lit is less than zero */
4604 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
4605 //rFalseIfx.condition ^= 1;
4606 //genSkipCond(&rFalseIfx,left,size,7);
4607 //rFalseIfx.condition ^= 1;
4608 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4609 //emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4611 if(rFalseIfx.condition)
4612 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4614 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4618 /* Lit is greater than or equal to zero */
4619 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
4620 //rFalseIfx.condition ^= 1;
4621 //genSkipCond(&rFalseIfx,right,size,7);
4622 //rFalseIfx.condition ^= 1;
4624 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4625 //emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4627 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4628 if(rFalseIfx.condition)
4629 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4631 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4636 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4637 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4641 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4643 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4645 rFalseIfx.condition ^= 1;
4646 //rFalseIfx.condition = 1;
4647 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4649 emitpLabel(truelbl->key);
4651 if(ifx) ifx->generated = 1;
4656 /* compare word or long to an unsigned literal on the right.*/
4661 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4664 break; /* handled above */
4667 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4669 emitpcode(POC_IORFW, popGet(AOP(right),size));
4670 genSkipz2(&rFalseIfx,0);
4674 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4676 emitpcode(POC_IORFW, popGet(AOP(right),size));
4679 if(rFalseIfx.condition)
4680 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4682 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4685 emitpcode(POC_MOVLW, popGetLit(lit+1));
4686 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4688 rFalseIfx.condition ^= 1;
4689 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4692 emitpLabel(truelbl->key);
4694 if(ifx) ifx->generated = 1;
4700 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4701 i = (lit >> (size*8)) & 0xff;
4703 emitpcode(POC_MOVLW, popGetLit(i));
4704 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4707 i = (lit >> (size*8)) & 0xff;
4710 emitpcode(POC_MOVLW, popGetLit(i));
4712 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4714 /* this byte of the lit is zero,
4715 *if it's not the last then OR in the variable */
4717 emitpcode(POC_IORFW, popGet(AOP(right),size));
4722 emitpLabel(lbl->key);
4724 rFalseIfx.condition ^= 1;
4725 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4729 emitpLabel(truelbl->key);
4730 if(ifx) ifx->generated = 1;
4734 /* Compare two variables */
4736 DEBUGpic14_emitcode(";sign","%d",sign);
4740 /* Sigh. thus sucks... */
4742 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4743 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4744 emitpcode(POC_MOVLW, popGetLit(0x80));
4745 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4746 emitpcode(POC_XORFW, popGet(AOP(right),size));
4747 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4749 /* Signed char comparison */
4750 /* Special thanks to Nikolai Golovchenko for this snippet */
4751 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4752 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4753 emitpcode(POC_RRFW, popGet(AOP(left),0)); /* could be any register */
4754 emitpcode(POC_XORFW, popGet(AOP(left),0));
4755 emitpcode(POC_XORFW, popGet(AOP(right),0));
4756 emitpcode(POC_ADDLW, popGetLit(0x80));
4758 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4759 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4761 if(ifx) ifx->generated = 1;
4767 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4768 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4772 /* The rest of the bytes of a multi-byte compare */
4776 emitpcode(POC_GOTO, popGetLabel(lbl->key));
4779 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4780 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4785 emitpLabel(lbl->key);
4787 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4788 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
4789 (AOP_TYPE(result) == AOP_REG)) {
4790 emitpcode(POC_CLRF, popGet(AOP(result),0));
4791 emitpcode(POC_RLF, popGet(AOP(result),0));
4793 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4795 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4796 if(ifx) ifx->generated = 1;
4803 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4804 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4805 pic14_outBitC(result);
4807 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4808 /* if the result is used in the next
4809 ifx conditional branch then generate
4810 code a little differently */
4812 genIfxJump (ifx,"c");
4814 pic14_outBitC(result);
4815 /* leave the result in acc */
4821 /*-----------------------------------------------------------------*/
4822 /* genCmpGt :- greater than comparison */
4823 /*-----------------------------------------------------------------*/
4824 static void genCmpGt (iCode *ic, iCode *ifx)
4826 operand *left, *right, *result;
4827 sym_link *letype , *retype;
4831 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4833 right= IC_RIGHT(ic);
4834 result = IC_RESULT(ic);
4836 letype = getSpec(operandType(left));
4837 retype =getSpec(operandType(right));
4838 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4839 /* assign the amsops */
4840 aopOp (left,ic,FALSE);
4841 aopOp (right,ic,FALSE);
4842 aopOp (result,ic,TRUE);
4844 genCmp(right, left, result, ifx, sign);
4846 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4847 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4848 freeAsmop(result,NULL,ic,TRUE);
4851 /*-----------------------------------------------------------------*/
4852 /* genCmpLt - less than comparisons */
4853 /*-----------------------------------------------------------------*/
4854 static void genCmpLt (iCode *ic, iCode *ifx)
4856 operand *left, *right, *result;
4857 sym_link *letype , *retype;
4861 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4863 right= IC_RIGHT(ic);
4864 result = IC_RESULT(ic);
4866 letype = getSpec(operandType(left));
4867 retype =getSpec(operandType(right));
4868 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4870 /* assign the amsops */
4871 aopOp (left,ic,FALSE);
4872 aopOp (right,ic,FALSE);
4873 aopOp (result,ic,TRUE);
4875 genCmp(left, right, result, ifx, sign);
4877 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4878 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4879 freeAsmop(result,NULL,ic,TRUE);
4883 /*-----------------------------------------------------------------*/
4884 /* genc16bit2lit - compare a 16 bit value to a literal */
4885 /*-----------------------------------------------------------------*/
4886 static void genc16bit2lit(operand *op, int lit, int offset)
4891 DEBUGpic14_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
4892 if( (lit&0xff) == 0)
4897 switch( BYTEofLONG(lit,i)) {
4899 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4902 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4905 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4908 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4909 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4914 switch( BYTEofLONG(lit,i)) {
4916 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4920 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4924 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4927 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4929 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4937 /*-----------------------------------------------------------------*/
4938 /* gencjneshort - compare and jump if not equal */
4939 /*-----------------------------------------------------------------*/
4940 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4942 int size = min(AOP_SIZE(left),AOP_SIZE(right));
4947 //unsigned long lit = 0L;
4949 if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4950 emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4953 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4954 DEBUGpic14_AopType(__LINE__,left,right,result);
4956 assert (!pic14_sameRegs (AOP(left), AOP(result)));
4957 assert (!pic14_sameRegs (AOP(right), AOP(result)));
4958 if (AOP_SIZE(result)) {
4959 for (offset = 0; offset < AOP_SIZE(result); offset++)
4960 emitpcode (POC_CLRF, popGet (AOP(result), offset));
4963 assert (AOP_SIZE(left) == AOP_SIZE(right));
4964 //resolveIfx(&rIfx,ifx);
4965 lbl = newiTempLabel (NULL);
4968 mov2w (AOP(right),size);
4969 emitpcode (POC_XORFW, popGet (AOP(left), size));
4973 emitpcode (POC_GOTO, popGetLabel (lbl->key));
4976 emitpLabel (lbl->key);
4977 if (AOP_SIZE(result)) {
4979 emitpcode (POC_INCF, popGet (AOP(result), 0));
4982 genSkipz (ifx, NULL != IC_TRUE(ifx));
4989 DEBUGpic14_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
4990 assert (!pic14_sameRegs (AOP(result), AOP(left)));
4991 assert (!pic14_sameRegs (AOP(result), AOP(right)));
4992 for (offset=0; offset < AOP_SIZE(result); offset++)
4994 emitpcode (POC_CLRF, popGet (AOP(result), offset));
4999 /* if the left side is a literal or
5000 if the right is in a pointer register and left
5002 if ((AOP_TYPE(left) == AOP_LIT) ||
5003 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5008 if(AOP_TYPE(right) == AOP_LIT)
5009 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5011 /* if the right side is a literal then anything goes */
5012 if (AOP_TYPE(right) == AOP_LIT &&
5013 AOP_TYPE(left) != AOP_DIR ) {
5016 genc16bit2lit(left, lit, 0);
5018 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5024 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5025 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5027 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5031 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5039 /* if the right side is in a register or in direct space or
5040 if the left is a pointer register & right is not */
5041 else if (AOP_TYPE(right) == AOP_REG ||
5042 AOP_TYPE(right) == AOP_DIR ||
5043 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5044 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5045 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5046 int lbl_key = lbl->key;
5049 DEBUGpic14_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
5050 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
5051 __FUNCTION__,__LINE__);
5055 /* switch(size) { */
5057 /* genc16bit2lit(left, lit, 0); */
5059 /* emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
5065 if((AOP_TYPE(left) == AOP_DIR) &&
5066 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5068 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5069 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5071 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5073 switch (lit & 0xff) {
5075 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5078 emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
5079 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5080 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5084 emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5085 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5086 //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5087 emitpcode(POC_GOTO,popGetLabel(lbl_key));
5091 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5092 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5097 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5100 if(AOP_TYPE(result) == AOP_CRY) {
5101 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5106 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5108 /* fix me. probably need to check result size too */
5109 //emitpcode(POC_CLRF,popGet(AOP(result),0));
5114 emitpcode(POC_GOTO,popGetLabel(lbl_key));
5124 } else if(AOP_TYPE(right) == AOP_REG &&
5125 AOP_TYPE(left) != AOP_DIR){
5129 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5130 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5131 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5136 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5141 /* right is a pointer reg need both a & b */
5144 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5146 pic14_emitcode("mov","b,%s",l);
5147 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5148 pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
5153 emitpcode(POC_INCF,popGet(AOP(result),0));
5155 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5157 emitpLabel(lbl->key);
5159 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5168 /*-----------------------------------------------------------------*/
5169 /* gencjne - compare and jump if not equal */
5170 /*-----------------------------------------------------------------*/
5171 static void gencjne(operand *left, operand *right, iCode *ifx)
5173 symbol *tlbl = newiTempLabel(NULL);
5175 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5176 gencjneshort(left, right, lbl);
5178 pic14_emitcode("mov","a,%s",one);
5179 pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5180 pic14_emitcode("","%05d_DS_:",lbl->key+100);
5181 pic14_emitcode("clr","a");
5182 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5184 emitpLabel(lbl->key);
5185 emitpLabel(tlbl->key);
5190 /*-----------------------------------------------------------------*/
5191 /* genCmpEq - generates code for equal to */
5192 /*-----------------------------------------------------------------*/
5193 static void genCmpEq (iCode *ic, iCode *ifx)
5195 operand *left, *right, *result;
5197 symbol *false_label;
5200 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5203 DEBUGpic14_emitcode ("; ifx is non-null","");
5205 DEBUGpic14_emitcode ("; ifx is null","");
5207 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5208 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5209 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5211 DEBUGpic14_AopType(__LINE__,left,right,result);
5213 /* if literal, move literal to right */
5214 if (op_isLitLike (IC_LEFT(ic))) {
5215 operand *tmp = right ;
5221 if (ifx && !IC_TRUE(ifx))
5223 assert (IC_FALSE(ifx));
5224 false_label = IC_FALSE(ifx);
5227 size = min(AOP_SIZE(left),AOP_SIZE(right));
5228 assert(!pic14_sameRegs(AOP(result),AOP(left)));
5229 assert(!pic14_sameRegs(AOP(result),AOP(right)));
5231 /* assume left != right */
5234 for (i=0; i < AOP_SIZE(result); i++)
5236 emitpcode(POC_CLRF, popGet(AOP(result),i));
5240 if (AOP_TYPE(right) == AOP_LIT)
5242 unsigned long lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
5244 size = AOP_SIZE(left);
5245 assert(!op_isLitLike(left));
5250 mov2w(AOP(left), 0);
5251 for (i=1; i < size; i++)
5252 emitpcode(POC_IORFW,popGet(AOP(left),i));
5253 /* now Z is set iff `left == right' */
5255 if (!false_label) false_label = newiTempLabel(NULL);
5256 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5260 for (i=0; i < size; i++)
5263 emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
5264 /* now Z is cleared if `left != right' */
5266 if (!false_label) false_label = newiTempLabel(NULL);
5267 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5274 /* right is no literal */
5277 for (i=0; i < size; i++)
5279 mov2w(AOP(right),i);
5280 emitpcode(POC_XORFW,popGet(AOP(left),i));
5281 /* now Z is cleared if `left != right' */
5283 if (!false_label) false_label = newiTempLabel(NULL);
5284 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5288 /* if we reach here, left == right */
5290 if (AOP_SIZE(result) > 0)
5292 emitpcode(POC_INCF, popGet(AOP(result),0));
5295 if (ifx && IC_TRUE(ifx))
5297 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5300 if (false_label && (!ifx || IC_TRUE(ifx)))
5301 emitpLabel(false_label->key);
5303 if (ifx) ifx->generated = 1;
5305 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5306 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5307 freeAsmop(result,NULL,ic,TRUE);
5310 /*-----------------------------------------------------------------*/
5311 /* ifxForOp - returns the icode containing the ifx for operand */
5312 /*-----------------------------------------------------------------*/
5313 static iCode *ifxForOp ( operand *op, iCode *ic )
5316 /* if true symbol then needs to be assigned */
5317 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5318 if (IS_TRUE_SYMOP(op))
5321 /* if this has register type condition and
5322 the next instruction is ifx with the same operand
5323 and live to of the operand is upto the ifx only then */
5325 ic->next->op == IFX &&
5326 IC_COND(ic->next)->key == op->key &&
5327 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5331 ic->next->op == IFX &&
5332 IC_COND(ic->next)->key == op->key) {
5333 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5337 DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5339 ic->next->op == IFX)
5340 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5343 ic->next->op == IFX &&
5344 IC_COND(ic->next)->key == op->key) {
5345 DEBUGpic14_emitcode ("; "," key is okay");
5346 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5347 OP_SYMBOL(op)->liveTo,
5354 /*-----------------------------------------------------------------*/
5355 /* genAndOp - for && operation */
5356 /*-----------------------------------------------------------------*/
5357 static void genAndOp (iCode *ic)
5359 operand *left,*right, *result;
5363 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5364 /* note here that && operations that are in an
5365 if statement are taken away by backPatchLabels
5366 only those used in arthmetic operations remain */
5367 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5368 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5369 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5371 DEBUGpic14_AopType(__LINE__,left,right,result);
5373 emitpcode(POC_MOVFW,popGet(AOP(left),0));
5374 emitpcode(POC_ANDFW,popGet(AOP(right),0));
5375 emitpcode(POC_MOVWF,popGet(AOP(result),0));
5377 /* if both are bit variables */
5378 /* if (AOP_TYPE(left) == AOP_CRY && */
5379 /* AOP_TYPE(right) == AOP_CRY ) { */
5380 /* pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5381 /* pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5382 /* pic14_outBitC(result); */
5384 /* tlbl = newiTempLabel(NULL); */
5385 /* pic14_toBoolean(left); */
5386 /* pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5387 /* pic14_toBoolean(right); */
5388 /* pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5389 /* pic14_outBitAcc(result); */
5392 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5393 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5394 freeAsmop(result,NULL,ic,TRUE);
5398 /*-----------------------------------------------------------------*/
5399 /* genOrOp - for || operation */
5400 /*-----------------------------------------------------------------*/
5403 modified this code, but it doesn't appear to ever get called
5406 static void genOrOp (iCode *ic)
5408 operand *left,*right, *result;
5412 /* note here that || operations that are in an
5413 if statement are taken away by backPatchLabels
5414 only those used in arthmetic operations remain */
5416 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5417 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5418 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5419 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5421 DEBUGpic14_AopType(__LINE__,left,right,result);
5423 for (i=0; i < AOP_SIZE(result); i++)
5425 emitpcode(POC_CLRF, popGet(AOP(result), i));
5428 tlbl = newiTempLabel(NULL);
5429 pic14_toBoolean(left);
5431 emitpcode(POC_GOTO, popGetLabel(tlbl->key));
5432 pic14_toBoolean(right);
5433 emitpLabel(tlbl->key);
5434 /* here Z is clear IFF `left || right' */
5436 emitpcode(POC_INCF, popGet(AOP(result), 0));
5438 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5439 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5440 freeAsmop(result,NULL,ic,TRUE);
5443 /*-----------------------------------------------------------------*/
5444 /* isLiteralBit - test if lit == 2^n */
5445 /*-----------------------------------------------------------------*/
5446 static int isLiteralBit(unsigned long lit)
5448 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5449 0x100L,0x200L,0x400L,0x800L,
5450 0x1000L,0x2000L,0x4000L,0x8000L,
5451 0x10000L,0x20000L,0x40000L,0x80000L,
5452 0x100000L,0x200000L,0x400000L,0x800000L,
5453 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5454 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5458 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5459 for(idx = 0; idx < 32; idx++)
5465 /*-----------------------------------------------------------------*/
5466 /* continueIfTrue - */
5467 /*-----------------------------------------------------------------*/
5468 static void continueIfTrue (iCode *ic)
5471 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5473 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5477 /*-----------------------------------------------------------------*/
5479 /*-----------------------------------------------------------------*/
5480 static void jumpIfTrue (iCode *ic)
5483 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5485 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5489 /*-----------------------------------------------------------------*/
5490 /* jmpTrueOrFalse - */
5491 /*-----------------------------------------------------------------*/
5492 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5495 // ugly but optimized by peephole
5496 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5498 symbol *nlbl = newiTempLabel(NULL);
5499 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5500 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5501 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5502 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5505 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5506 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5511 /*-----------------------------------------------------------------*/
5512 /* genAnd - code for and */
5513 /*-----------------------------------------------------------------*/
5514 static void genAnd (iCode *ic, iCode *ifx)
5516 operand *left, *right, *result;
5518 unsigned long lit = 0L;
5523 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5524 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5525 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5526 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5528 resolveIfx(&rIfx,ifx);
5530 /* if left is a literal & right is not then exchange them */
5531 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5532 AOP_NEEDSACC(left)) {
5533 operand *tmp = right ;
5538 /* if result = right then exchange them */
5539 if(pic14_sameRegs(AOP(result),AOP(right))){
5540 operand *tmp = right ;
5545 /* if right is bit then exchange them */
5546 if (AOP_TYPE(right) == AOP_CRY &&
5547 AOP_TYPE(left) != AOP_CRY){
5548 operand *tmp = right ;
5552 if(AOP_TYPE(right) == AOP_LIT)
5553 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5555 size = AOP_SIZE(result);
5557 DEBUGpic14_AopType(__LINE__,left,right,result);
5560 // result = bit & yy;
5561 if (AOP_TYPE(left) == AOP_CRY){
5562 // c = bit & literal;
5563 if(AOP_TYPE(right) == AOP_LIT){
5565 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5568 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5571 if(size && (AOP_TYPE(result) == AOP_CRY)){
5572 pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5575 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5579 pic14_emitcode("clr","c");
5582 if (AOP_TYPE(right) == AOP_CRY){
5584 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5585 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5588 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5590 pic14_emitcode("rrc","a");
5591 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5597 pic14_outBitC(result);
5599 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5600 genIfxJump(ifx, "c");
5604 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5605 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5606 if((AOP_TYPE(right) == AOP_LIT) &&
5607 (AOP_TYPE(result) == AOP_CRY) &&
5608 (AOP_TYPE(left) != AOP_CRY)){
5609 int posbit = isLiteralBit(lit);
5613 //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5616 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5621 while (posbit > 7) {
5625 emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5626 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5627 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5634 symbol *tlbl = newiTempLabel(NULL);
5635 int sizel = AOP_SIZE(left);
5637 pic14_emitcode("setb","c");
5639 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5640 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5642 if((posbit = isLiteralBit(bytelit)) != 0)
5643 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5645 if(bytelit != 0x0FFL)
5646 pic14_emitcode("anl","a,%s",
5647 aopGet(AOP(right),offset,FALSE,TRUE));
5648 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5653 // bit = left & literal
5655 pic14_emitcode("clr","c");
5656 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5658 // if(left & literal)
5661 jmpTrueOrFalse(ifx, tlbl);
5665 pic14_outBitC(result);
5669 /* if left is same as result */
5670 if(pic14_sameRegs(AOP(result),AOP(left))){
5672 for(;size--; offset++,lit>>=8) {
5673 if(AOP_TYPE(right) == AOP_LIT){
5674 switch(lit & 0xff) {
5676 /* and'ing with 0 has clears the result */
5677 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5680 /* and'ing with 0xff is a nop when the result and left are the same */
5685 int p = my_powof2( (~lit) & 0xff );
5687 /* only one bit is set in the literal, so use a bcf instruction */
5688 emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5691 if(know_W != (int)(lit&0xff))
5692 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5694 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5699 if (AOP_TYPE(left) == AOP_ACC) {
5700 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5702 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5703 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5710 // left & result in different registers
5711 if(AOP_TYPE(result) == AOP_CRY){
5713 // if(size), result in bit
5714 // if(!size && ifx), conditional oper: if(left & right)
5715 symbol *tlbl = newiTempLabel(NULL);
5716 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5718 pic14_emitcode("setb","c");
5720 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5721 pic14_emitcode("anl","a,%s",
5722 aopGet(AOP(left),offset,FALSE,FALSE));
5723 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5728 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5729 pic14_outBitC(result);
5731 jmpTrueOrFalse(ifx, tlbl);
5733 for(;(size--);offset++) {
5735 // result = left & right
5736 if(AOP_TYPE(right) == AOP_LIT){
5737 int t = (lit >> (offset*8)) & 0x0FFL;
5740 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5743 if(AOP_TYPE(left) != AOP_ACC) {
5744 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5746 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5749 if(AOP_TYPE(left) == AOP_ACC) {
5750 emitpcode(POC_ANDLW, popGetLit(t));
5752 emitpcode(POC_MOVLW, popGetLit(t));
5753 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5755 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5760 if (AOP_TYPE(left) == AOP_ACC) {
5761 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5763 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5764 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5766 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5772 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5773 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5774 freeAsmop(result,NULL,ic,TRUE);
5777 /*-----------------------------------------------------------------*/
5778 /* genOr - code for or */
5779 /*-----------------------------------------------------------------*/
5780 static void genOr (iCode *ic, iCode *ifx)
5782 operand *left, *right, *result;
5784 unsigned long lit = 0L;
5787 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5789 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5790 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5791 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5793 DEBUGpic14_AopType(__LINE__,left,right,result);
5795 /* if left is a literal & right is not then exchange them */
5796 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5797 AOP_NEEDSACC(left)) {
5798 operand *tmp = right ;
5803 /* if result = right then exchange them */
5804 if(pic14_sameRegs(AOP(result),AOP(right))){
5805 operand *tmp = right ;
5810 /* if right is bit then exchange them */
5811 if (AOP_TYPE(right) == AOP_CRY &&
5812 AOP_TYPE(left) != AOP_CRY){
5813 operand *tmp = right ;
5818 DEBUGpic14_AopType(__LINE__,left,right,result);
5820 if(AOP_TYPE(right) == AOP_LIT)
5821 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5823 size = AOP_SIZE(result);
5827 if (AOP_TYPE(left) == AOP_CRY){
5828 if(AOP_TYPE(right) == AOP_LIT){
5829 // c = bit & literal;
5831 // lit != 0 => result = 1
5832 if(AOP_TYPE(result) == AOP_CRY){
5834 emitpcode(POC_BSF, popGet(AOP(result),0));
5835 //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5836 // AOP(result)->aopu.aop_dir,
5837 // AOP(result)->aopu.aop_dir);
5839 continueIfTrue(ifx);
5843 // lit == 0 => result = left
5844 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5846 pic14_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5849 if (AOP_TYPE(right) == AOP_CRY){
5850 if(pic14_sameRegs(AOP(result),AOP(left))){
5852 emitpcode(POC_BCF, popGet(AOP(result),0));
5853 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5854 emitpcode(POC_BSF, popGet(AOP(result),0));
5856 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5857 AOP(result)->aopu.aop_dir,
5858 AOP(result)->aopu.aop_dir);
5859 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5860 AOP(right)->aopu.aop_dir,
5861 AOP(right)->aopu.aop_dir);
5862 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5863 AOP(result)->aopu.aop_dir,
5864 AOP(result)->aopu.aop_dir);
5866 if( AOP_TYPE(result) == AOP_ACC) {
5867 emitpcode(POC_MOVLW, popGetLit(0));
5868 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5869 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5870 emitpcode(POC_MOVLW, popGetLit(1));
5874 emitpcode(POC_BCF, popGet(AOP(result),0));
5875 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5876 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5877 emitpcode(POC_BSF, popGet(AOP(result),0));
5879 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5880 AOP(result)->aopu.aop_dir,
5881 AOP(result)->aopu.aop_dir);
5882 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5883 AOP(right)->aopu.aop_dir,
5884 AOP(right)->aopu.aop_dir);
5885 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5886 AOP(left)->aopu.aop_dir,
5887 AOP(left)->aopu.aop_dir);
5888 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5889 AOP(result)->aopu.aop_dir,
5890 AOP(result)->aopu.aop_dir);
5895 symbol *tlbl = newiTempLabel(NULL);
5896 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5899 emitpcode(POC_BCF, popGet(AOP(result),0));
5900 if( AOP_TYPE(right) == AOP_ACC) {
5901 emitpcode(POC_IORLW, popGetLit(0));
5903 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5904 emitpcode(POC_BSF, popGet(AOP(result),0));
5909 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5910 pic14_emitcode(";XXX setb","c");
5911 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5912 AOP(left)->aopu.aop_dir,tlbl->key+100);
5913 pic14_toBoolean(right);
5914 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5915 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5916 jmpTrueOrFalse(ifx, tlbl);
5920 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5927 pic14_outBitC(result);
5929 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5930 genIfxJump(ifx, "c");
5934 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5935 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5936 if((AOP_TYPE(right) == AOP_LIT) &&
5937 (AOP_TYPE(result) == AOP_CRY) &&
5938 (AOP_TYPE(left) != AOP_CRY)){
5940 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5943 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5945 continueIfTrue(ifx);
5948 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5949 // lit = 0, result = boolean(left)
5951 pic14_emitcode(";XXX setb","c");
5952 pic14_toBoolean(right);
5954 symbol *tlbl = newiTempLabel(NULL);
5955 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5957 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5959 genIfxJump (ifx,"a");
5963 pic14_outBitC(result);
5967 /* if left is same as result */
5968 if(pic14_sameRegs(AOP(result),AOP(left))){
5970 for(;size--; offset++,lit>>=8) {
5971 if(AOP_TYPE(right) == AOP_LIT){
5972 if((lit & 0xff) == 0)
5973 /* or'ing with 0 has no effect */
5976 int p = my_powof2(lit & 0xff);
5978 /* only one bit is set in the literal, so use a bsf instruction */
5980 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5982 if(know_W != (int)(lit & 0xff))
5983 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5984 know_W = lit & 0xff;
5985 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5990 if (AOP_TYPE(left) == AOP_ACC) {
5991 emitpcode(POC_IORFW, popGet(AOP(right),offset));
5992 pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5994 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
5995 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5997 pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5998 pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
6004 // left & result in different registers
6005 if(AOP_TYPE(result) == AOP_CRY){
6007 // if(size), result in bit
6008 // if(!size && ifx), conditional oper: if(left | right)
6009 symbol *tlbl = newiTempLabel(NULL);
6010 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6011 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6015 pic14_emitcode(";XXX setb","c");
6017 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6018 pic14_emitcode(";XXX orl","a,%s",
6019 aopGet(AOP(left),offset,FALSE,FALSE));
6020 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6025 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6026 pic14_outBitC(result);
6028 jmpTrueOrFalse(ifx, tlbl);
6029 } else for(;(size--);offset++){
6031 // result = left | right
6032 if(AOP_TYPE(right) == AOP_LIT){
6033 int t = (lit >> (offset*8)) & 0x0FFL;
6036 if (AOP_TYPE(left) != AOP_ACC) {
6037 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
6039 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6043 if (AOP_TYPE(left) == AOP_ACC) {
6044 emitpcode(POC_IORLW, popGetLit(t));
6046 emitpcode(POC_MOVLW, popGetLit(t));
6047 emitpcode(POC_IORFW, popGet(AOP(left),offset));
6049 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6054 // faster than result <- left, anl result,right
6055 // and better if result is SFR
6056 if (AOP_TYPE(left) == AOP_ACC) {
6057 emitpcode(POC_IORFW,popGet(AOP(right),offset));
6059 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6060 emitpcode(POC_IORFW,popGet(AOP(left),offset));
6062 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6067 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6068 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6069 freeAsmop(result,NULL,ic,TRUE);
6072 /*-----------------------------------------------------------------*/
6073 /* genXor - code for xclusive or */
6074 /*-----------------------------------------------------------------*/
6075 static void genXor (iCode *ic, iCode *ifx)
6077 operand *left, *right, *result;
6079 unsigned long lit = 0L;
6082 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6084 aopOp((left = IC_LEFT(ic)),ic,FALSE);
6085 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6086 aopOp((result=IC_RESULT(ic)),ic,TRUE);
6088 /* if left is a literal & right is not ||
6089 if left needs acc & right does not */
6090 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6091 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6092 operand *tmp = right ;
6097 /* if result = right then exchange them */
6098 if(pic14_sameRegs(AOP(result),AOP(right))){
6099 operand *tmp = right ;
6104 /* if right is bit then exchange them */
6105 if (AOP_TYPE(right) == AOP_CRY &&
6106 AOP_TYPE(left) != AOP_CRY){
6107 operand *tmp = right ;
6111 if(AOP_TYPE(right) == AOP_LIT)
6112 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6114 size = AOP_SIZE(result);
6118 if (AOP_TYPE(left) == AOP_CRY){
6119 if(AOP_TYPE(right) == AOP_LIT){
6120 // c = bit & literal;
6122 // lit>>1 != 0 => result = 1
6123 if(AOP_TYPE(result) == AOP_CRY){
6125 {emitpcode(POC_BSF, popGet(AOP(result),offset));
6126 pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6128 continueIfTrue(ifx);
6131 pic14_emitcode("setb","c");
6135 // lit == 0, result = left
6136 if(size && pic14_sameRegs(AOP(result),AOP(left)))
6138 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6140 // lit == 1, result = not(left)
6141 if(size && pic14_sameRegs(AOP(result),AOP(left))){
6142 emitpcode(POC_MOVLW, popGet(AOP(result),offset));
6143 emitpcode(POC_XORWF, popGet(AOP(result),offset));
6144 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6147 assert ( !"incomplete genXor" );
6148 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6149 pic14_emitcode("cpl","c");
6156 symbol *tlbl = newiTempLabel(NULL);
6157 if (AOP_TYPE(right) == AOP_CRY){
6159 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6162 int sizer = AOP_SIZE(right);
6164 // if val>>1 != 0, result = 1
6165 pic14_emitcode("setb","c");
6167 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6169 // test the msb of the lsb
6170 pic14_emitcode("anl","a,#0xfe");
6171 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6175 pic14_emitcode("rrc","a");
6177 pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6178 pic14_emitcode("cpl","c");
6179 pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6184 pic14_outBitC(result);
6186 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6187 genIfxJump(ifx, "c");
6191 if(pic14_sameRegs(AOP(result),AOP(left))){
6192 /* if left is same as result */
6193 for(;size--; offset++) {
6194 if(AOP_TYPE(right) == AOP_LIT){
6195 int t = (lit >> (offset*8)) & 0x0FFL;
6199 if (IS_AOP_PREG(left)) {
6200 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6201 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6202 aopPut(AOP(result),"a",offset);
6204 emitpcode(POC_MOVLW, popGetLit(t));
6205 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6206 pic14_emitcode("xrl","%s,%s",
6207 aopGet(AOP(left),offset,FALSE,TRUE),
6208 aopGet(AOP(right),offset,FALSE,FALSE));
6211 if (AOP_TYPE(left) == AOP_ACC)
6212 pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6214 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6215 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6217 if (IS_AOP_PREG(left)) {
6218 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6219 aopPut(AOP(result),"a",offset);
6221 pic14_emitcode("xrl","%s,a",
6222 aopGet(AOP(left),offset,FALSE,TRUE));
6228 // left & result in different registers
6229 if(AOP_TYPE(result) == AOP_CRY){
6231 // if(size), result in bit
6232 // if(!size && ifx), conditional oper: if(left ^ right)
6233 symbol *tlbl = newiTempLabel(NULL);
6234 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6236 pic14_emitcode("setb","c");
6238 if((AOP_TYPE(right) == AOP_LIT) &&
6239 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6240 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6242 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6243 pic14_emitcode("xrl","a,%s",
6244 aopGet(AOP(left),offset,FALSE,FALSE));
6246 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6251 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6252 pic14_outBitC(result);
6254 jmpTrueOrFalse(ifx, tlbl);
6255 } else for(;(size--);offset++){
6257 // result = left & right
6258 if(AOP_TYPE(right) == AOP_LIT){
6259 int t = (lit >> (offset*8)) & 0x0FFL;
6262 if (AOP_TYPE(left) != AOP_ACC) {
6263 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6265 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6266 pic14_emitcode("movf","%s,w",
6267 aopGet(AOP(left),offset,FALSE,FALSE));
6268 pic14_emitcode("movwf","%s",
6269 aopGet(AOP(result),offset,FALSE,FALSE));
6272 if (AOP_TYPE(left) == AOP_ACC) {
6273 emitpcode(POC_XORLW, popGetLit(t));
6275 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6277 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6280 if (AOP_TYPE(left) == AOP_ACC) {
6281 emitpcode(POC_XORLW, popGetLit(t));
6283 emitpcode(POC_MOVLW, popGetLit(t));
6284 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6286 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6287 pic14_emitcode("movlw","0x%x",t);
6288 pic14_emitcode("xorwf","%s,w",
6289 aopGet(AOP(left),offset,FALSE,FALSE));
6290 pic14_emitcode("movwf","%s",
6291 aopGet(AOP(result),offset,FALSE,FALSE));
6297 // faster than result <- left, anl result,right
6298 // and better if result is SFR
6299 if (AOP_TYPE(left) == AOP_ACC) {
6300 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6302 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6303 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6305 if ( AOP_TYPE(result) != AOP_ACC){
6306 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6312 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6313 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6314 freeAsmop(result,NULL,ic,TRUE);
6317 /*-----------------------------------------------------------------*/
6318 /* genInline - write the inline code out */
6319 /*-----------------------------------------------------------------*/
6320 static void genInline (iCode *ic)
6322 char *buffer, *bp, *bp1;
6325 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6327 _G.inLine += (!options.asmpeep);
6329 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6330 strcpy(buffer,IC_INLINE(ic));
6332 /* emit each line as a code */
6338 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6346 /* print label, use this special format with NULL directive
6347 * to denote that the argument should not be indented with tab */
6348 addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6355 if ((bp1 != bp) && *bp1)
6356 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6360 _G.inLine -= (!options.asmpeep);
6363 /*-----------------------------------------------------------------*/
6364 /* genRRC - rotate right with carry */
6365 /*-----------------------------------------------------------------*/
6366 static void genRRC (iCode *ic)
6368 operand *left , *result ;
6369 int size, offset = 0, same;
6372 /* rotate right with carry */
6374 result=IC_RESULT(ic);
6375 aopOp (left,ic,FALSE);
6376 aopOp (result,ic,FALSE);
6378 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6380 same = pic14_sameRegs(AOP(result),AOP(left));
6382 size = AOP_SIZE(result);
6384 /* get the lsb and put it into the carry */
6385 emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6392 emitpcode(POC_RRF, popGet(AOP(left),offset));
6394 emitpcode(POC_RRFW, popGet(AOP(left),offset));
6395 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6401 freeAsmop(left,NULL,ic,TRUE);
6402 freeAsmop(result,NULL,ic,TRUE);
6405 /*-----------------------------------------------------------------*/
6406 /* genRLC - generate code for rotate left with carry */
6407 /*-----------------------------------------------------------------*/
6408 static void genRLC (iCode *ic)
6410 operand *left , *result ;
6411 int size, offset = 0;
6415 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6416 /* rotate right with carry */
6418 result=IC_RESULT(ic);
6419 aopOp (left,ic,FALSE);
6420 aopOp (result,ic,FALSE);
6422 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6424 same = pic14_sameRegs(AOP(result),AOP(left));
6426 /* move it to the result */
6427 size = AOP_SIZE(result);
6429 /* get the msb and put it into the carry */
6430 emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6437 emitpcode(POC_RLF, popGet(AOP(left),offset));
6439 emitpcode(POC_RLFW, popGet(AOP(left),offset));
6440 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6447 freeAsmop(left,NULL,ic,TRUE);
6448 freeAsmop(result,NULL,ic,TRUE);
6451 /*-----------------------------------------------------------------*/
6452 /* genGetHbit - generates code get highest order bit */
6453 /*-----------------------------------------------------------------*/
6454 static void genGetHbit (iCode *ic)
6456 operand *left, *result;
6458 result=IC_RESULT(ic);
6459 aopOp (left,ic,FALSE);
6460 aopOp (result,ic,FALSE);
6463 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6464 /* get the highest order byte into a */
6465 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6466 if(AOP_TYPE(result) == AOP_CRY){
6467 pic14_emitcode("rlc","a");
6468 pic14_outBitC(result);
6471 pic14_emitcode("rl","a");
6472 pic14_emitcode("anl","a,#0x01");
6473 pic14_outAcc(result);
6477 freeAsmop(left,NULL,ic,TRUE);
6478 freeAsmop(result,NULL,ic,TRUE);
6481 /*-----------------------------------------------------------------*/
6482 /* AccLsh - shift left accumulator by known count */
6483 /* MARK: pic14 always rotates through CARRY! */
6484 /*-----------------------------------------------------------------*/
6485 static void AccLsh (pCodeOp *pcop,int shCount)
6488 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6489 shCount &= 0x0007; // shCount : 0..7
6496 emitpcode(POC_RLF,pcop);
6500 emitpcode(POC_RLF,pcop);
6501 emitpcode(POC_RLF,pcop);
6504 emitpcode(POC_RLF,pcop);
6505 emitpcode(POC_RLF,pcop);
6506 emitpcode(POC_RLF,pcop);
6509 emitpcode(POC_SWAPF,pcop);
6512 emitpcode(POC_SWAPF,pcop);
6513 emitpcode(POC_RLF,pcop);
6516 emitpcode(POC_SWAPF,pcop);
6517 emitpcode(POC_RLF,pcop);
6518 emitpcode(POC_RLF,pcop);
6521 emitpcode(POC_RRFW,pcop);
6522 emitpcode(POC_RRF,pcop);
6525 /* clear invalid bits */
6526 emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6527 emitpcode(POC_ANDWF, pcop);
6530 /*-----------------------------------------------------------------*/
6531 /* AccRsh - shift right accumulator by known count */
6532 /* MARK: pic14 always rotates through CARRY! */
6533 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6534 /* 1: mask out invalid bits (zero-extend) */
6535 /* 2: sign-extend result (pretty slow) */
6536 /*-----------------------------------------------------------------*/
6537 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6540 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6541 shCount &= 0x0007; // shCount : 0..7
6547 /* load sign if needed */
6548 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6549 else if (mask_mode == 1) emitCLRC;
6550 emitpcode(POC_RRF,pcop);
6554 /* load sign if needed */
6555 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6556 emitpcode(POC_RRF,pcop);
6557 /* load sign if needed */
6558 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6559 emitpcode(POC_RRF,pcop);
6560 if (mask_mode == 2) return;
6563 /* load sign if needed */
6564 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6565 emitpcode(POC_RRF,pcop);
6566 /* load sign if needed */
6567 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6568 emitpcode(POC_RRF,pcop);
6569 /* load sign if needed */
6570 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6571 emitpcode(POC_RRF,pcop);
6572 if (mask_mode == 2) return;
6575 emitpcode(POC_SWAPF,pcop);
6578 emitpcode(POC_SWAPF,pcop);
6579 emitpcode(POC_RRF,pcop);
6582 emitpcode(POC_SWAPF,pcop);
6583 emitpcode(POC_RRF,pcop);
6584 emitpcode(POC_RRF,pcop);
6590 emitpcode(POC_RLFW,pcop);
6591 emitpcode(POC_CLRF,pcop);
6593 emitpcode(POC_COMF,pcop);
6596 emitpcode(POC_RLFW,pcop);
6597 emitpcode(POC_RLF,pcop);
6604 /* leave invalid bits undefined */
6608 /* clear invalid bits -- zero-extend */
6609 emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6610 emitpcode(POC_ANDWF, pcop);
6612 if (mask_mode == 2) {
6614 emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6615 emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6616 emitpcode(POC_IORWF, pcop);
6621 /*-----------------------------------------------------------------*/
6622 /* AccSRsh - signed right shift accumulator by known count */
6623 /*-----------------------------------------------------------------*/
6624 static void AccSRsh (int shCount)
6627 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6630 pic14_emitcode("mov","c,acc.7");
6631 pic14_emitcode("rrc","a");
6632 } else if(shCount == 2){
6633 pic14_emitcode("mov","c,acc.7");
6634 pic14_emitcode("rrc","a");
6635 pic14_emitcode("mov","c,acc.7");
6636 pic14_emitcode("rrc","a");
6638 tlbl = newiTempLabel(NULL);
6639 /* rotate right accumulator */
6640 AccRol(8 - shCount);
6641 /* and kill the higher order bits */
6642 pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6643 pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6644 pic14_emitcode("orl","a,#0x%02x",
6645 (unsigned char)~SRMask[shCount]);
6646 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6651 /*-----------------------------------------------------------------*/
6652 /* shiftR1Left2Result - shift right one byte from left to result */
6653 /*-----------------------------------------------------------------*/
6654 static void shiftR1Left2ResultSigned (operand *left, int offl,
6655 operand *result, int offr,
6661 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6663 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6667 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6669 emitpcode(POC_RRF, popGet(AOP(result),offr));
6671 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6672 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6678 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6680 emitpcode(POC_RRF, popGet(AOP(result),offr));
6682 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6683 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6685 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6686 emitpcode(POC_RRF, popGet(AOP(result),offr));
6692 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6694 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6695 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6698 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6699 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6700 emitpcode(POC_ANDLW, popGetLit(0x1f));
6702 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6703 emitpcode(POC_IORLW, popGetLit(0xe0));
6705 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6709 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6710 emitpcode(POC_ANDLW, popGetLit(0x0f));
6711 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6712 emitpcode(POC_IORLW, popGetLit(0xf0));
6713 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6717 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6719 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6720 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6722 emitpcode(POC_RRFW, popGet(AOP(result),offr));
6723 emitpcode(POC_ANDLW, popGetLit(0x07));
6724 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6725 emitpcode(POC_IORLW, popGetLit(0xf8));
6726 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6731 emitpcode(POC_MOVLW, popGetLit(0x00));
6732 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6733 emitpcode(POC_MOVLW, popGetLit(0xfe));
6734 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6735 emitpcode(POC_IORLW, popGetLit(0x01));
6736 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6738 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6739 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6740 emitpcode(POC_DECF, popGet(AOP(result),offr));
6741 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6742 emitpcode(POC_BCF, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6748 emitpcode(POC_MOVLW, popGetLit(0x00));
6749 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6750 emitpcode(POC_MOVLW, popGetLit(0xff));
6751 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6753 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6754 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6755 emitpcode(POC_DECF, popGet(AOP(result),offr));
6763 /*-----------------------------------------------------------------*/
6764 /* shiftR1Left2Result - shift right one byte from left to result */
6765 /*-----------------------------------------------------------------*/
6766 static void shiftR1Left2Result (operand *left, int offl,
6767 operand *result, int offr,
6768 int shCount, int sign)
6773 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6775 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6777 /* Copy the msb into the carry if signed. */
6779 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6789 emitpcode(POC_RRF, popGet(AOP(result),offr));
6791 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6792 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6798 emitpcode(POC_RRF, popGet(AOP(result),offr));
6800 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6801 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6804 emitpcode(POC_RRF, popGet(AOP(result),offr));
6809 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6811 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6812 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6815 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6816 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6817 emitpcode(POC_ANDLW, popGetLit(0x1f));
6818 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6822 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6823 emitpcode(POC_ANDLW, popGetLit(0x0f));
6824 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6828 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6829 emitpcode(POC_ANDLW, popGetLit(0x0f));
6830 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6832 emitpcode(POC_RRF, popGet(AOP(result),offr));
6837 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6838 emitpcode(POC_ANDLW, popGetLit(0x80));
6839 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6840 emitpcode(POC_RLF, popGet(AOP(result),offr));
6841 emitpcode(POC_RLF, popGet(AOP(result),offr));
6846 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6847 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6848 emitpcode(POC_RLF, popGet(AOP(result),offr));
6857 /*-----------------------------------------------------------------*/
6858 /* shiftL1Left2Result - shift left one byte from left to result */
6859 /*-----------------------------------------------------------------*/
6860 static void shiftL1Left2Result (operand *left, int offl,
6861 operand *result, int offr, int shCount)
6867 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6869 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6870 DEBUGpic14_emitcode ("; ***","same = %d",same);
6871 // l = aopGet(AOP(left),offl,FALSE,FALSE);
6873 /* shift left accumulator */
6874 //AccLsh(shCount); // don't comment out just yet...
6875 // aopPut(AOP(result),"a",offr);
6879 /* Shift left 1 bit position */
6880 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6882 emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6884 emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6885 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6889 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6890 emitpcode(POC_ANDLW,popGetLit(0x7e));
6891 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6892 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6895 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6896 emitpcode(POC_ANDLW,popGetLit(0x3e));
6897 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6898 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6899 emitpcode(POC_RLF, popGet(AOP(result),offr));
6902 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6903 emitpcode(POC_ANDLW, popGetLit(0xf0));
6904 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6907 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6908 emitpcode(POC_ANDLW, popGetLit(0xf0));
6909 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6910 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6913 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6914 emitpcode(POC_ANDLW, popGetLit(0x30));
6915 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6916 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6917 emitpcode(POC_RLF, popGet(AOP(result),offr));
6920 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6921 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6922 emitpcode(POC_RRF, popGet(AOP(result),offr));
6926 DEBUGpic14_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6932 /*-----------------------------------------------------------------*/
6933 /* movLeft2Result - move byte from left to result */
6934 /*-----------------------------------------------------------------*/
6935 static void movLeft2Result (operand *left, int offl,
6936 operand *result, int offr)
6940 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6941 if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6942 l = aopGet(AOP(left),offl,FALSE,FALSE);
6944 if (*l == '@' && (IS_AOP_PREG(result))) {
6945 pic14_emitcode("mov","a,%s",l);
6946 aopPut(AOP(result),"a",offr);
6948 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6949 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6954 /*-----------------------------------------------------------------*/
6955 /* shiftLeft_Left2ResultLit - shift left by known count */
6956 /*-----------------------------------------------------------------*/
6958 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6960 int size, same, offr, i;
6962 size = AOP_SIZE(left);
6963 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6965 same = pic14_sameRegs (AOP(left), AOP(result));
6968 shCount = shCount & 0x07;
6974 case 0: /* takes 0 or 2N cycles (for offr==0) */
6975 if (!same || offr) {
6976 for (i=size-1; i >= 0; i--)
6977 movLeft2Result (left, i, result, offr + i);
6981 case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6983 shiftLeft_Left2ResultLit (left, result, 8 * offr);
6984 shiftLeft_Left2ResultLit (result, result, shCount);
6985 return; /* prevent clearing result again */
6988 for (i=0; i < size; i++) {
6989 if (same && !offr) {
6990 emitpcode (POC_RLF, popGet (AOP(left), i));
6992 emitpcode (POC_RLFW, popGet (AOP(left), i));
6993 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6999 case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
7000 /* works in-place/with offr as well */
7001 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
7002 emitpcode (POC_ANDLW, popGetLit (0xF0));
7003 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
7005 for (i = size - 2; i >= 0; i--)
7007 emitpcode (POC_SWAPFW, popGet (AOP(left), i));
7008 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7009 emitpcode (POC_ANDLW, popGetLit (0x0F));
7010 emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
7011 emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
7015 case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
7016 /* works in-place/with offr as well */
7017 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
7018 for (i = size-2; i >= 0; i--) {
7019 emitpcode (POC_RRFW, popGet (AOP(left), i));
7020 emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
7022 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7023 emitpcode (POC_RRF, popGet (AOP(result), offr));
7027 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
7028 shiftLeft_Left2ResultLit (result, result, 1);
7029 return; /* prevent clearing result again */
7035 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7039 /*-----------------------------------------------------------------*/
7040 /* shiftRight_Left2ResultLit - shift right by known count */
7041 /*-----------------------------------------------------------------*/
7043 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
7045 int size, same, offr, i;
7047 size = AOP_SIZE(left);
7048 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7050 same = pic14_sameRegs (AOP(left), AOP(result));
7053 shCount = shCount & 0x07;
7061 case 0: /* takes 0 or 2N cycles (for offr==0) */
7062 if (!same || offr) {
7063 for (i=0; i < size; i++)
7064 movLeft2Result (left, i + offr, result, i);
7068 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7069 emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7071 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7072 shiftRight_Left2ResultLit (result, result, shCount, sign);
7073 return; /* prevent sign-extending result again */
7077 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7080 for (i = size-1; i >= 0; i--) {
7081 if (same && !offr) {
7082 emitpcode (POC_RRF, popGet (AOP(left), i));
7084 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7085 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7091 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7092 /* works in-place/with offr as well */
7093 emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7094 emitpcode (POC_ANDLW, popGetLit (0x0F));
7095 emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7097 for (i = 1; i < size; i++)
7099 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7100 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7101 emitpcode (POC_ANDLW, popGetLit (0xF0));
7102 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7103 emitpcode (POC_XORWF, popGet (AOP(result), i));
7108 emitpcode (POC_MOVLW, popGetLit (0xF0));
7109 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7110 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7114 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7115 /* works in-place/with offr as well */
7116 emitpcode (POC_RLFW, popGet (AOP(left), offr));
7117 for (i = 0; i < size-1; i++) {
7118 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7119 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7121 emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7123 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7126 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7131 shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7132 shiftRight_Left2ResultLit (result, result, 1, sign);
7133 return; /* prevent sign extending result again */
7138 addSign (result, size, sign);
7142 /*-----------------------------------------------------------------*/
7143 /* shiftL2Left2Result - shift left two bytes from left to result */
7144 /*-----------------------------------------------------------------*/
7145 static void shiftL2Left2Result (operand *left, int offl,
7146 operand *result, int offr, int shCount)
7150 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7152 if(pic14_sameRegs(AOP(result), AOP(left))) {
7160 emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7161 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7162 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7166 emitpcode(POC_RLF, popGet(AOP(result),offr));
7167 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7173 emitpcode(POC_MOVLW, popGetLit(0x0f));
7174 emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7175 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7176 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7177 emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7178 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7179 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7181 emitpcode(POC_RLF, popGet(AOP(result),offr));
7182 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7186 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7187 emitpcode(POC_RRF, popGet(AOP(result),offr));
7188 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7189 emitpcode(POC_RRF, popGet(AOP(result),offr));
7190 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7191 emitpcode(POC_ANDLW,popGetLit(0xc0));
7192 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7193 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7194 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7195 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7198 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7199 emitpcode(POC_RRFW, popGet(AOP(result),offr));
7200 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7201 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7202 emitpcode(POC_RRF, popGet(AOP(result),offr));
7212 /* note, use a mov/add for the shift since the mov has a
7213 chance of getting optimized out */
7214 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7215 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7216 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7217 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7218 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7222 emitpcode(POC_RLF, popGet(AOP(result),offr));
7223 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7229 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7230 emitpcode(POC_ANDLW, popGetLit(0xF0));
7231 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7232 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7233 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7234 emitpcode(POC_ANDLW, popGetLit(0xF0));
7235 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7236 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7240 emitpcode(POC_RLF, popGet(AOP(result),offr));
7241 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7245 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7246 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7247 emitpcode(POC_RRFW, popGet(AOP(result),offl));
7248 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7250 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7251 emitpcode(POC_RRF, popGet(AOP(result),offr));
7252 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7253 emitpcode(POC_ANDLW,popGetLit(0xc0));
7254 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7255 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7256 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7257 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7260 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7261 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7262 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7263 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7264 emitpcode(POC_RRF, popGet(AOP(result),offr));
7270 /*-----------------------------------------------------------------*/
7271 /* shiftR2Left2Result - shift right two bytes from left to result */
7272 /*-----------------------------------------------------------------*/
7273 static void shiftR2Left2Result (operand *left, int offl,
7274 operand *result, int offr,
7275 int shCount, int sign)
7280 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7281 same = pic14_sameRegs(AOP(result), AOP(left));
7283 if(same && ((offl + MSB16) == offr)){
7285 /* don't crash result[offr] */
7286 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7287 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7290 movLeft2Result(left,offl, result, offr);
7291 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7294 /* a:x >> shCount (x = lsb(result))*/
7297 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7299 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7308 emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7313 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7314 emitpcode(POC_RRF,popGet(AOP(result),offr));
7316 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7317 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7318 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7319 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7324 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7327 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7328 emitpcode(POC_RRF,popGet(AOP(result),offr));
7335 emitpcode(POC_MOVLW, popGetLit(0xf0));
7336 emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7337 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7339 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7340 emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7341 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7342 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7344 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7345 emitpcode(POC_ANDLW, popGetLit(0x0f));
7346 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7348 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7349 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7350 emitpcode(POC_ANDLW, popGetLit(0xf0));
7351 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7352 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7356 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7357 emitpcode(POC_RRF, popGet(AOP(result),offr));
7361 emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7362 emitpcode(POC_BTFSC,
7363 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7364 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7372 emitpcode(POC_RLF, popGet(AOP(result),offr));
7373 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7375 emitpcode(POC_RLF, popGet(AOP(result),offr));
7376 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7377 emitpcode(POC_RLFW, popGet(AOP(result),offr));
7378 emitpcode(POC_ANDLW,popGetLit(0x03));
7380 emitpcode(POC_BTFSC,
7381 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7382 emitpcode(POC_IORLW,popGetLit(0xfc));
7384 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7385 emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7386 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7387 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7389 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7390 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7391 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7392 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7393 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7394 emitpcode(POC_RLF, popGet(AOP(result),offr));
7395 emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7396 emitpcode(POC_ANDLW,popGetLit(0x03));
7398 emitpcode(POC_BTFSC,
7399 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7400 emitpcode(POC_IORLW,popGetLit(0xfc));
7402 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7403 //emitpcode(POC_RLF, popGet(AOP(result),offr));
7410 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7411 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7412 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7413 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7416 emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7418 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7422 /*-----------------------------------------------------------------*/
7423 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7424 /*-----------------------------------------------------------------*/
7425 static void shiftLLeftOrResult (operand *left, int offl,
7426 operand *result, int offr, int shCount)
7429 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7431 /* shift left accumulator */
7432 AccLsh(left,offl,shCount);
7433 /* or with result */
7434 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7435 assert ( !"broken (modifies left, fails for left==result))" );
7438 /*-----------------------------------------------------------------*/
7439 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7440 /*-----------------------------------------------------------------*/
7441 static void shiftRLeftOrResult (operand *left, int offl,
7442 operand *result, int offr, int shCount)
7445 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7447 /* shift right accumulator */
7448 AccRsh(left,offl,shCount);
7449 /* or with result */
7450 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7451 assert ( !"broken (modifies left, fails for left==result))" );
7454 /*-----------------------------------------------------------------*/
7455 /* genlshOne - left shift a one byte quantity by known count */
7456 /*-----------------------------------------------------------------*/
7457 static void genlshOne (operand *result, operand *left, int shCount)
7460 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7461 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7464 /*-----------------------------------------------------------------*/
7465 /* genlshTwo - left shift two bytes by known amount != 0 */
7466 /*-----------------------------------------------------------------*/
7467 static void genlshTwo (operand *result,operand *left, int shCount)
7472 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7473 size = pic14_getDataSize(result);
7475 /* if shCount >= 8 */
7481 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7483 movLeft2Result(left, LSB, result, MSB16);
7485 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7488 /* 1 <= shCount <= 7 */
7491 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7493 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7497 /*-----------------------------------------------------------------*/
7498 /* shiftLLong - shift left one long from left to result */
7499 /* offl = LSB or MSB16 */
7500 /*-----------------------------------------------------------------*/
7501 static void shiftLLong (operand *left, operand *result, int offr )
7504 int size = AOP_SIZE(result);
7507 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7508 if(size >= LSB+offr){
7509 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7511 pic14_emitcode("add","a,acc");
7512 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7513 size >= MSB16+offr && offr != LSB )
7514 pic14_emitcode("xch","a,%s",
7515 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7517 aopPut(AOP(result),"a",LSB+offr);
7520 if(size >= MSB16+offr){
7521 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7522 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7525 pic14_emitcode("rlc","a");
7526 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7527 size >= MSB24+offr && offr != LSB)
7528 pic14_emitcode("xch","a,%s",
7529 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7531 aopPut(AOP(result),"a",MSB16+offr);
7534 if(size >= MSB24+offr){
7535 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7536 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7539 pic14_emitcode("rlc","a");
7540 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7541 size >= MSB32+offr && offr != LSB )
7542 pic14_emitcode("xch","a,%s",
7543 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7545 aopPut(AOP(result),"a",MSB24+offr);
7548 if(size > MSB32+offr){
7549 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7550 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7553 pic14_emitcode("rlc","a");
7554 aopPut(AOP(result),"a",MSB32+offr);
7557 aopPut(AOP(result),zero,LSB);
7560 /*-----------------------------------------------------------------*/
7561 /* genlshFour - shift four byte by a known amount != 0 */
7562 /*-----------------------------------------------------------------*/
7563 static void genlshFour (operand *result, operand *left, int shCount)
7568 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7569 size = AOP_SIZE(result);
7571 /* if shifting more that 3 bytes */
7572 if (shCount >= 24 ) {
7575 /* lowest order of left goes to the highest
7576 order of the destination */
7577 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7579 movLeft2Result(left, LSB, result, MSB32);
7580 aopPut(AOP(result),zero,LSB);
7581 aopPut(AOP(result),zero,MSB16);
7582 aopPut(AOP(result),zero,MSB32);
7586 /* more than two bytes */
7587 else if ( shCount >= 16 ) {
7588 /* lower order two bytes goes to higher order two bytes */
7590 /* if some more remaining */
7592 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7594 movLeft2Result(left, MSB16, result, MSB32);
7595 movLeft2Result(left, LSB, result, MSB24);
7597 aopPut(AOP(result),zero,MSB16);
7598 aopPut(AOP(result),zero,LSB);
7602 /* if more than 1 byte */
7603 else if ( shCount >= 8 ) {
7604 /* lower order three bytes goes to higher order three bytes */
7608 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7610 movLeft2Result(left, LSB, result, MSB16);
7612 else{ /* size = 4 */
7614 movLeft2Result(left, MSB24, result, MSB32);
7615 movLeft2Result(left, MSB16, result, MSB24);
7616 movLeft2Result(left, LSB, result, MSB16);
7617 aopPut(AOP(result),zero,LSB);
7619 else if(shCount == 1)
7620 shiftLLong(left, result, MSB16);
7622 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7623 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7624 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7625 aopPut(AOP(result),zero,LSB);
7630 /* 1 <= shCount <= 7 */
7631 else if(shCount <= 2){
7632 shiftLLong(left, result, LSB);
7634 shiftLLong(result, result, LSB);
7636 /* 3 <= shCount <= 7, optimize */
7638 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7639 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7640 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7646 /*-----------------------------------------------------------------*/
7647 /* genLeftShiftLiteral - left shifting by known count */
7648 /*-----------------------------------------------------------------*/
7649 static void genLeftShiftLiteral (operand *left,
7654 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7658 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7659 freeAsmop(right,NULL,ic,TRUE);
7661 aopOp(left,ic,FALSE);
7662 aopOp(result,ic,FALSE);
7664 size = getSize(operandType(result));
7667 pic14_emitcode("; shift left ","result %d, left %d",size,
7671 /* I suppose that the left size >= result size */
7674 movLeft2Result(left, size, result, size);
7678 else if(shCount >= (size * 8))
7680 aopPut(AOP(result),zero,size);
7684 genlshOne (result,left,shCount);
7689 genlshTwo (result,left,shCount);
7693 genlshFour (result,left,shCount);
7697 freeAsmop(left,NULL,ic,TRUE);
7698 freeAsmop(result,NULL,ic,TRUE);
7702 /*-----------------------------------------------------------------*
7703 * genMultiAsm - repeat assembly instruction for size of register.
7704 * if endian == 1, then the high byte (i.e base address + size of
7705 * register) is used first else the low byte is used first;
7706 *-----------------------------------------------------------------*/
7707 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7713 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7726 emitpcode(poc, popGet(AOP(reg),offset));
7733 /*-----------------------------------------------------------------*/
7734 /* genLeftShift - generates code for left shifting */
7735 /*-----------------------------------------------------------------*/
7736 static void genLeftShift (iCode *ic)
7738 operand *left,*right, *result;
7740 unsigned long lit = 0L;
7742 symbol *tlbl , *tlbl1;
7746 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7748 right = IC_RIGHT(ic);
7750 result = IC_RESULT(ic);
7752 aopOp(right,ic,FALSE);
7753 aopOp(left,ic,FALSE);
7754 aopOp(result,ic,FALSE);
7757 /* if the shift count is known then do it
7758 as efficiently as possible */
7759 if (AOP_TYPE(right) == AOP_LIT) {
7760 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7764 /* shift count is unknown then we have to form
7765 a loop get the loop count in B : Note: we take
7766 only the lower order byte since shifting
7767 more that 32 bits make no sense anyway, ( the
7768 largest size of an object can be only 32 bits ) */
7770 /* this code fails for RIGHT == RESULT */
7771 assert (!pic14_sameRegs (AOP(right), AOP(result)));
7773 /* now move the left to the result if they are not the
7775 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
7776 AOP_SIZE(result) > 1) {
7778 size = AOP_SIZE(result);
7781 l = aopGet(AOP(left),offset,FALSE,TRUE);
7782 if (*l == '@' && (IS_AOP_PREG(result))) {
7784 pic14_emitcode("mov","a,%s",l);
7785 aopPut(AOP(result),"a",offset);
7787 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
7788 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7789 //aopPut(AOP(result),l,offset);
7795 if(AOP_TYPE(left) == AOP_LIT)
7796 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7798 size = AOP_SIZE(result);
7800 /* if it is only one byte then */
7802 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7803 emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7804 emitpcode(POC_ANDLW, popGetLit(0xf0));
7805 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7806 emitpcode(POC_MOVFW, popGet(AOP(left),0));
7807 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7808 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7809 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7810 emitpcode(POC_RLFW, popGet(AOP(result),0));
7811 emitpcode(POC_ANDLW, popGetLit(0xfe));
7812 emitpcode(POC_ADDFW, popGet(AOP(result),0));
7813 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7814 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7817 tlbl = newiTempLabel(NULL);
7818 if (!pic14_sameRegs(AOP(left),AOP(result))) {
7819 mov2w (AOP(left), 0);
7820 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7823 emitpcode(POC_COMFW, popGet(AOP(right),0));
7824 emitpcode(POC_RRF, popGet(AOP(result),0));
7825 emitpLabel(tlbl->key);
7826 emitpcode(POC_RLF, popGet(AOP(result),0));
7827 emitpcode(POC_ADDLW, popGetLit(1));
7829 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7834 if (pic14_sameRegs(AOP(left),AOP(result))) {
7836 tlbl = newiTempLabel(NULL);
7837 emitpcode(POC_COMFW, popGet(AOP(right),0));
7838 genMultiAsm(POC_RRF, result, size,1);
7839 emitpLabel(tlbl->key);
7840 genMultiAsm(POC_RLF, result, size,0);
7841 emitpcode(POC_ADDLW, popGetLit(1));
7843 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7847 //tlbl = newiTempLabel(NULL);
7849 //tlbl1 = newiTempLabel(NULL);
7851 //reAdjustPreg(AOP(result));
7853 //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7854 //pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7855 //l = aopGet(AOP(result),offset,FALSE,FALSE);
7857 //pic14_emitcode("add","a,acc");
7858 //aopPut(AOP(result),"a",offset++);
7860 // l = aopGet(AOP(result),offset,FALSE,FALSE);
7862 // pic14_emitcode("rlc","a");
7863 // aopPut(AOP(result),"a",offset++);
7865 //reAdjustPreg(AOP(result));
7867 //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7868 //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7871 tlbl = newiTempLabel(NULL);
7872 tlbl1= newiTempLabel(NULL);
7874 size = AOP_SIZE(result);
7877 pctemp = popGetTempReg(); /* grab a temporary working register. */
7879 emitpcode(POC_MOVFW, popGet(AOP(right),0));
7881 /* offset should be 0, 1 or 3 */
7882 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7884 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
7886 emitpcode(POC_MOVWF, pctemp);
7889 emitpLabel(tlbl->key);
7892 emitpcode(POC_RLF, popGet(AOP(result),0));
7894 emitpcode(POC_RLF, popGet(AOP(result),offset++));
7896 emitpcode(POC_DECFSZ, pctemp);
7897 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7898 emitpLabel(tlbl1->key);
7900 popReleaseTempReg(pctemp);
7904 freeAsmop (right,NULL,ic,TRUE);
7905 freeAsmop(left,NULL,ic,TRUE);
7906 freeAsmop(result,NULL,ic,TRUE);
7911 /*-----------------------------------------------------------------*/
7912 /* genrshOne - right shift a one byte quantity by known count */
7913 /*-----------------------------------------------------------------*/
7914 static void genrshOne (operand *result, operand *left,
7915 int shCount, int sign)
7918 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7919 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7922 /*-----------------------------------------------------------------*/
7923 /* genrshTwo - right shift two bytes by known amount != 0 */
7924 /*-----------------------------------------------------------------*/
7925 static void genrshTwo (operand *result,operand *left,
7926 int shCount, int sign)
7929 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7930 /* if shCount >= 8 */
7934 shiftR1Left2Result(left, MSB16, result, LSB,
7937 movLeft2Result(left, MSB16, result, LSB);
7939 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7942 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7943 emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7947 /* 1 <= shCount <= 7 */
7949 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
7952 /*-----------------------------------------------------------------*/
7953 /* shiftRLong - shift right one long from left to result */
7954 /* offl = LSB or MSB16 */
7955 /*-----------------------------------------------------------------*/
7956 static void shiftRLong (operand *left, int offl,
7957 operand *result, int sign)
7962 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7964 size = AOP_SIZE(left);
7965 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7968 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7972 assert (offl >= 0 && offl < size);
7974 same = pic14_sameRegs (AOP(left), AOP(result));
7976 /* perform the shift */
7979 if (same && !offl) {
7980 emitpcode (POC_RRF, popGet (AOP(result), size));
7982 emitpcode (POC_RRFW, popGet (AOP(left), size));
7983 emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7987 addSign (result, AOP_SIZE(left) - offl, sign);
7990 /*-----------------------------------------------------------------*/
7991 /* genrshFour - shift four byte by a known amount != 0 */
7992 /*-----------------------------------------------------------------*/
7993 static void genrshFour (operand *result, operand *left,
7994 int shCount, int sign)
7997 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7998 /* if shifting more that 3 bytes */
7999 if(shCount >= 24 ) {
8002 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8004 movLeft2Result(left, MSB32, result, LSB);
8006 addSign(result, MSB16, sign);
8008 else if(shCount >= 16){
8011 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8013 movLeft2Result(left, MSB24, result, LSB);
8014 movLeft2Result(left, MSB32, result, MSB16);
8016 addSign(result, MSB24, sign);
8018 else if(shCount >= 8){
8021 shiftRLong(left, MSB16, result, sign);
8022 else if(shCount == 0){
8023 movLeft2Result(left, MSB16, result, LSB);
8024 movLeft2Result(left, MSB24, result, MSB16);
8025 movLeft2Result(left, MSB32, result, MSB24);
8026 addSign(result, MSB32, sign);
8029 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8030 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8031 /* the last shift is signed */
8032 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8033 addSign(result, MSB32, sign);
8036 else{ /* 1 <= shCount <= 7 */
8038 shiftRLong(left, LSB, result, sign);
8040 shiftRLong(result, LSB, result, sign);
8043 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8044 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8045 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8050 /*-----------------------------------------------------------------*/
8051 /* genRightShiftLiteral - right shifting by known count */
8052 /*-----------------------------------------------------------------*/
8053 static void genRightShiftLiteral (operand *left,
8059 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8063 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8064 freeAsmop(right,NULL,ic,TRUE);
8066 aopOp(left,ic,FALSE);
8067 aopOp(result,ic,FALSE);
8070 pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8074 lsize = pic14_getDataSize(left);
8075 res_size = pic14_getDataSize(result);
8076 /* test the LEFT size !!! */
8078 /* I suppose that the left size >= result size */
8081 movLeft2Result(left, res_size, result, res_size);
8084 else if(shCount >= (lsize * 8)){
8087 emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8089 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8090 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8095 emitpcode(POC_MOVLW, popGetLit(0));
8096 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8097 emitpcode(POC_MOVLW, popGetLit(0xff));
8099 emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8104 emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8111 genrshOne (result,left,shCount,sign);
8115 genrshTwo (result,left,shCount,sign);
8119 genrshFour (result,left,shCount,sign);
8127 freeAsmop(left,NULL,ic,TRUE);
8128 freeAsmop(result,NULL,ic,TRUE);
8133 /*-----------------------------------------------------------------*/
8134 /* genSignedRightShift - right shift of signed number */
8135 /*-----------------------------------------------------------------*/
8136 static void genSignedRightShift (iCode *ic)
8138 operand *right, *left, *result;
8141 symbol *tlbl, *tlbl1 ;
8144 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8146 /* we do it the hard way put the shift count in b
8147 and loop thru preserving the sign */
8149 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8151 right = IC_RIGHT(ic);
8153 result = IC_RESULT(ic);
8155 aopOp(right,ic,FALSE);
8156 aopOp(left,ic,FALSE);
8157 aopOp(result,ic,FALSE);
8160 if ( AOP_TYPE(right) == AOP_LIT) {
8161 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8162 //genRightShiftLiteral (left,right,result,ic,1);
8165 /* shift count is unknown then we have to form
8166 a loop get the loop count in B : Note: we take
8167 only the lower order byte since shifting
8168 more that 32 bits make no sense anyway, ( the
8169 largest size of an object can be only 32 bits ) */
8171 //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8172 //pic14_emitcode("inc","b");
8173 //freeAsmop (right,NULL,ic,TRUE);
8174 //aopOp(left,ic,FALSE);
8175 //aopOp(result,ic,FALSE);
8177 /* now move the left to the result if they are not the
8179 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
8180 AOP_SIZE(result) > 1) {
8182 size = AOP_SIZE(result);
8186 l = aopGet(AOP(left),offset,FALSE,TRUE);
8187 if (*l == '@' && IS_AOP_PREG(result)) {
8188 pic14_emitcode("mov","a,%s",l);
8189 aopPut(AOP(result),"a",offset);
8191 aopPut(AOP(result),l,offset);
8193 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8194 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8200 /* mov the highest order bit to OVR */
8201 tlbl = newiTempLabel(NULL);
8202 tlbl1= newiTempLabel(NULL);
8204 size = AOP_SIZE(result);
8207 pctemp = popGetTempReg(); /* grab a temporary working register. */
8209 emitpcode(POC_MOVFW, popGet(AOP(right),0));
8211 /* offset should be 0, 1 or 3 */
8212 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8214 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8216 emitpcode(POC_MOVWF, pctemp);
8219 emitpLabel(tlbl->key);
8221 emitpcode(POC_RLFW, popGet(AOP(result),offset));
8222 emitpcode(POC_RRF, popGet(AOP(result),offset));
8225 emitpcode(POC_RRF, popGet(AOP(result),--offset));
8228 emitpcode(POC_DECFSZ, pctemp);
8229 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8230 emitpLabel(tlbl1->key);
8232 popReleaseTempReg(pctemp);
8234 size = AOP_SIZE(result);
8236 pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8237 pic14_emitcode("rlc","a");
8238 pic14_emitcode("mov","ov,c");
8239 /* if it is only one byte then */
8241 l = aopGet(AOP(left),0,FALSE,FALSE);
8243 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8244 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8245 pic14_emitcode("mov","c,ov");
8246 pic14_emitcode("rrc","a");
8247 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8248 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8249 aopPut(AOP(result),"a",0);
8253 reAdjustPreg(AOP(result));
8254 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8255 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8256 pic14_emitcode("mov","c,ov");
8258 l = aopGet(AOP(result),offset,FALSE,FALSE);
8260 pic14_emitcode("rrc","a");
8261 aopPut(AOP(result),"a",offset--);
8263 reAdjustPreg(AOP(result));
8264 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8265 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8270 freeAsmop(left,NULL,ic,TRUE);
8271 freeAsmop(result,NULL,ic,TRUE);
8272 freeAsmop(right,NULL,ic,TRUE);
8276 /*-----------------------------------------------------------------*/
8277 /* loadSignToC - load the operand's sign bit into CARRY */
8278 /*-----------------------------------------------------------------*/
8280 static void loadSignToC (operand *op)
8283 assert (op && AOP(op) && AOP_SIZE(op));
8286 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8290 /*-----------------------------------------------------------------*/
8291 /* genRightShift - generate code for right shifting */
8292 /*-----------------------------------------------------------------*/
8293 static void genGenericShift (iCode *ic, int shiftRight)
8295 operand *right, *left, *result;
8298 symbol *tlbl, *tlbl1, *inverselbl;
8301 /* if signed then we do it the hard way preserve the
8302 sign bit moving it inwards */
8303 retype = getSpec(operandType(IC_RESULT(ic)));
8304 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8306 /* signed & unsigned types are treated the same : i.e. the
8307 signed is NOT propagated inwards : quoting from the
8308 ANSI - standard : "for E1 >> E2, is equivalent to division
8309 by 2**E2 if unsigned or if it has a non-negative value,
8310 otherwise the result is implementation defined ", MY definition
8311 is that the sign does not get propagated */
8313 right = IC_RIGHT(ic);
8315 result = IC_RESULT(ic);
8317 aopOp(right,ic,FALSE);
8318 aopOp(left,ic,FALSE);
8319 aopOp(result,ic,FALSE);
8321 /* if the shift count is known then do it
8322 as efficiently as possible */
8323 if (AOP_TYPE(right) == AOP_LIT) {
8324 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8328 shiftRight = !shiftRight;
8332 shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8334 shiftLeft_Left2ResultLit (left, result, lit);
8335 //genRightShiftLiteral (left,right,result,ic, 0);
8339 /* shift count is unknown then we have to form
8340 a loop get the loop count in B : Note: we take
8341 only the lower order byte since shifting
8342 more that 32 bits make no sense anyway, ( the
8343 largest size of an object can be only 32 bits ) */
8345 /* we must not overwrite the shift counter */
8346 assert (!pic14_sameRegs(AOP(right),AOP(result)));
8348 /* now move the left to the result if they are not the
8350 if (!pic14_sameRegs(AOP(left),AOP(result)))
8352 size = min(AOP_SIZE(result), AOP_SIZE(left));
8354 mov2w(AOP(left), size);
8355 movwf(AOP(result), size);
8357 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8360 tlbl = newiTempLabel(NULL);
8361 tlbl1= newiTempLabel(NULL);
8363 size = AOP_SIZE(result);
8365 mov2w(AOP(right),0);
8366 if (!SPEC_USIGN(operandType(right)))
8368 inverselbl = newiTempLabel(NULL);
8369 /* signed shift count -- invert shift direction for c<0 */
8370 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8371 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8373 emitpcode(POC_SUBLW, popGetLit(0)); /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8374 /* check for `a = b >> c' with `-c == 0' */
8376 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8377 emitpLabel(tlbl->key);
8378 /* propagate the sign bit inwards for SIGNED result */
8379 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8380 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8381 emitpcode(POC_ADDLW, popGetLit(1)); /* clears CARRY (unless W==0 afterwards) */
8383 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8385 if (!SPEC_USIGN(operandType(right)))
8387 symbol *inv_loop = newiTempLabel(NULL);
8389 shiftRight = !shiftRight; /* invert shift direction */
8391 /* we came here from the code above -- we are done */
8392 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8394 /* emit code for shifting N<0 steps, count is already in W */
8395 emitpLabel(inverselbl->key);
8396 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8397 emitpLabel(inv_loop->key);
8398 /* propagate the sign bit inwards for SIGNED result */
8399 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8400 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8401 emitpcode(POC_ADDLW, popGetLit(1));
8403 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8406 emitpLabel(tlbl1->key);
8408 freeAsmop(left,NULL,ic,TRUE);
8409 freeAsmop (right,NULL,ic,TRUE);
8410 freeAsmop(result,NULL,ic,TRUE);
8413 static void genRightShift (iCode *ic)
8415 genGenericShift(ic, 1);
8418 static void genLeftShift (iCode *ic)
8420 genGenericShift(ic, 0);
8423 /*-----------------------------------------------------------------*/
8424 /* SetIrp - Set IRP bit */
8425 /*-----------------------------------------------------------------*/
8426 void SetIrp(operand *result) {
8428 if (AOP_TYPE(result) == AOP_LIT) {
8429 unsigned lit = (unsigned)operandLitValue(result);
8435 if (PCOP(AOP(result))->type == PO_LITERAL) {
8436 int addrs = PCOL(AOP(result))->lit;
8442 emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8443 if(AOP_SIZE(result) > 1) {
8444 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8452 setup_fsr (operand *ptr)
8455 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8457 /* also setup-up IRP */
8461 /*-----------------------------------------------------------------*/
8462 /* emitPtrByteGet - emits code to get a byte into WREG from an */
8463 /* arbitrary pointer (__code, __data, generic) */
8464 /*-----------------------------------------------------------------*/
8466 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8473 if (!alreadyAddressed) setup_fsr (src);
8474 emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8478 assert( AOP_SIZE(src) == 2 );
8480 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8482 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8483 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
8484 call_libraryfunc ("__gptrget1");
8488 assert( AOP_SIZE(src) == 3 );
8490 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8492 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8494 call_libraryfunc ("__gptrget1");
8498 assert( !"unhandled pointer type" );
8503 /*-----------------------------------------------------------------*/
8504 /* emitPtrByteSet - emits code to set a byte from src through a */
8505 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR). */
8506 /*-----------------------------------------------------------------*/
8508 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8515 if (!alreadyAddressed) setup_fsr (dst);
8516 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8520 assert( !"trying to assign to __code pointer" );
8524 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8526 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8528 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8530 call_libraryfunc ("__gptrput1");
8534 assert( !"unhandled pointer type" );
8539 /*-----------------------------------------------------------------*/
8540 /* genUnpackBits - generates code for unpacking bits */
8541 /*-----------------------------------------------------------------*/
8542 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8544 int rsize; /* result size */
8545 sym_link *etype; /* bitfield type information */
8546 int blen; /* bitfield length */
8547 int bstr; /* bitfield starting bit within byte */
8550 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8551 etype = getSpec(operandType(result));
8552 rsize = getSize (operandType (result));
8553 blen = SPEC_BLEN (etype);
8554 bstr = SPEC_BSTR (etype);
8556 /* single bit field case */
8558 if (ifx) { /* that is for an if statement */
8561 resolveIfx(&rIfx,ifx);
8562 if (ptype == -1) /* direct */
8563 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8565 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8566 emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8567 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8571 assert (!pic14_sameRegs (AOP(result), AOP(left)));
8572 for (i=0; i < AOP_SIZE(result); i++)
8573 emitpcode (POC_CLRF, popGet (AOP(result), i));
8578 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8579 /* adjust result below */
8586 emitPtrByteGet (left, ptype, FALSE);
8587 emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8589 /* adjust result below */
8593 assert( !"unhandled pointer type" );
8596 /* move sign-/zero extended bit to result */
8597 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8598 emitpcode (POC_INCF, popGet (AOP(result), 0));
8600 emitpcode (POC_DECF, popGet (AOP(result), 0));
8602 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8606 else if (blen <= 8 && ((blen + bstr) <= 8))
8611 for (i=0; i < AOP_SIZE(result); i++)
8612 emitpcode (POC_CLRF, popGet (AOP(result), i));
8617 mov2w(AOP(left), 0);
8624 emitPtrByteGet (left, ptype, FALSE);
8628 assert( !"unhandled pointer type" );
8632 emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8633 movwf(AOP(result), 0);
8634 AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8636 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8638 /* signed bitfield */
8639 assert (bstr + blen > 0);
8640 emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8641 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8642 emitpcode(POC_IORWF, popGet(AOP(result),0));
8644 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8648 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8652 /*-----------------------------------------------------------------*/
8653 /* genDataPointerGet - generates code when ptr offset is known */
8654 /*-----------------------------------------------------------------*/
8655 static void genDataPointerGet (operand *left,
8659 int size , offset = 0;
8662 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8665 /* optimization - most of the time, left and result are the same
8666 * address, but different types. for the pic code, we could omit
8669 aopOp(result,ic,TRUE);
8671 if (pic14_sameRegs (AOP(left), AOP(result)))
8674 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8676 //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8678 size = AOP_SIZE(result);
8679 if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8683 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8684 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8688 freeAsmop(left,NULL,ic,TRUE);
8689 freeAsmop(result,NULL,ic,TRUE);
8693 /*-----------------------------------------------------------------*/
8694 /* genNearPointerGet - pic14_emitcode for near pointer fetch */
8695 /*-----------------------------------------------------------------*/
8696 static void genNearPointerGet (operand *left,
8701 sym_link *ltype = operandType(left);
8702 sym_link *rtype = operandType(result);
8703 sym_link *retype= getSpec(rtype); /* bitfield type information */
8707 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8710 aopOp(left,ic,FALSE);
8712 /* if left is rematerialisable and
8713 result is not bit variable type and
8714 the left is pointer to data space i.e
8715 lower 128 bytes of space */
8716 if (AOP_TYPE(left) == AOP_PCODE && //AOP_TYPE(left) == AOP_IMMD &&
8717 !IS_BITVAR(retype) &&
8718 PIC_IS_DATA_PTR(ltype)) {
8719 genDataPointerGet (left,result,ic);
8723 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8724 aopOp (result,ic,FALSE);
8726 /* Check if can access directly instead of via a pointer */
8727 if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8728 && AOP_SIZE(result) == 1)
8733 if (IS_BITFIELD(getSpec(operandType(result))))
8735 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8739 /* If the pointer value is not in a the FSR then need to put it in */
8740 /* Must set/reset IRP bit for use with FSR. */
8745 /* if bitfield then unpack the bits */
8747 /* we have can just get the values */
8748 int size = AOP_SIZE(result);
8751 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8755 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8757 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8758 if (AOP_TYPE(result) == AOP_LIT) {
8759 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8761 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8763 if (size && !direct)
8764 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8769 /* now some housekeeping stuff */
8771 /* we had to allocate for this iCode */
8772 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8773 freeAsmop(NULL,aop,ic,TRUE);
8775 /* we did not allocate which means left
8776 already in a pointer register, then
8777 if size > 0 && this could be used again
8778 we have to point it back to where it
8780 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8781 if (AOP_SIZE(result) > 1 &&
8782 !OP_SYMBOL(left)->remat &&
8783 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8785 int size = AOP_SIZE(result) - 1;
8787 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8793 freeAsmop(left,NULL,ic,TRUE);
8794 freeAsmop(result,NULL,ic,TRUE);
8799 /*-----------------------------------------------------------------*/
8800 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch */
8801 /*-----------------------------------------------------------------*/
8802 static void genPagedPointerGet (operand *left,
8809 sym_link *rtype, *retype;
8812 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8814 rtype = operandType(result);
8815 retype= getSpec(rtype);
8817 aopOp(left,ic,FALSE);
8819 /* if the value is already in a pointer register
8820 then don't need anything more */
8821 if (!AOP_INPREG(AOP(left))) {
8822 /* otherwise get a free pointer register */
8824 preg = getFreePtr(ic,&aop,FALSE);
8825 pic14_emitcode("mov","%s,%s",
8827 aopGet(AOP(left),0,FALSE,TRUE));
8828 rname = preg->name ;
8830 rname = aopGet(AOP(left),0,FALSE,FALSE);
8832 freeAsmop(left,NULL,ic,TRUE);
8833 aopOp (result,ic,FALSE);
8835 /* if bitfield then unpack the bits */
8836 if (IS_BITFIELD(retype))
8837 genUnpackBits (result,left,rname,PPOINTER,0);
8839 /* we have can just get the values */
8840 int size = AOP_SIZE(result);
8845 pic14_emitcode("movx","a,@%s",rname);
8846 aopPut(AOP(result),"a",offset);
8851 pic14_emitcode("inc","%s",rname);
8855 /* now some housekeeping stuff */
8857 /* we had to allocate for this iCode */
8858 freeAsmop(NULL,aop,ic,TRUE);
8860 /* we did not allocate which means left
8861 already in a pointer register, then
8862 if size > 0 && this could be used again
8863 we have to point it back to where it
8865 if (AOP_SIZE(result) > 1 &&
8866 !OP_SYMBOL(left)->remat &&
8867 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8869 int size = AOP_SIZE(result) - 1;
8871 pic14_emitcode("dec","%s",rname);
8876 freeAsmop(result,NULL,ic,TRUE);
8881 /*-----------------------------------------------------------------*/
8882 /* genFarPointerGet - gget value from far space */
8883 /*-----------------------------------------------------------------*/
8884 static void genFarPointerGet (operand *left,
8885 operand *result, iCode *ic)
8888 sym_link *retype = getSpec(operandType(result));
8891 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8893 aopOp(left,ic,FALSE);
8895 /* if the operand is already in dptr
8896 then we do nothing else we move the value to dptr */
8897 if (AOP_TYPE(left) != AOP_STR) {
8898 /* if this is remateriazable */
8899 if (AOP_TYPE(left) == AOP_IMMD)
8900 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8901 else { /* we need to get it byte by byte */
8902 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8903 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8904 if (options.model == MODEL_FLAT24)
8906 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8910 /* so dptr know contains the address */
8911 freeAsmop(left,NULL,ic,TRUE);
8912 aopOp(result,ic,FALSE);
8914 /* if bit then unpack */
8915 if (IS_BITFIELD(retype))
8916 genUnpackBits(result,left,"dptr",FPOINTER,0);
8918 size = AOP_SIZE(result);
8922 pic14_emitcode("movx","a,@dptr");
8923 aopPut(AOP(result),"a",offset++);
8925 pic14_emitcode("inc","dptr");
8929 freeAsmop(result,NULL,ic,TRUE);
8934 /*-----------------------------------------------------------------*/
8935 /* genCodePointerGet - get value from code space */
8936 /*-----------------------------------------------------------------*/
8937 static void genCodePointerGet (operand *left,
8938 operand *result, iCode *ic)
8941 sym_link *retype = getSpec(operandType(result));
8943 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8945 aopOp(left,ic,FALSE);
8947 /* if the operand is already in dptr
8948 then we do nothing else we move the value to dptr */
8949 if (AOP_TYPE(left) != AOP_STR) {
8950 /* if this is remateriazable */
8951 if (AOP_TYPE(left) == AOP_IMMD)
8952 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8953 else { /* we need to get it byte by byte */
8954 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8955 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8956 if (options.model == MODEL_FLAT24)
8958 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8962 /* so dptr know contains the address */
8963 freeAsmop(left,NULL,ic,TRUE);
8964 aopOp(result,ic,FALSE);
8966 /* if bit then unpack */
8967 if (IS_BITFIELD(retype))
8968 genUnpackBits(result,left,"dptr",CPOINTER,0);
8970 size = AOP_SIZE(result);
8974 pic14_emitcode("clr","a");
8975 pic14_emitcode("movc","a,@a+dptr");
8976 aopPut(AOP(result),"a",offset++);
8978 pic14_emitcode("inc","dptr");
8982 freeAsmop(result,NULL,ic,TRUE);
8985 /*-----------------------------------------------------------------*/
8986 /* genGenPointerGet - gget value from generic pointer space */
8987 /*-----------------------------------------------------------------*/
8988 static void genGenPointerGet (operand *left,
8989 operand *result, iCode *ic)
8992 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8993 aopOp(left,ic,FALSE);
8994 aopOp(result,ic,FALSE);
8997 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8999 if (IS_BITFIELD(getSpec(operandType(result))))
9001 genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
9006 /* emit call to __gptrget */
9007 char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
9008 int size = AOP_SIZE(result);
9011 assert (size > 0 && size <= 4);
9013 /* pass arguments */
9014 assert (AOP_SIZE(left) == 3);
9015 mov2w(AOP(left), 0);
9016 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9017 mov2w(AOP(left), 1);
9018 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9019 mov2w(AOP(left), 2);
9020 call_libraryfunc (func[size]);
9023 movwf (AOP(result), --size);
9025 emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
9026 movwf (AOP(result), size);
9030 freeAsmop(left,NULL,ic,TRUE);
9031 freeAsmop(result,NULL,ic,TRUE);
9035 /*-----------------------------------------------------------------*/
9036 /* genConstPointerGet - get value from const generic pointer space */
9037 /*-----------------------------------------------------------------*/
9038 static void genConstPointerGet (operand *left,
9039 operand *result, iCode *ic)
9041 //sym_link *retype = getSpec(operandType(result));
9043 symbol *albl, *blbl;//, *clbl;
9050 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9051 aopOp(left,ic,FALSE);
9052 aopOp(result,ic,FALSE);
9054 size = AOP_SIZE(result);
9056 DEBUGpic14_AopType(__LINE__,left,NULL,result);
9058 DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
9060 lit = op_isLitLike (left);
9061 poc = lit ? POC_MOVLW : POC_MOVFW;
9063 if (IS_BITFIELD(getSpec(operandType(result))))
9065 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
9070 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
9071 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
9072 assert (size > 0 && size <= 4);
9075 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9077 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9078 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
9079 call_libraryfunc (func[size]);
9081 movwf(AOP(result),size-1);
9082 for (i = 1; i < size; i++)
9084 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
9085 movwf(AOP(result),size - 1 - i);
9090 freeAsmop(left,NULL,ic,TRUE);
9091 freeAsmop(result,NULL,ic,TRUE);
9094 /*-----------------------------------------------------------------*/
9095 /* genPointerGet - generate code for pointer get */
9096 /*-----------------------------------------------------------------*/
9097 static void genPointerGet (iCode *ic)
9099 operand *left, *result ;
9100 sym_link *type, *etype;
9104 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9107 result = IC_RESULT(ic) ;
9109 /* depending on the type of pointer we need to
9110 move it to the correct pointer register */
9111 type = operandType(left);
9112 etype = getSpec(type);
9114 if (IS_PTR_CONST(type))
9115 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9117 /* if left is of type of pointer then it is simple */
9118 if (IS_PTR(type) && !IS_FUNC(type->next))
9119 p_type = DCL_TYPE(type);
9121 /* we have to go by the storage class */
9122 p_type = PTR_TYPE(SPEC_OCLS(etype));
9124 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9126 if (SPEC_OCLS(etype)->codesp ) {
9127 DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9128 //p_type = CPOINTER ;
9131 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9132 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9133 /*p_type = FPOINTER ;*/
9135 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9136 DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9137 /* p_type = PPOINTER; */
9139 if (SPEC_OCLS(etype) == idata )
9140 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9141 /* p_type = IPOINTER; */
9143 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9144 /* p_type = POINTER ; */
9147 /* now that we have the pointer type we assign
9148 the pointer values */
9154 genNearPointerGet (left,result,ic);
9158 genPagedPointerGet(left,result,ic);
9162 genFarPointerGet (left,result,ic);
9166 genConstPointerGet (left,result,ic);
9170 genGenPointerGet (left,result,ic);
9173 assert ( !"unhandled pointer type" );
9179 /*-----------------------------------------------------------------*/
9180 /* genPackBits - generates code for packed bit storage */
9181 /*-----------------------------------------------------------------*/
9182 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9184 int blen; /* bitfield length */
9185 int bstr; /* bitfield starting bit within byte */
9186 int litval; /* source literal value (if AOP_LIT) */
9187 unsigned char mask; /* bitmask within current byte */
9190 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9192 blen = SPEC_BLEN (etype);
9193 bstr = SPEC_BSTR (etype);
9195 /* If the bitfield length is less than a byte and does not cross byte boundaries */
9196 if ((blen <= 8) && ((bstr + blen) <= 8))
9198 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9199 (unsigned char) (0xFF >> (8 - bstr)));
9201 if (AOP_TYPE (right) == AOP_LIT)
9203 /* Case with a bitfield length <8 and literal source */
9204 int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9211 if (AOP(result)->type == AOP_PCODE)
9212 pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9214 pcop = popGet(AOP(result),0);
9215 emitpcode(lit?POC_BSF:POC_BCF,pcop);
9221 emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9225 assert( !"trying to assign to bitfield via pointer to __code space" );
9229 emitPtrByteGet(result, p_type, FALSE);
9231 emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9233 emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9235 emitPtrByteSet(result, p_type, TRUE);
9239 assert( !"unhandled pointer type" );
9241 } // switch (p_type)
9244 litval = lit << bstr;
9245 litval &= (~mask) & 0x00ff;
9250 mov2w (AOP(result), 0);
9251 if ((litval|mask) != 0x00ff)
9252 emitpcode(POC_ANDLW, popGetLit (mask));
9254 emitpcode(POC_IORLW, popGetLit (litval));
9255 movwf (AOP(result), 0);
9261 emitPtrByteGet(result, p_type, FALSE);
9262 if ((litval|mask) != 0x00ff)
9263 emitpcode(POC_ANDLW, popGetLit (mask));
9265 emitpcode(POC_IORLW, popGetLit (litval));
9266 emitPtrByteSet(result, p_type, TRUE);
9270 assert( !"trying to assign to bitfield via pointer to __code space" );
9274 assert( !"unhandled pointer type" );
9281 /* right is no literal */
9286 /* Note more efficient code, of pre clearing bit then only setting it if required,
9287 * can only be done if it is known that the result is not a SFR */
9288 emitpcode(POC_RRFW,popGet(AOP(right),0));
9290 emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9292 emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9298 emitPtrByteGet (result, p_type, FALSE);
9299 emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9300 emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9301 emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9302 emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9303 emitPtrByteSet (result, p_type, TRUE);
9307 assert( !"trying to assign to bitfield via pointer to __code space" );
9311 assert( !"unhandled pointer type" );
9316 /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9317 pCodeOp *temp = popGetTempReg ();
9319 mov2w (AOP(right), 0);
9321 emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9323 emitpcode(POC_MOVWF, temp);
9325 AccLsh (temp, bstr);
9331 mov2w (AOP(result), 0);
9332 emitpcode(POC_ANDLW, popGetLit (mask));
9333 emitpcode(POC_IORFW, temp);
9334 movwf (AOP(result), 0);
9340 emitPtrByteGet (result, p_type, FALSE);
9341 emitpcode(POC_ANDLW, popGetLit (mask));
9342 emitpcode(POC_IORFW, temp);
9343 emitPtrByteSet (result, p_type, TRUE);
9347 assert( !"trying to assign to bitfield via pointer to __code space" );
9351 assert( !"unhandled pointer type" );
9355 popReleaseTempReg (temp);
9357 } // if (AOP(right)->type != AOP_LIT)
9359 } // if (blen <= 8 && ((blen + bstr) <= 8))
9361 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9365 bitpatternFromVal (value *val)
9372 assert (sizeof (float) == sizeof (uint32_t));
9374 //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));
9376 switch (SPEC_NOUN(val->type))
9380 return (unsigned long)floatFromVal (val);
9384 float_long.d = floatFromVal (val);
9385 return float_long.l;
9388 assert( !"unhandled value type" );
9392 float_long.d = floatFromVal (val);
9393 return float_long.l;
9396 /*-----------------------------------------------------------------*/
9397 /* genDataPointerSet - remat pointer to data space */
9398 /*-----------------------------------------------------------------*/
9399 static void genDataPointerSet(operand *right,
9403 int size, offset = 0 ;
9407 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9408 aopOp(right,ic,FALSE);
9409 aopOp(result,ic,FALSE);
9411 assert (IS_SYMOP(result));
9412 assert (IS_PTR(OP_SYM_TYPE(result)));
9414 size = AOP_SIZE(right);
9415 ressize = getSize(OP_SYM_ETYPE(result));
9416 if (size > ressize) size = ressize;
9417 //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9419 //assert( !"what's going on here?" );
9422 if ( AOP_TYPE(result) == AOP_PCODE) {
9423 fprintf(stderr,"genDataPointerSet %s, %d\n",
9424 AOP(result)->aopu.pcop->name,
9425 PCOI(AOP(result)->aopu.pcop)->offset);
9429 // tsd, was l+1 - the underline `_' prefix was being stripped
9431 emitpComment ("%s:%u: size=%d/%d, offset=%i", __FILE__,__LINE__, size, ressize, offset);
9433 if (AOP_TYPE(right) == AOP_LIT) {
9434 /* XXX: might be float... */
9435 unsigned int lit = bitpatternFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9436 lit = lit >> (8*offset);
9437 //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9439 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9440 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9442 emitpcode(POC_CLRF, popGet(AOP(result),offset));
9445 //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9446 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9447 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9453 freeAsmop(right,NULL,ic,TRUE);
9454 freeAsmop(result,NULL,ic,TRUE);
9457 /*-----------------------------------------------------------------*/
9458 /* genNearPointerSet - pic14_emitcode for near pointer put */
9459 /*-----------------------------------------------------------------*/
9460 static void genNearPointerSet (operand *right,
9465 sym_link *ptype = operandType(result);
9466 sym_link *retype = getSpec(operandType(right));
9467 sym_link *letype = getSpec(ptype);
9472 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9473 aopOp(result,ic,FALSE);
9476 /* if the result is rematerializable &
9477 in data space & not a bit variable */
9478 //if (AOP_TYPE(result) == AOP_IMMD &&
9479 if (AOP_TYPE(result) == AOP_PCODE &&
9480 PIC_IS_DATA_PTR(ptype) &&
9481 !IS_BITVAR (retype) &&
9482 !IS_BITVAR (letype)) {
9483 genDataPointerSet (right,result,ic);
9484 freeAsmop(result,NULL,ic,TRUE);
9489 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9490 aopOp(right,ic,FALSE);
9491 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9493 /* Check if can access directly instead of via a pointer */
9494 if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9498 if (IS_BITFIELD (letype))
9500 genPackBits (letype, result, right, direct?-1:POINTER);
9504 /* If the pointer value is not in a the FSR then need to put it in */
9505 /* Must set/reset IRP bit for use with FSR. */
9506 /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9511 /* we have can just get the values */
9512 int size = AOP_SIZE(right);
9515 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9517 char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9519 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9521 if (AOP_TYPE(right) == AOP_LIT) {
9522 emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9524 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9527 emitpcode(POC_MOVWF,popGet(AOP(result),0));
9529 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9531 if (size && !direct)
9532 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9537 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9538 /* now some housekeeping stuff */
9540 /* we had to allocate for this iCode */
9541 freeAsmop(NULL,aop,ic,TRUE);
9543 /* we did not allocate which means left
9544 already in a pointer register, then
9545 if size > 0 && this could be used again
9546 we have to point it back to where it
9548 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9549 if (AOP_SIZE(right) > 1 &&
9550 !OP_SYMBOL(result)->remat &&
9551 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9553 int size = AOP_SIZE(right) - 1;
9555 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9559 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9562 freeAsmop(right,NULL,ic,TRUE);
9563 freeAsmop(result,NULL,ic,TRUE);
9567 /*-----------------------------------------------------------------*/
9568 /* genPagedPointerSet - pic14_emitcode for Paged pointer put */
9569 /*-----------------------------------------------------------------*/
9570 static void genPagedPointerSet (operand *right,
9580 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9582 retype= getSpec(operandType(right));
9584 aopOp(result,ic,FALSE);
9586 /* if the value is already in a pointer register
9587 then don't need anything more */
9588 if (!AOP_INPREG(AOP(result))) {
9589 /* otherwise get a free pointer register */
9591 preg = getFreePtr(ic,&aop,FALSE);
9592 pic14_emitcode("mov","%s,%s",
9594 aopGet(AOP(result),0,FALSE,TRUE));
9595 rname = preg->name ;
9597 rname = aopGet(AOP(result),0,FALSE,FALSE);
9599 freeAsmop(result,NULL,ic,TRUE);
9600 aopOp (right,ic,FALSE);
9602 /* if bitfield then unpack the bits */
9603 if (IS_BITFIELD(retype))
9604 genPackBits (retype,result,right,rname,PPOINTER);
9606 /* we have can just get the values */
9607 int size = AOP_SIZE(right);
9611 l = aopGet(AOP(right),offset,FALSE,TRUE);
9614 pic14_emitcode("movx","@%s,a",rname);
9617 pic14_emitcode("inc","%s",rname);
9623 /* now some housekeeping stuff */
9625 /* we had to allocate for this iCode */
9626 freeAsmop(NULL,aop,ic,TRUE);
9628 /* we did not allocate which means left
9629 already in a pointer register, then
9630 if size > 0 && this could be used again
9631 we have to point it back to where it
9633 if (AOP_SIZE(right) > 1 &&
9634 !OP_SYMBOL(result)->remat &&
9635 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9637 int size = AOP_SIZE(right) - 1;
9639 pic14_emitcode("dec","%s",rname);
9644 freeAsmop(right,NULL,ic,TRUE);
9649 /*-----------------------------------------------------------------*/
9650 /* genFarPointerSet - set value from far space */
9651 /*-----------------------------------------------------------------*/
9652 static void genFarPointerSet (operand *right,
9653 operand *result, iCode *ic)
9656 sym_link *retype = getSpec(operandType(right));
9659 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9660 aopOp(result,ic,FALSE);
9662 /* if the operand is already in dptr
9663 then we do nothing else we move the value to dptr */
9664 if (AOP_TYPE(result) != AOP_STR) {
9665 /* if this is remateriazable */
9666 if (AOP_TYPE(result) == AOP_IMMD)
9667 pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9668 else { /* we need to get it byte by byte */
9669 pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9670 pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9671 if (options.model == MODEL_FLAT24)
9673 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9677 /* so dptr know contains the address */
9678 freeAsmop(result,NULL,ic,TRUE);
9679 aopOp(right,ic,FALSE);
9681 /* if bit then unpack */
9682 if (IS_BITFIELD(retype))
9683 genPackBits(retype,result,right,"dptr",FPOINTER);
9685 size = AOP_SIZE(right);
9689 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9691 pic14_emitcode("movx","@dptr,a");
9693 pic14_emitcode("inc","dptr");
9697 freeAsmop(right,NULL,ic,TRUE);
9701 /*-----------------------------------------------------------------*/
9702 /* genGenPointerSet - set value from generic pointer space */
9703 /*-----------------------------------------------------------------*/
9704 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9706 sym_link *retype = getSpec(operandType(result));
9709 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9710 aopOp(right,ic,FALSE);
9711 aopOp(result,ic,FALSE);
9714 DEBUGpic14_AopType(__LINE__,right,NULL,result);
9716 if (IS_BITFIELD(retype))
9718 genPackBits (retype, result, right, GPOINTER);
9723 /* emit call to __gptrput */
9724 char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9725 int size = AOP_SIZE(right);
9728 assert (size == getSize(OP_SYM_ETYPE(result)));
9729 assert (size > 0 && size <= 4);
9731 /* pass arguments */
9732 /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9738 mov2w_op (right, off);
9739 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9744 assert (AOP_SIZE(result) == 3);
9745 mov2w(AOP(result), 0);
9746 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9747 mov2w(AOP(result), 1);
9748 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9749 mov2w(AOP(result), 2);
9750 call_libraryfunc (func[size]);
9753 freeAsmop(right,NULL,ic,TRUE);
9754 freeAsmop(result,NULL,ic,TRUE);
9757 /*-----------------------------------------------------------------*/
9758 /* genPointerSet - stores the value into a pointer location */
9759 /*-----------------------------------------------------------------*/
9760 static void genPointerSet (iCode *ic)
9762 operand *right, *result ;
9763 sym_link *type, *etype;
9767 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9769 right = IC_RIGHT(ic);
9770 result = IC_RESULT(ic) ;
9772 /* depending on the type of pointer we need to
9773 move it to the correct pointer register */
9774 type = operandType(result);
9775 etype = getSpec(type);
9776 /* if left is of type of pointer then it is simple */
9777 if (IS_PTR(type) && !IS_FUNC(type->next)) {
9778 p_type = DCL_TYPE(type);
9781 /* we have to go by the storage class */
9782 p_type = PTR_TYPE(SPEC_OCLS(etype));
9784 /* if (SPEC_OCLS(etype)->codesp ) { */
9785 /* p_type = CPOINTER ; */
9788 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9789 /* p_type = FPOINTER ; */
9791 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9792 /* p_type = PPOINTER ; */
9794 /* if (SPEC_OCLS(etype) == idata ) */
9795 /* p_type = IPOINTER ; */
9797 /* p_type = POINTER ; */
9800 /* now that we have the pointer type we assign
9801 the pointer values */
9807 genNearPointerSet (right,result,ic);
9811 genPagedPointerSet (right,result,ic);
9815 genFarPointerSet (right,result,ic);
9819 genGenPointerSet (right,result,ic);
9823 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9824 "genPointerSet: illegal pointer type");
9828 /*-----------------------------------------------------------------*/
9829 /* genIfx - generate code for Ifx statement */
9830 /*-----------------------------------------------------------------*/
9831 static void genIfx (iCode *ic, iCode *popIc)
9833 operand *cond = IC_COND(ic);
9837 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9839 aopOp(cond,ic,FALSE);
9841 /* get the value into acc */
9842 if (AOP_TYPE(cond) != AOP_CRY)
9843 pic14_toBoolean(cond);
9847 /* if there was something to be popped then do it */
9853 /* This assumes that CARRY is set iff cond is true */
9856 assert (!IC_FALSE(ic));
9857 emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
9859 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9861 assert (IC_FALSE(ic));
9862 emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
9864 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9868 static int hasWarned = 0;
9871 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
9878 /* now Z is set iff !cond */
9881 assert (!IC_FALSE(ic));
9883 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9886 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9892 /* the result is now in the accumulator */
9893 freeAsmop(cond,NULL,ic,TRUE);
9896 /*-----------------------------------------------------------------*/
9897 /* genAddrOf - generates code for address of */
9898 /*-----------------------------------------------------------------*/
9899 static void genAddrOf (iCode *ic)
9901 operand *right, *result, *left;
9905 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9908 //aopOp(IC_RESULT(ic),ic,FALSE);
9910 aopOp((left=IC_LEFT(ic)),ic,FALSE);
9911 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9912 aopOp((result=IC_RESULT(ic)),ic,TRUE);
9914 DEBUGpic14_AopType(__LINE__,left,right,result);
9915 assert (IS_SYMOP (left));
9917 /* sanity check: generic pointers to code space are not yet supported,
9918 * pionters to codespace must not be assigned addresses of __data values. */
9920 fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9921 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)));
9922 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)));
9923 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)));
9924 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)));
9927 if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9928 fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9929 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9930 OP_SYMBOL(left)->name);
9931 } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9932 fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9933 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9934 OP_SYMBOL(left)->name);
9937 size = AOP_SIZE(IC_RESULT(ic));
9938 if (IS_GENPTR(OP_SYM_TYPE(result))) {
9940 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9945 /* fixing bug #863624, reported from (errolv) */
9946 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9947 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9950 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9951 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9956 if (IS_GENPTR(OP_SYM_TYPE(result)))
9958 /* provide correct tag */
9959 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9960 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9961 movwf (AOP(result), 2);
9964 freeAsmop(left,NULL,ic,FALSE);
9965 freeAsmop(result,NULL,ic,TRUE);
9970 /*-----------------------------------------------------------------*/
9971 /* genFarFarAssign - assignment when both are in far space */
9972 /*-----------------------------------------------------------------*/
9973 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9975 int size = AOP_SIZE(right);
9978 /* first push the right side on to the stack */
9980 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9982 pic14_emitcode ("push","acc");
9985 freeAsmop(right,NULL,ic,FALSE);
9986 /* now assign DPTR to result */
9987 aopOp(result,ic,FALSE);
9988 size = AOP_SIZE(result);
9990 pic14_emitcode ("pop","acc");
9991 aopPut(AOP(result),"a",--offset);
9993 freeAsmop(result,NULL,ic,FALSE);
9998 /*-----------------------------------------------------------------*/
9999 /* genAssign - generate code for assignment */
10000 /*-----------------------------------------------------------------*/
10001 static void genAssign (iCode *ic)
10003 operand *result, *right;
10004 int size, offset,know_W;
10005 unsigned long lit = 0L;
10007 result = IC_RESULT(ic);
10008 right = IC_RIGHT(ic) ;
10011 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10013 /* if they are the same */
10014 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10017 aopOp(right,ic,FALSE);
10018 aopOp(result,ic,TRUE);
10020 DEBUGpic14_AopType(__LINE__,NULL,right,result);
10022 /* if they are the same registers */
10023 if (pic14_sameRegs(AOP(right),AOP(result)))
10026 /* special case: assign from __code */
10027 if (!IS_ITEMP(right) /* --> iTemps never reside in __code */
10028 && IS_SYMOP (right) /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
10029 && !IS_FUNC(OP_SYM_TYPE(right)) /* --> we would want its address instead of the first instruction */
10030 && !IS_CODEPTR(OP_SYM_TYPE(right)) /* --> get symbols address instread */
10031 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
10033 emitpComment ("genAssign from CODESPACE");
10034 genConstPointerGet (right, result, ic);
10038 /* just for symmetry reasons... */
10039 if (!IS_ITEMP(result)
10040 && IS_SYMOP (result)
10041 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
10043 assert ( !"cannot write to CODESPACE" );
10046 /* if the result is a bit */
10047 if (AOP_TYPE(result) == AOP_CRY) {
10049 /* if the right size is a literal then
10050 we know what the value is */
10051 if (AOP_TYPE(right) == AOP_LIT) {
10053 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10054 popGet(AOP(result),0));
10056 if (((int) operandLitValue(right)))
10057 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10058 AOP(result)->aopu.aop_dir,
10059 AOP(result)->aopu.aop_dir);
10061 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10062 AOP(result)->aopu.aop_dir,
10063 AOP(result)->aopu.aop_dir);
10067 /* the right is also a bit variable */
10068 if (AOP_TYPE(right) == AOP_CRY) {
10069 emitpcode(POC_BCF, popGet(AOP(result),0));
10070 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10071 emitpcode(POC_BSF, popGet(AOP(result),0));
10073 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10074 AOP(result)->aopu.aop_dir,
10075 AOP(result)->aopu.aop_dir);
10076 pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
10077 AOP(right)->aopu.aop_dir,
10078 AOP(right)->aopu.aop_dir);
10079 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10080 AOP(result)->aopu.aop_dir,
10081 AOP(result)->aopu.aop_dir);
10085 /* we need to or */
10086 emitpcode(POC_BCF, popGet(AOP(result),0));
10087 pic14_toBoolean(right);
10089 emitpcode(POC_BSF, popGet(AOP(result),0));
10090 //aopPut(AOP(result),"a",0);
10094 /* bit variables done */
10096 size = AOP_SIZE(result);
10098 if(AOP_TYPE(right) == AOP_LIT)
10099 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10101 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
10102 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10103 if(aopIdx(AOP(result),0) == 4) {
10104 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10105 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10106 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10109 DEBUGpic14_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
10114 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10115 if(AOP_TYPE(right) == AOP_LIT) {
10117 if(know_W != (int)(lit&0xff))
10118 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10120 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10122 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10126 } else if (AOP_TYPE(right) == AOP_CRY) {
10127 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10129 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10130 emitpcode(POC_INCF, popGet(AOP(result),0));
10133 mov2w_op (right, offset);
10134 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10142 freeAsmop (right,NULL,ic,FALSE);
10143 freeAsmop (result,NULL,ic,TRUE);
10146 /*-----------------------------------------------------------------*/
10147 /* genJumpTab - genrates code for jump table */
10148 /*-----------------------------------------------------------------*/
10149 static void genJumpTab (iCode *ic)
10155 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10157 aopOp(IC_JTCOND(ic),ic,FALSE);
10158 /* get the condition into accumulator */
10159 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10161 /* multiply by three */
10162 pic14_emitcode("add","a,acc");
10163 pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10165 jtab = newiTempLabel(NULL);
10166 pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10167 pic14_emitcode("jmp","@a+dptr");
10168 pic14_emitcode("","%05d_DS_:",jtab->key+100);
10170 emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10171 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10172 emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10173 emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10175 emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10176 emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10177 emitpLabel(jtab->key);
10179 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10181 /* now generate the jump labels */
10182 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10183 jtab = setNextItem(IC_JTLABELS(ic))) {
10184 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10185 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10191 /*-----------------------------------------------------------------*/
10192 /* genMixedOperation - gen code for operators between mixed types */
10193 /*-----------------------------------------------------------------*/
10195 TSD - Written for the PIC port - but this unfortunately is buggy.
10196 This routine is good in that it is able to efficiently promote
10197 types to different (larger) sizes. Unfortunately, the temporary
10198 variables that are optimized out by this routine are sometimes
10199 used in other places. So until I know how to really parse the
10200 iCode tree, I'm going to not be using this routine :(.
10202 static int genMixedOperation (iCode *ic)
10206 operand *result = IC_RESULT(ic);
10207 sym_link *ctype = operandType(IC_LEFT(ic));
10208 operand *right = IC_RIGHT(ic);
10214 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10216 pic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10222 nextright = IC_RIGHT(nextic);
10223 nextleft = IC_LEFT(nextic);
10224 nextresult = IC_RESULT(nextic);
10226 aopOp(right,ic,FALSE);
10227 aopOp(result,ic,FALSE);
10228 aopOp(nextright, nextic, FALSE);
10229 aopOp(nextleft, nextic, FALSE);
10230 aopOp(nextresult, nextic, FALSE);
10232 if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10234 operand *t = right;
10238 pic14_emitcode(";remove right +","");
10240 } else if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10242 operand *t = right;
10246 pic14_emitcode(";remove left +","");
10250 big = AOP_SIZE(nextleft);
10251 small = AOP_SIZE(nextright);
10253 switch(nextic->op) {
10256 pic14_emitcode(";optimize a +","");
10257 /* if unsigned or not an integral type */
10258 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10259 pic14_emitcode(";add a bit to something","");
10262 pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10264 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10265 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10266 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10268 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10276 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10277 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10278 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10281 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10283 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10284 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10285 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10286 pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10287 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10290 pic14_emitcode("rlf","known_zero,w");
10297 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10298 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10299 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10301 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10311 freeAsmop(right,NULL,ic,TRUE);
10312 freeAsmop(result,NULL,ic,TRUE);
10313 freeAsmop(nextright,NULL,ic,TRUE);
10314 freeAsmop(nextleft,NULL,ic,TRUE);
10316 nextic->generated = 1;
10323 /*-----------------------------------------------------------------*/
10324 /* genCast - gen code for casting */
10325 /*-----------------------------------------------------------------*/
10326 static void genCast (iCode *ic)
10328 operand *result = IC_RESULT(ic);
10329 sym_link *restype = operandType(result);
10330 sym_link *rtype = operandType(IC_RIGHT(ic));
10331 operand *right = IC_RIGHT(ic);
10335 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10336 /* if they are equivalent then do nothing */
10337 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10340 aopOp(right,ic,FALSE) ;
10341 aopOp(result,ic,FALSE);
10343 DEBUGpic14_AopType(__LINE__,NULL,right,result);
10345 /* if the result is a bit */
10346 if (AOP_TYPE(result) == AOP_CRY) {
10347 assert(!"assigning to bit variables is not supported");
10350 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10352 size = AOP_SIZE(result);
10354 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10356 emitpcode(POC_CLRF, popGet(AOP(result),0));
10357 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10358 emitpcode(POC_INCF, popGet(AOP(result),0));
10361 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
10366 if (IS_PTR(restype))
10368 operand *result = IC_RESULT(ic);
10369 //operand *left = IC_LEFT(ic);
10370 operand *right = IC_RIGHT(ic);
10373 /* copy common part */
10374 int max, size = AOP_SIZE(result);
10375 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10376 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10378 /* warn if we discard generic opinter tag */
10379 if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10381 //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10387 mov2w_op (right, size);
10388 movwf (AOP(result), size);
10391 /* upcast into generic pointer type? */
10392 if (IS_GENPTR(restype)
10393 && (size < AOP_SIZE(result))
10394 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10396 //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10399 switch (DCL_TYPE(rtype))
10401 case POINTER: /* __data */
10402 case FPOINTER: /* __data */
10403 assert (AOP_SIZE(right) == 2);
10404 tag = GPTRTAG_DATA;
10407 case CPOINTER: /* __code */
10408 assert (AOP_SIZE(right) == 2);
10409 tag = GPTRTAG_CODE;
10412 case GPOINTER: /* unknown destination, __data or __code */
10413 /* assume __data space (address of immediate) */
10414 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10415 if (AOP(right)->code)
10416 tag = GPTRTAG_CODE;
10418 tag = GPTRTAG_DATA;
10422 assert (!"unhandled pointer type");
10425 /* convert other values into pointers to __data space */
10426 tag = GPTRTAG_DATA;
10429 assert (AOP_SIZE(result) == 3);
10431 emitpcode(POC_CLRF, popGet(AOP(result), 2));
10433 emitpcode(POC_MOVLW, popGetLit(tag));
10434 movwf(AOP(result), 2);
10437 addSign(result, max, 0);
10442 /* if they are the same size : or less */
10443 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10445 /* if they are in the same place */
10446 if (pic14_sameRegs(AOP(right),AOP(result)))
10449 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10450 if (IS_PTR_CONST(rtype))
10451 DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10452 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10453 DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10455 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10456 emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10457 emitpcode(POC_MOVWF, popGet(AOP(result),0));
10458 emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10459 emitpcode(POC_MOVWF, popGet(AOP(result),1));
10460 if(AOP_SIZE(result) <2)
10461 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10465 /* if they in different places then copy */
10466 size = AOP_SIZE(result);
10469 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10470 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10472 //aopPut(AOP(result),
10473 // aopGet(AOP(right),offset,FALSE,FALSE),
10482 /* so we now know that the size of destination is greater
10483 than the size of the source.
10484 Now, if the next iCode is an operator then we might be
10485 able to optimize the operation without performing a cast.
10487 if(0 && genMixedOperation(ic)) {
10488 /* XXX: cannot optimize: must copy regs! */
10492 /* we move to result for the size of source */
10493 size = AOP_SIZE(right);
10496 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10497 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10501 addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10504 freeAsmop(right,NULL,ic,TRUE);
10505 freeAsmop(result,NULL,ic,TRUE);
10509 /*-----------------------------------------------------------------*/
10510 /* genDjnz - generate decrement & jump if not zero instrucion */
10511 /*-----------------------------------------------------------------*/
10512 static int genDjnz (iCode *ic, iCode *ifx)
10514 symbol *lbl, *lbl1;
10516 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10521 /* if the if condition has a false label
10522 then we cannot save */
10526 /* if the minus is not of the form
10528 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10529 !IS_OP_LITERAL(IC_RIGHT(ic)))
10532 if (operandLitValue(IC_RIGHT(ic)) != 1)
10535 /* if the size of this greater than one then no
10537 if (getSize(operandType(IC_RESULT(ic))) > 1)
10540 /* otherwise we can save BIG */
10541 lbl = newiTempLabel(NULL);
10542 lbl1= newiTempLabel(NULL);
10544 aopOp(IC_RESULT(ic),ic,FALSE);
10546 if (IS_AOP_PREG(IC_RESULT(ic))) {
10547 pic14_emitcode("dec","%s",
10548 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10549 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10550 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10554 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10555 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10557 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10558 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10561 /* pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10562 /* pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10563 /* pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10564 /* pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10567 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10568 ifx->generated = 1;
10572 /*-----------------------------------------------------------------*/
10573 /* genReceive - generate code for a receive iCode */
10574 /*-----------------------------------------------------------------*/
10575 static void genReceive (iCode *ic)
10578 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10580 if (isOperandInFarSpace(IC_RESULT(ic)) &&
10581 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10582 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10584 int size = getSize(operandType(IC_RESULT(ic)));
10585 int offset = fReturnSizePic - size;
10587 pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10588 fReturn[fReturnSizePic - offset - 1] : "acc"));
10591 aopOp(IC_RESULT(ic),ic,FALSE);
10592 size = AOP_SIZE(IC_RESULT(ic));
10595 pic14_emitcode ("pop","acc");
10596 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10601 aopOp(IC_RESULT(ic),ic,FALSE);
10603 assignResultValue(IC_RESULT(ic));
10606 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10609 /*-----------------------------------------------------------------*/
10610 /* genDummyRead - generate code for dummy read of volatiles */
10611 /*-----------------------------------------------------------------*/
10613 genDummyRead (iCode * ic)
10616 pic14_emitcode ("; genDummyRead","");
10617 pic14_emitcode ("; not implemented","");
10622 /*-----------------------------------------------------------------*/
10623 /* genpic14Code - generate code for pic14 based controllers */
10624 /*-----------------------------------------------------------------*/
10626 * At this point, ralloc.c has gone through the iCode and attempted
10627 * to optimize in a way suitable for a PIC. Now we've got to generate
10628 * PIC instructions that correspond to the iCode.
10630 * Once the instructions are generated, we'll pass through both the
10631 * peep hole optimizer and the pCode optimizer.
10632 *-----------------------------------------------------------------*/
10634 void genpic14Code (iCode *lic)
10641 lineHead = lineCurr = NULL;
10643 pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10646 /* if debug information required */
10647 if (options.debug && currFunc) {
10649 debugFile->writeFunction (currFunc, lic);
10654 for (ic = lic ; ic ; ic = ic->next ) {
10656 //DEBUGpic14_emitcode(";ic","");
10657 //fprintf (stderr, "in ic loop\n");
10658 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10659 //ic->lineno, printCLine(ic->filename, ic->lineno));
10661 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10663 //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10664 cline = printCLine (ic->filename, ic->lineno);
10665 if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10666 addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10667 //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10670 if (options.iCodeInAsm) {
10671 emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10673 /* if the result is marked as
10674 spilt and rematerializable or code for
10675 this has already been generated then
10677 if (resultRemat(ic) || ic->generated )
10680 /* depending on the operation */
10699 /* IPOP happens only when trying to restore a
10700 spilt live range, if there is an ifx statement
10701 following this pop then the if statement might
10702 be using some of the registers being popped which
10703 would destory the contents of the register so
10704 we need to check for this condition and handle it */
10706 ic->next->op == IFX &&
10707 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10708 genIfx (ic->next,ic);
10726 genEndFunction (ic);
10746 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10763 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
10767 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10774 /* note these two are xlated by algebraic equivalence
10775 during parsing SDCC.y */
10776 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10777 "got '>=' or '<=' shouldn't have come here");
10781 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10793 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10797 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10801 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10825 genRightShift (ic);
10828 case GET_VALUE_AT_ADDRESS:
10833 if (POINTER_SET(ic))
10860 addSet(&_G.sendSet,ic);
10863 case DUMMY_READ_VOLATILE:
10868 fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10875 /* now we are ready to call the
10876 peep hole optimizer */
10877 if (!options.nopeep) {
10878 peepHole (&lineHead);
10880 /* now do the actual printing */
10881 printLine (lineHead,codeOutFile);
10884 DFPRINTF((stderr,"printing pBlock\n\n"));
10885 printpBlock(stdout,pb);
10891 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10892 * (meaning: representing its own address) or not (referencing its contents).
10893 * This can only be decided based on the operand's type. */
10895 aop_isLitLike (asmop *aop)
10898 if (aop->type == AOP_LIT) return 1;
10899 if (aop->type == AOP_IMMD) return 1;
10900 if ((aop->type == AOP_PCODE) &&
10901 ((aop->aopu.pcop->type == PO_LITERAL)))
10903 /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10904 * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10911 op_isLitLike (operand *op)
10914 if (aop_isLitLike (AOP(op))) return 1;
10915 if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10916 if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;