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 -------------------------------------------------------------------------*/
37 #include "SDCCglobl.h"
41 #include "SDCCpeeph.h"
46 /* When changing these, you must also update the assembler template
47 * in device/lib/libsdcc/macros.inc */
48 #define GPTRTAG_DATA 0x00
49 #define GPTRTAG_CODE 0x80
51 /* The PIC port(s) need not differentiate between POINTER and FPOINTER. */
52 #define PIC_IS_DATA_PTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
53 #define PIC_IS_FARPTR(x) (PIC_IS_DATA_PTR(x))
55 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
56 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
57 void genMult8X8_8 (operand *, operand *,operand *);
58 extern void printpBlock(FILE *of, pBlock *pb);
60 static int labelOffset=0;
61 extern int debug_verbose;
62 extern int pic14_hasInterrupt;
63 //static int optimized_for_speed = 0;
65 /* max_key keeps track of the largest label number used in
66 a function. This is then used to adjust the label offset
67 for the next function.
70 static int GpsuedoStkPtr=0;
72 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
73 extern char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
74 unsigned int pic14aopLiteral (value *val, int offset);
75 const char *AopType(short type);
77 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0x00ff)
79 /* this is the down and dirty file with all kinds of
80 kludgy & hacky stuff. This is what it is all about
81 CODE GENERATION for a specific MCU . some of the
82 routines may be reusable, will have to see */
84 static char *zero = "#0x00";
85 static char *one = "#0x01";
86 static char *spname = "sp";
88 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
89 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
90 static char **fReturn = fReturnpic14;
92 //static char *accUse[] = {"a","b"};
94 //static short rbank = -1;
106 /* Resolved ifx structure. This structure stores information
107 about an iCode ifx that makes it easier to generate code.
109 typedef struct resolvedIfx {
110 symbol *lbl; /* pointer to a label */
111 int condition; /* true or false ifx */
112 int generated; /* set true when the code associated with the ifx
116 extern int pic14_ptrRegReq ;
117 extern int pic14_nRegs;
118 extern FILE *codeOutFile;
119 static void saverbank (int, iCode *,bool);
121 static lineNode *lineHead = NULL;
122 static lineNode *lineCurr = NULL;
125 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
126 0xE0, 0xC0, 0x80, 0x00};
127 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
128 0x07, 0x03, 0x01, 0x00};
133 /*-----------------------------------------------------------------*/
134 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
135 /* exponent of 2 is returned, otherwise -1 is */
137 /* note that this is similar to the function `powof2' in SDCCsymt */
141 /*-----------------------------------------------------------------*/
142 static int my_powof2 (unsigned long num)
145 if( (num & (num-1)) == 0) {
158 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
161 DEBUGpic14_emitcode ("; ","line = %d result %s=%s, size=%d, left %s=%s, size=%d, right %s=%s, size=%d",
163 ((result) ? AopType(AOP_TYPE(result)) : "-"),
164 ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
165 ((result) ? AOP_SIZE(result) : 0),
166 ((left) ? AopType(AOP_TYPE(left)) : "-"),
167 ((left) ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
168 ((left) ? AOP_SIZE(left) : 0),
169 ((right) ? AopType(AOP_TYPE(right)) : "-"),
170 ((right) ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
171 ((right) ? AOP_SIZE(right) : 0));
175 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
178 DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
180 ((result) ? AopType(AOP_TYPE(result)) : "-"),
181 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
182 ((left) ? AopType(AOP_TYPE(left)) : "-"),
183 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
184 ((right) ? AopType(AOP_TYPE(right)) : "-"),
185 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
189 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
192 char lb[INITIAL_INLINEASM];
193 unsigned char *lbp = (unsigned char *)lb;
195 if(!debug_verbose && !options.debug)
202 sprintf(lb,"%s\t",inst);
204 sprintf(lb,"%s",inst);
205 vsprintf(lb+(strlen(lb)),fmt,ap);
209 while (isspace(*lbp)) lbp++;
212 lineCurr = (lineCurr ?
213 connectLine(lineCurr,newLineNode(lb)) :
214 (lineHead = newLineNode(lb)));
215 lineCurr->isInline = _G.inLine;
216 lineCurr->isDebug = _G.debugLine;
218 addpCode2pBlock(pb,newpCodeCharP(lb));
223 static void Safe_vsnprintf (char *buf, size_t size, const char *fmt, va_list ap)
225 #if defined (HAVE_VSNPRINTF)
226 vsnprintf (buf, size, fmt, ap);
227 #elif defined (HAVE_VSPRINTF)
228 vsprintf (buf, size, fmt, ap);
229 if (strlen (buf) >= size)
231 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
233 #elif defined (HAVE_SNPRINTF)
234 snprintf (buf, size, "vs(n)printf required");
235 #elif defined (HAVE_SRINTF)
236 sprintf (buf, "vs(n)printf required");
237 if (strlen (buf) >= size)
239 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
242 assert ( !"neither vsnprintf nor vsprintf is present -- unable to proceed" );
246 void emitpComment (const char *fmt, ...)
253 Safe_vsnprintf (buffer, 4096, fmt, va);
254 //fprintf (stderr, "%s\n" ,buffer);
255 addpCode2pBlock (pb, newpCodeCharP (buffer));
258 Safe_vsnprintf (buffer, 4096, fmt, va);
259 fprintf (stderr, "No current pBlock -- discarding comment [%s]\n", buffer);
265 void emitpLabel(int key)
267 addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
270 /* gen.h defines a macro emitpcode that should be used to call emitpcode
271 * as this allows for easy debugging (ever asked the question: where was
272 * this instruction geenrated? Here is the answer... */
273 void emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
276 addpCode2pBlock(pb,newpCode(poc,pcop));
278 DEBUGpic14_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
281 void emitpcodeNULLop(PIC_OPCODE poc)
284 addpCode2pBlock(pb,newpCode(poc,NULL));
289 /*-----------------------------------------------------------------*/
290 /* pic14_emitcode - writes the code into a file : for now it is simple */
291 /*-----------------------------------------------------------------*/
292 void pic14_emitcode (char *inst,char *fmt, ...)
295 char lb[INITIAL_INLINEASM];
296 unsigned char *lbp = (unsigned char *)lb;
302 sprintf(lb,"%s\t",inst);
304 sprintf(lb,"%s",inst);
305 vsprintf(lb+(strlen(lb)),fmt,ap);
309 while (isspace(*lbp)) lbp++;
312 lineCurr = (lineCurr ?
313 connectLine(lineCurr,newLineNode(lb)) :
314 (lineHead = newLineNode(lb)));
315 lineCurr->isInline = _G.inLine;
316 lineCurr->isDebug = _G.debugLine;
319 addpCode2pBlock(pb,newpCodeCharP(lb));
324 /*-----------------------------------------------------------------*/
325 /* pic14_emitDebuggerSymbol - associate the current code location */
326 /* with a debugger symbol */
327 /*-----------------------------------------------------------------*/
329 pic14_emitDebuggerSymbol (char * debugSym)
332 pic14_emitcode ("", ";%s ==.", debugSym);
337 /*-----------------------------------------------------------------*/
338 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
339 /*-----------------------------------------------------------------*/
340 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
342 bool r0iu = FALSE , r1iu = FALSE;
343 bool r0ou = FALSE , r1ou = FALSE;
345 /* the logic: if r0 & r1 used in the instruction
346 then we are in trouble otherwise */
348 /* first check if r0 & r1 are used by this
349 instruction, in which case we are in trouble */
350 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
351 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
356 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
357 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
359 /* if no usage of r0 then return it */
360 if (!r0iu && !r0ou) {
361 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
362 (*aopp)->type = AOP_R0;
364 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
367 /* if no usage of r1 then return it */
368 if (!r1iu && !r1ou) {
369 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
370 (*aopp)->type = AOP_R1;
372 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
375 /* now we know they both have usage */
376 /* if r0 not used in this instruction */
378 /* push it if not already pushed */
380 //pic14_emitcode ("push","%s",
381 // pic14_regWithIdx(R0_IDX)->dname);
385 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
386 (*aopp)->type = AOP_R0;
388 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
391 /* if r1 not used then */
394 /* push it if not already pushed */
396 //pic14_emitcode ("push","%s",
397 // pic14_regWithIdx(R1_IDX)->dname);
401 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
402 (*aopp)->type = AOP_R1;
403 return pic14_regWithIdx(R1_IDX);
407 /* I said end of world but not quite end of world yet */
408 /* if this is a result then we can push it on the stack*/
410 (*aopp)->type = AOP_STK;
414 /* other wise this is true end of the world */
415 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
416 "getFreePtr should never reach here");
421 /*-----------------------------------------------------------------*/
422 /* newAsmop - creates a new asmOp */
423 /*-----------------------------------------------------------------*/
424 asmop *newAsmop (short type)
428 aop = Safe_calloc(1,sizeof(asmop));
433 static void genSetDPTR(int n)
437 pic14_emitcode(";", "Select standard DPTR");
438 pic14_emitcode("mov", "dps, #0x00");
442 pic14_emitcode(";", "Select alternate DPTR");
443 pic14_emitcode("mov", "dps, #0x01");
447 /*-----------------------------------------------------------------*/
448 /* resolveIfx - converts an iCode ifx into a form more useful for */
449 /* generating code */
450 /*-----------------------------------------------------------------*/
451 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
456 // DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
458 resIfx->condition = 1; /* assume that the ifx is true */
459 resIfx->generated = 0; /* indicate that the ifx has not been used */
462 resIfx->lbl = NULL; /* this is wrong: newiTempLabel(NULL); / * oops, there is no ifx. so create a label */
464 DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
465 __FUNCTION__,__LINE__,resIfx->lbl->key);
469 resIfx->lbl = IC_TRUE(ifx);
471 resIfx->lbl = IC_FALSE(ifx);
472 resIfx->condition = 0;
476 DEBUGpic14_emitcode("; ***","ifx true is non-null");
478 DEBUGpic14_emitcode("; ***","ifx false is non-null");
482 // DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
485 /*-----------------------------------------------------------------*/
486 /* pointerCode - returns the code for a pointer type */
487 /*-----------------------------------------------------------------*/
489 static int pointerCode (sym_link *etype)
492 return PTR_TYPE(SPEC_OCLS(etype));
497 /*-----------------------------------------------------------------*/
498 /* aopForSym - for a true symbol */
499 /*-----------------------------------------------------------------*/
500 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
503 memmap *space= SPEC_OCLS(sym->etype);
505 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
506 /* if already has one */
511 /* assign depending on the storage class */
512 /* if it is on the stack or indirectly addressable */
513 /* space we need to assign either r0 or r1 to it */
514 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
515 sym->aop = aop = newAsmop(0);
516 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
517 aop->size = getSize(sym->type);
519 /* now assign the address of the variable to
520 the pointer register */
521 if (aop->type != AOP_STK) {
525 pic14_emitcode("push","acc");
527 pic14_emitcode("mov","a,_bp");
528 pic14_emitcode("add","a,#0x%02x",
530 ((char)(sym->stack - _G.nRegsSaved )) :
531 ((char)sym->stack)) & 0xff);
532 pic14_emitcode("mov","%s,a",
533 aop->aopu.aop_ptr->name);
536 pic14_emitcode("pop","acc");
538 pic14_emitcode("mov","%s,#%s",
539 aop->aopu.aop_ptr->name,
541 aop->paged = space->paged;
543 aop->aopu.aop_stk = sym->stack;
547 if (sym->onStack && options.stack10bit)
549 /* It's on the 10 bit stack, which is located in
553 //DEBUGpic14_emitcode(";","%d",__LINE__);
556 pic14_emitcode("push","acc");
558 pic14_emitcode("mov","a,_bp");
559 pic14_emitcode("add","a,#0x%02x",
561 ((char)(sym->stack - _G.nRegsSaved )) :
562 ((char)sym->stack)) & 0xff);
565 pic14_emitcode ("mov","dpx1,#0x40");
566 pic14_emitcode ("mov","dph1,#0x00");
567 pic14_emitcode ("mov","dpl1, a");
571 pic14_emitcode("pop","acc");
573 sym->aop = aop = newAsmop(AOP_DPTR2);
574 aop->size = getSize(sym->type);
579 //DEBUGpic14_emitcode(";","%d",__LINE__);
580 /* if in bit space */
581 if (IN_BITSPACE(space)) {
582 sym->aop = aop = newAsmop (AOP_CRY);
583 aop->aopu.aop_dir = sym->rname ;
584 aop->size = getSize(sym->type);
585 //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
588 /* if it is in direct space */
589 if (IN_DIRSPACE(space)) {
590 sym->aop = aop = newAsmop (AOP_DIR);
591 aop->aopu.aop_dir = sym->rname ;
592 aop->size = getSize(sym->type);
593 DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
597 /* special case for a function */
598 if (IS_FUNC(sym->type)) {
600 sym->aop = aop = newAsmop(AOP_PCODE);
601 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
602 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
603 PCOI(aop->aopu.pcop)->_function = 1;
604 PCOI(aop->aopu.pcop)->index = 0;
605 aop->size = FPTRSIZE;
607 sym->aop = aop = newAsmop(AOP_IMMD);
608 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
609 strcpy(aop->aopu.aop_immd,sym->rname);
610 aop->size = FPTRSIZE;
612 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
616 if (IS_ARRAY(sym->type)) {
617 sym->aop = aop = newAsmop(AOP_PCODE);
618 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
619 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
620 PCOI(aop->aopu.pcop)->_function = 0;
621 PCOI(aop->aopu.pcop)->index = 0;
622 aop->size = getSize(sym->etype) * DCL_ELEM(sym->type);
624 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
628 /* only remaining is far space */
629 /* in which case DPTR gets the address */
630 sym->aop = aop = newAsmop(AOP_PCODE);
632 aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
633 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
634 PCOI(aop->aopu.pcop)->index = 0;
636 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
637 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
639 allocDirReg (IC_LEFT(ic));
641 aop->size = FPTRSIZE;
643 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
644 sym->aop = aop = newAsmop(AOP_DPTR);
645 pic14_emitcode ("mov","dptr,#%s", sym->rname);
646 aop->size = getSize(sym->type);
648 DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
651 /* if it is in code space */
652 if (IN_CODESPACE(space))
658 /*-----------------------------------------------------------------*/
659 /* aopForRemat - rematerialzes an object */
660 /*-----------------------------------------------------------------*/
661 static asmop *aopForRemat (operand *op) // x symbol *sym)
663 symbol *sym = OP_SYMBOL(op);
665 asmop *aop = newAsmop(AOP_PCODE);
669 ic = sym->rematiCode;
671 DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
672 if(IS_OP_POINTER(op)) {
673 DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
677 val += (int) operandLitValue(IC_RIGHT(ic));
678 } else if (ic->op == '-') {
679 val -= (int) operandLitValue(IC_RIGHT(ic));
683 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
686 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
687 aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
688 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
689 PCOI(aop->aopu.pcop)->index = val;
691 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
692 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
693 val, IS_PTR_CONST(operandType(op)));
695 // DEBUGpic14_emitcode(";","aop type %s",AopType(AOP_TYPE(IC_LEFT(ic))));
697 allocDirReg (IC_LEFT(ic));
702 int aopIdx (asmop *aop, int offset)
707 if(aop->type != AOP_REG)
710 return aop->aopu.aop_reg[offset]->rIdx;
713 /*-----------------------------------------------------------------*/
714 /* regsInCommon - two operands have some registers in common */
715 /*-----------------------------------------------------------------*/
716 static bool regsInCommon (operand *op1, operand *op2)
721 /* if they have registers in common */
722 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
725 sym1 = OP_SYMBOL(op1);
726 sym2 = OP_SYMBOL(op2);
728 if (sym1->nRegs == 0 || sym2->nRegs == 0)
731 for (i = 0 ; i < sym1->nRegs ; i++) {
736 for (j = 0 ; j < sym2->nRegs ;j++ ) {
740 if (sym2->regs[j] == sym1->regs[i])
748 /*-----------------------------------------------------------------*/
749 /* operandsEqu - equivalent */
750 /*-----------------------------------------------------------------*/
751 static bool operandsEqu ( operand *op1, operand *op2)
755 /* if they not symbols */
756 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
759 sym1 = OP_SYMBOL(op1);
760 sym2 = OP_SYMBOL(op2);
762 /* if both are itemps & one is spilt
763 and the other is not then false */
764 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
765 sym1->isspilt != sym2->isspilt )
768 /* if they are the same */
772 if (sym1->rname[0] && sym2->rname[0]
773 && strcmp (sym1->rname, sym2->rname) == 0)
777 /* if left is a tmp & right is not */
781 (sym1->usl.spillLoc == sym2))
788 (sym2->usl.spillLoc == sym1))
794 /*-----------------------------------------------------------------*/
795 /* pic14_sameRegs - two asmops have the same registers */
796 /*-----------------------------------------------------------------*/
797 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
804 if (aop1->type != AOP_REG ||
805 aop2->type != AOP_REG )
808 if (aop1->size != aop2->size )
811 for (i = 0 ; i < aop1->size ; i++ )
812 if (aop1->aopu.aop_reg[i] !=
813 aop2->aopu.aop_reg[i] )
819 /*-----------------------------------------------------------------*/
820 /* aopOp - allocates an asmop for an operand : */
821 /*-----------------------------------------------------------------*/
822 void aopOp (operand *op, iCode *ic, bool result)
831 /* if this a literal */
832 if (IS_OP_LITERAL(op)) {
833 op->aop = aop = newAsmop(AOP_LIT);
834 aop->aopu.aop_lit = op->operand.valOperand;
835 aop->size = getSize(operandType(op));
840 sym_link *type = operandType(op);
841 if(IS_PTR_CONST(type))
842 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
845 /* if already has a asmop then continue */
849 /* if the underlying symbol has a aop */
850 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
851 DEBUGpic14_emitcode(";","%d",__LINE__);
852 op->aop = OP_SYMBOL(op)->aop;
856 /* if this is a true symbol */
857 if (IS_TRUE_SYMOP(op)) {
858 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
859 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
863 /* this is a temporary : this has
869 e) can be a return use only */
874 /* if the type is a conditional */
875 if (sym->regType == REG_CND) {
876 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
881 /* if it is spilt then two situations
883 b) has a spill location */
884 if (sym->isspilt || sym->nRegs == 0) {
886 DEBUGpic14_emitcode(";","%d",__LINE__);
887 /* rematerialize it NOW */
890 sym->aop = op->aop = aop = aopForRemat (op);
891 aop->size = getSize(sym->type);
892 //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
897 /* WREG is not usable as an ordinary operand with PIC architecture,
898 * one might introduce a scratch register that can be used to make
899 * WREG accesible as an operand... disable WREG for now */
902 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
903 aop->size = getSize(sym->type);
904 for ( i = 0 ; i < 2 ; i++ )
905 aop->aopu.aop_str[i] = accUse[i];
906 DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
912 if(sym->isptr) { // && sym->uptr
913 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
914 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
916 //PCOI(aop->aopu.pcop)->_const = 0;
917 //PCOI(aop->aopu.pcop)->index = 0;
919 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
920 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
922 //allocDirReg (IC_LEFT(ic));
924 aop->size = getSize(sym->type);
925 DEBUGpic14_emitcode(";","%d",__LINE__);
932 aop = op->aop = sym->aop = newAsmop(AOP_STR);
933 aop->size = getSize(sym->type);
934 for ( i = 0 ; i < fReturnSizePic ; i++ )
935 aop->aopu.aop_str[i] = fReturn[i];
937 DEBUGpic14_emitcode(";","%d",__LINE__);
942 /* else spill location */
943 if (sym->usl.spillLoc)
945 asmop *oldAsmOp = NULL;
947 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
949 /* force a new aop if sizes differ */
950 oldAsmOp = sym->usl.spillLoc->aop;
951 sym->usl.spillLoc->aop = NULL;
953 DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
954 __FUNCTION__,__LINE__,
955 sym->usl.spillLoc->rname,
956 sym->rname, sym->usl.spillLoc->offset);
958 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
959 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
961 /* Don't reuse the new aop, go with the last one */
962 sym->usl.spillLoc->aop = oldAsmOp;
964 //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
965 aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname,
967 sym->usl.spillLoc->offset);
968 aop->size = getSize(sym->type);
975 sym_link *type = operandType(op);
976 if(IS_PTR_CONST(type))
977 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
980 /* must be in a register */
981 DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
982 sym->aop = op->aop = aop = newAsmop(AOP_REG);
983 aop->size = sym->nRegs;
984 for ( i = 0 ; i < sym->nRegs ;i++)
985 aop->aopu.aop_reg[i] = sym->regs[i];
988 /*-----------------------------------------------------------------*/
989 /* freeAsmop - free up the asmop given to an operand */
990 /*----------------------------------------------------------------*/
991 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1008 /* depending on the asmop type only three cases need work AOP_RO
1009 , AOP_R1 && AOP_STK */
1011 switch (aop->type) {
1015 pic14_emitcode ("pop","ar0");
1019 bitVectUnSetBit(ic->rUsed,R0_IDX);
1025 pic14_emitcode ("pop","ar1");
1029 bitVectUnSetBit(ic->rUsed,R1_IDX);
1035 int stk = aop->aopu.aop_stk + aop->size;
1036 bitVectUnSetBit(ic->rUsed,R0_IDX);
1037 bitVectUnSetBit(ic->rUsed,R1_IDX);
1039 getFreePtr(ic,&aop,FALSE);
1041 if (options.stack10bit)
1043 /* I'm not sure what to do here yet... */
1046 "*** Warning: probably generating bad code for "
1047 "10 bit stack mode.\n");
1051 pic14_emitcode ("mov","a,_bp");
1052 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1053 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1055 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1059 pic14_emitcode("pop","acc");
1060 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1062 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1065 freeAsmop(op,NULL,ic,TRUE);
1067 pic14_emitcode("pop","ar0");
1072 pic14_emitcode("pop","ar1");
1080 /* all other cases just dealloc */
1084 OP_SYMBOL(op)->aop = NULL;
1085 /* if the symbol has a spill */
1087 SPIL_LOC(op)->aop = NULL;
1092 /*-----------------------------------------------------------------*/
1093 /* aopGet - for fetching value of the aop */
1094 /*-----------------------------------------------------------------*/
1095 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1100 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1101 /* offset is greater than
1103 if (offset > (aop->size - 1) &&
1104 aop->type != AOP_LIT)
1107 /* depending on type */
1108 switch (aop->type) {
1112 DEBUGpic14_emitcode(";","%d",__LINE__);
1113 /* if we need to increment it */
1114 while (offset > aop->coff) {
1115 pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);
1119 while (offset < aop->coff) {
1120 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1124 aop->coff = offset ;
1126 pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1127 return (dname ? "acc" : "a");
1129 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1130 rs = Safe_calloc(1,strlen(s)+1);
1136 DEBUGpic14_emitcode(";","%d",__LINE__);
1137 if (aop->type == AOP_DPTR2)
1142 while (offset > aop->coff) {
1143 pic14_emitcode ("inc","dptr");
1147 while (offset < aop->coff) {
1148 pic14_emitcode("lcall","__decdptr");
1154 pic14_emitcode("clr","a");
1155 pic14_emitcode("movc","a,@a+dptr");
1158 pic14_emitcode("movx","a,@dptr");
1161 if (aop->type == AOP_DPTR2)
1166 return (dname ? "acc" : "a");
1171 sprintf (s,"%s",aop->aopu.aop_immd);
1174 sprintf(s,"(%s >> %d)",
1179 aop->aopu.aop_immd);
1180 DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1181 rs = Safe_calloc(1,strlen(s)+1);
1187 sprintf(s,"(%s + %d)",
1190 DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1192 sprintf(s,"%s",aop->aopu.aop_dir);
1193 rs = Safe_calloc(1,strlen(s)+1);
1199 // return aop->aopu.aop_reg[offset]->dname;
1201 return aop->aopu.aop_reg[offset]->name;
1204 //pic14_emitcode(";","%d",__LINE__);
1205 return aop->aopu.aop_dir;
1208 DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1209 return "AOP_accumulator_bug";
1212 sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1213 rs = Safe_calloc(1,strlen(s)+1);
1218 aop->coff = offset ;
1219 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1222 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1224 return aop->aopu.aop_str[offset];
1228 pCodeOp *pcop = aop->aopu.pcop;
1229 DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1232 DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
1233 sprintf(s,"(%s+%d)", pcop->name,offset);
1235 DEBUGpic14_emitcode(";","%s",pcop->name);
1236 sprintf(s,"%s", pcop->name);
1239 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1242 rs = Safe_calloc(1,strlen(s)+1);
1248 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1249 "aopget got unsupported aop->type");
1254 /*-----------------------------------------------------------------*/
1255 /* popGetTempReg - create a new temporary pCodeOp */
1256 /*-----------------------------------------------------------------*/
1257 pCodeOp *popGetTempReg(void)
1262 pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1263 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1264 PCOR(pcop)->r->wasUsed=1;
1265 PCOR(pcop)->r->isFree=0;
1271 /*-----------------------------------------------------------------*/
1272 /* popReleaseTempReg - create a new temporary pCodeOp */
1273 /*-----------------------------------------------------------------*/
1274 void popReleaseTempReg(pCodeOp *pcop)
1277 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1278 PCOR(pcop)->r->isFree = 1;
1281 /*-----------------------------------------------------------------*/
1282 /* popGetLabel - create a new pCodeOp of type PO_LABEL */
1283 /*-----------------------------------------------------------------*/
1284 pCodeOp *popGetLabel(unsigned int key)
1287 DEBUGpic14_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1289 if(key>(unsigned int)max_key)
1292 return newpCodeOpLabel(NULL,key+100+labelOffset);
1295 /*-------------------------------------------------------------------*/
1296 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1297 /*-------------------------------------------------------------------*/
1298 pCodeOp *popGetHighLabel(unsigned int key)
1301 pcop = popGetLabel(key);
1302 PCOLAB(pcop)->offset = 1;
1306 /*-----------------------------------------------------------------*/
1307 /* popGetLit - asm operator to pcode operator conversion */
1308 /*-----------------------------------------------------------------*/
1309 pCodeOp *popGetLit(unsigned int lit)
1312 return newpCodeOpLit((unsigned char)lit);
1315 /*-----------------------------------------------------------------*/
1316 /* popGetImmd - asm operator to pcode immediate conversion */
1317 /*-----------------------------------------------------------------*/
1318 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1321 return newpCodeOpImmd(name, offset,index, 0, is_func);
1324 extern set *externs;
1326 /*-----------------------------------------------------------------*/
1327 /* popGetWithString - asm operator to pcode operator conversion */
1328 /*-----------------------------------------------------------------*/
1329 pCodeOp *popGetWithString(char *str, int isExtern)
1335 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1339 pcop = newpCodeOp(str,PO_STR);
1340 PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1345 pCodeOp *popGetExternal (char *str)
1347 pCodeOp *pcop = popGetWithString (str, 1);
1353 for (sym = setFirstItem (externs); !found && sym; sym = setNextItem (externs))
1355 if (!strcmp (str, sym->rname))
1361 sym = newSymbol(str, 0);
1362 strncpy(sym->rname, str, SDCC_NAME_MAX);
1363 addSet (&externs, sym);
1369 /*-----------------------------------------------------------------*/
1370 /* popRegFromString - */
1371 /*-----------------------------------------------------------------*/
1372 pCodeOp *popRegFromString(char *str, int size, int offset)
1375 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1376 pcop->type = PO_DIR;
1378 DEBUGpic14_emitcode(";","%d",__LINE__);
1383 pcop->name = Safe_calloc(1,strlen(str)+1);
1384 strcpy(pcop->name,str);
1386 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1388 PCOR(pcop)->r = dirregWithName(pcop->name);
1389 if(PCOR(pcop)->r == NULL) {
1390 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1391 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1392 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1394 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1396 PCOR(pcop)->instance = offset;
1401 /*-----------------------------------------------------------------*/
1402 /*-----------------------------------------------------------------*/
1403 pCodeOp *popRegFromIdx(int rIdx)
1407 DEBUGpic14_emitcode ("; ***","%s,%d , rIdx=0x%x",
1408 __FUNCTION__,__LINE__,rIdx);
1410 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1412 PCOR(pcop)->rIdx = rIdx;
1413 PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1414 PCOR(pcop)->r->isFree = 0;
1415 PCOR(pcop)->r->wasUsed = 1;
1417 pcop->type = PCOR(pcop)->r->pc_type;
1423 /*-----------------------------------------------------------------*/
1424 /* popGet - asm operator to pcode operator conversion */
1425 /*-----------------------------------------------------------------*/
1426 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1428 //char *s = buffer ;
1433 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1434 /* offset is greater than
1439 /* XXX: still needed for BIT operands (AOP_CRY) */
1440 if (offset > (aop->size - 1) &&
1441 aop->type != AOP_LIT)
1442 return NULL; //zero;
1444 /* depending on type */
1445 switch (aop->type) {
1452 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1456 DEBUGpic14_emitcode(";","%d",__LINE__);
1457 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1460 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1462 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1463 pcop->type = PO_DIR;
1465 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1466 strcpy(pcop->name,aop->aopu.aop_dir);
1467 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1468 if(PCOR(pcop)->r == NULL) {
1469 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1470 PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1471 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1473 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1475 PCOR(pcop)->instance = offset;
1483 assert (offset < aop->size);
1484 rIdx = aop->aopu.aop_reg[offset]->rIdx;
1486 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1487 PCOR(pcop)->rIdx = rIdx;
1488 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1489 PCOR(pcop)->r->wasUsed=1;
1490 PCOR(pcop)->r->isFree=0;
1492 PCOR(pcop)->instance = offset;
1493 pcop->type = PCOR(pcop)->r->pc_type;
1494 //rs = aop->aopu.aop_reg[offset]->name;
1495 DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1500 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1501 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1502 //if(PCOR(pcop)->r == NULL)
1503 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1507 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1510 DEBUGpic14_emitcode(";","%d %s",__LINE__,aop->aopu.aop_str[offset]);
1511 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1513 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1514 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1515 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1516 pcop->type = PCOR(pcop)->r->pc_type;
1517 pcop->name = PCOR(pcop)->r->name;
1524 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1526 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1527 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1528 switch (aop->aopu.pcop->type)
1531 pcop = pCodeOpCopy (aop->aopu.pcop);
1532 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1533 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1534 PCOI(pcop)->index += offset;
1535 //PCOI(pcop)->offset = 0;
1538 pcop = pCodeOpCopy (aop->aopu.pcop);
1539 PCOR(pcop)->instance = offset;
1542 assert ( !"unhandled pCode type" );
1548 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1549 "popGet got unsupported aop->type");
1553 /*-----------------------------------------------------------------*/
1554 /* popGetAddr - access the low/high word of a symbol (immediate) */
1555 /* (for non-PO_IMMEDIATEs this is the same as popGet) */
1556 /*-----------------------------------------------------------------*/
1557 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1559 if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1561 pCodeOp *pcop = aop->aopu.pcop;
1562 assert (offset <= GPTRSIZE);
1564 /* special case: index >= 2 should return GPOINTER-style values */
1567 pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1571 pcop = pCodeOpCopy (pcop);
1572 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1573 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1574 PCOI(pcop)->offset += offset;
1575 PCOI(pcop)->index += index;
1576 //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);
1579 return popGet (aop, offset + index);
1583 /*-----------------------------------------------------------------*/
1584 /* aopPut - puts a string for a aop */
1585 /*-----------------------------------------------------------------*/
1586 void aopPut (asmop *aop, char *s, int offset)
1591 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1593 if (aop->size && offset > ( aop->size - 1)) {
1594 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1595 "aopPut got offset > aop->size");
1599 /* will assign value to value */
1600 /* depending on where it is ofcourse */
1601 switch (aop->type) {
1604 sprintf(d,"(%s + %d)",
1605 aop->aopu.aop_dir,offset);
1606 fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1609 sprintf(d,"%s",aop->aopu.aop_dir);
1612 DEBUGpic14_emitcode(";","%d",__LINE__);
1614 pic14_emitcode("movf","%s,w",s);
1615 pic14_emitcode("movwf","%s",d);
1618 pic14_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
1619 if(offset >= aop->size) {
1620 emitpcode(POC_CLRF,popGet(aop,offset));
1623 emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
1626 emitpcode(POC_MOVWF,popGet(aop,offset));
1632 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1633 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1636 strcmp(s,"r0") == 0 ||
1637 strcmp(s,"r1") == 0 ||
1638 strcmp(s,"r2") == 0 ||
1639 strcmp(s,"r3") == 0 ||
1640 strcmp(s,"r4") == 0 ||
1641 strcmp(s,"r5") == 0 ||
1642 strcmp(s,"r6") == 0 ||
1643 strcmp(s,"r7") == 0 )
1644 pic14_emitcode("mov","%s,%s ; %d",
1645 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1649 if(strcmp(s,"W")==0 )
1650 pic14_emitcode("movf","%s,w ; %d",s,__LINE__);
1652 pic14_emitcode("movwf","%s",
1653 aop->aopu.aop_reg[offset]->name);
1655 if(strcmp(s,zero)==0) {
1656 emitpcode(POC_CLRF,popGet(aop,offset));
1658 } else if(strcmp(s,"W")==0) {
1659 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1660 pcop->type = PO_GPR_REGISTER;
1662 PCOR(pcop)->rIdx = -1;
1663 PCOR(pcop)->r = NULL;
1665 DEBUGpic14_emitcode(";","%d",__LINE__);
1666 pcop->name = Safe_strdup(s);
1667 emitpcode(POC_MOVFW,pcop);
1668 emitpcode(POC_MOVWF,popGet(aop,offset));
1669 } else if(strcmp(s,one)==0) {
1670 emitpcode(POC_CLRF,popGet(aop,offset));
1671 emitpcode(POC_INCF,popGet(aop,offset));
1673 emitpcode(POC_MOVWF,popGet(aop,offset));
1681 if (aop->type == AOP_DPTR2)
1687 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1688 "aopPut writting to code space");
1692 while (offset > aop->coff) {
1694 pic14_emitcode ("inc","dptr");
1697 while (offset < aop->coff) {
1699 pic14_emitcode("lcall","__decdptr");
1704 /* if not in accumulater */
1707 pic14_emitcode ("movx","@dptr,a");
1709 if (aop->type == AOP_DPTR2)
1717 while (offset > aop->coff) {
1719 pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1721 while (offset < aop->coff) {
1723 pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1729 pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1734 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1736 if (strcmp(s,"r0") == 0 ||
1737 strcmp(s,"r1") == 0 ||
1738 strcmp(s,"r2") == 0 ||
1739 strcmp(s,"r3") == 0 ||
1740 strcmp(s,"r4") == 0 ||
1741 strcmp(s,"r5") == 0 ||
1742 strcmp(s,"r6") == 0 ||
1743 strcmp(s,"r7") == 0 ) {
1745 sprintf(buffer,"a%s",s);
1746 pic14_emitcode("mov","@%s,%s",
1747 aop->aopu.aop_ptr->name,buffer);
1749 pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1754 if (strcmp(s,"a") == 0)
1755 pic14_emitcode("push","acc");
1757 pic14_emitcode("push","%s",s);
1762 /* if bit variable */
1763 if (!aop->aopu.aop_dir) {
1764 pic14_emitcode("clr","a");
1765 pic14_emitcode("rlc","a");
1768 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1771 pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1774 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1776 lbl = newiTempLabel(NULL);
1778 if (strcmp(s,"a")) {
1781 pic14_emitcode("clr","c");
1782 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1783 pic14_emitcode("cpl","c");
1784 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1785 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1792 if (strcmp(aop->aopu.aop_str[offset],s))
1793 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1798 if (!offset && (strcmp(s,"acc") == 0))
1801 if (strcmp(aop->aopu.aop_str[offset],s))
1802 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1806 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1807 "aopPut got unsupported aop->type");
1813 /*-----------------------------------------------------------------*/
1814 /* mov2w_op - generate either a MOVLW or MOVFW based operand type */
1815 /*-----------------------------------------------------------------*/
1816 static void mov2w_op (operand *op, int offset)
1821 /* for PO_IMMEDIATEs: use address or value? */
1822 if (op_isLitLike (op))
1824 /* access address of op */
1825 if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
1826 if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
1828 if (offset == GPTRSIZE-1)
1829 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1831 emitpcode (POC_MOVLW, popGetLit (0));
1834 emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
1836 /* access value stored in op */
1837 mov2w (AOP(op), offset);
1842 /*-----------------------------------------------------------------*/
1843 /* mov2w - generate either a MOVLW or MOVFW based operand type */
1844 /*-----------------------------------------------------------------*/
1845 void mov2w (asmop *aop, int offset)
1851 DEBUGpic14_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
1853 if ( aop_isLitLike (aop) )
1854 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1856 emitpcode(POC_MOVFW,popGet(aop,offset));
1860 static void movwf (asmop *op, int offset)
1862 emitpcode (POC_MOVWF, popGet(op, offset));
1865 static pCodeOp *get_argument_pcop (int idx)
1867 assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1868 return popRegFromIdx (Gstack_base_addr - (idx - 1));
1871 static pCodeOp *get_return_val_pcop (int offset)
1873 assert (offset > 0 && "the most significant byte is returned via WREG");
1874 return popRegFromIdx (Gstack_base_addr - (offset - 1));
1877 static void pass_argument (operand *op, int offset, int idx)
1880 mov2w_op (op, offset);
1882 emitpcode(POC_MOVWF, get_argument_pcop (idx));
1885 static void get_returnvalue (operand *op, int offset, int idx)
1888 emitpcode(POC_MOVFW, get_return_val_pcop (idx));
1889 movwf(AOP(op), offset);
1892 static void call_libraryfunc (char *name)
1894 /* library code might reside in different page... */
1895 emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1896 /* call the library function */
1897 emitpcode (POC_CALL, popGetExternal (name));
1898 /* might return from different page... */
1899 emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1902 /*-----------------------------------------------------------------*/
1903 /* reAdjustPreg - points a register back to where it should */
1904 /*-----------------------------------------------------------------*/
1905 static void reAdjustPreg (asmop *aop)
1909 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1911 if ((size = aop->size) <= 1)
1914 switch (aop->type) {
1918 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1922 if (aop->type == AOP_DPTR2)
1928 pic14_emitcode("lcall","__decdptr");
1931 if (aop->type == AOP_DPTR2)
1944 /*-----------------------------------------------------------------*/
1945 /* opIsGptr: returns non-zero if the passed operand is */
1946 /* a generic pointer type. */
1947 /*-----------------------------------------------------------------*/
1948 static int opIsGptr(operand *op)
1950 sym_link *type = operandType(op);
1952 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1953 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1961 /*-----------------------------------------------------------------*/
1962 /* pic14_getDataSize - get the operand data size */
1963 /*-----------------------------------------------------------------*/
1964 int pic14_getDataSize(operand *op)
1968 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1971 size = getSize(OP_SYM_ETYPE(op));
1973 //return AOP_SIZE(op);
1975 // tsd- in the pic port, the genptr size is 1, so this code here
1976 // fails. ( in the 8051 port, the size was 4).
1978 size = AOP_SIZE(op);
1979 if (IS_GENPTR(OP_SYM_TYPE(op)))
1981 sym_link *type = operandType(op);
1982 if (IS_GENPTR(type))
1984 /* generic pointer; arithmetic operations
1985 * should ignore the high byte (pointer type).
1988 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1995 /*-----------------------------------------------------------------*/
1996 /* pic14_outAcc - output Acc */
1997 /*-----------------------------------------------------------------*/
1998 void pic14_outAcc(operand *result)
2001 DEBUGpic14_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2002 DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
2005 size = pic14_getDataSize(result);
2007 emitpcode(POC_MOVWF,popGet(AOP(result),0));
2010 /* unsigned or positive */
2012 emitpcode(POC_CLRF,popGet(AOP(result),offset++));
2017 /*-----------------------------------------------------------------*/
2018 /* pic14_outBitC - output a bit C */
2019 /*-----------------------------------------------------------------*/
2020 void pic14_outBitC(operand *result)
2023 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2024 /* if the result is bit */
2025 if (AOP_TYPE(result) == AOP_CRY)
2026 aopPut(AOP(result),"c",0);
2028 pic14_emitcode("clr","a ; %d", __LINE__);
2029 pic14_emitcode("rlc","a");
2030 pic14_outAcc(result);
2034 /*-----------------------------------------------------------------*/
2035 /* pic14_toBoolean - emit code for orl a,operator(sizeop) */
2036 /*-----------------------------------------------------------------*/
2037 void pic14_toBoolean(operand *oper)
2039 int size = AOP_SIZE(oper);
2042 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2047 /* MOVFW does not load the flags... */
2048 if (AOP_TYPE(oper) == AOP_ACC) {
2049 emitpcode(POC_IORLW, popGetLit(0));
2052 emitpcode(POC_MOVLW, popGetLit(0));
2056 if ( AOP_TYPE(oper) != AOP_ACC) {
2057 emitpcode(POC_MOVFW,popGet(AOP(oper),0));
2062 while (offset < size) {
2063 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
2065 /* Z is set iff (oper == 0) */
2069 /*-----------------------------------------------------------------*/
2070 /* genNot - generate code for ! operation */
2071 /*-----------------------------------------------------------------*/
2072 static void genNot (iCode *ic)
2079 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2080 /* assign asmOps to operand & result */
2081 aopOp (IC_LEFT(ic),ic,FALSE);
2082 aopOp (IC_RESULT(ic),ic,TRUE);
2084 DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2085 /* if in bit space then a special case */
2086 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2087 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2088 emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
2089 emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
2091 emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
2092 emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
2093 emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
2098 size = AOP_SIZE(IC_LEFT(ic));
2099 mov2w (AOP(IC_LEFT(ic)),0);
2102 if (op_isLitLike (IC_LEFT(ic)))
2103 emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
2105 emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
2107 emitpcode(POC_MOVLW, popGetLit (0));
2109 emitpcode(POC_MOVLW, popGetLit (1));
2110 movwf(AOP(IC_RESULT(ic)), 0);
2112 for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
2114 emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
2119 /* release the aops */
2120 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2121 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2125 /*-----------------------------------------------------------------*/
2126 /* genCpl - generate code for complement */
2127 /*-----------------------------------------------------------------*/
2128 static void genCpl (iCode *ic)
2130 operand *left, *result;
2135 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2136 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2137 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2139 /* if both are in bit space then
2141 if (AOP_TYPE(result) == AOP_CRY &&
2142 AOP_TYPE(left) == AOP_CRY ) {
2144 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir);
2145 pic14_emitcode("cpl","c");
2146 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir);
2150 size = AOP_SIZE(result);
2151 if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
2154 if(AOP_TYPE(left) == AOP_ACC)
2155 emitpcode(POC_XORLW, popGetLit(0xff));
2157 emitpcode(POC_COMFW,popGet(AOP(left),offset));
2159 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
2162 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2166 /* release the aops */
2167 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2168 freeAsmop(result,NULL,ic,TRUE);
2171 /*-----------------------------------------------------------------*/
2172 /* genUminusFloat - unary minus for floating points */
2173 /*-----------------------------------------------------------------*/
2174 static void genUminusFloat(operand *op,operand *result)
2176 int size ,offset =0 ;
2181 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2182 /* for this we just need to flip the
2183 first it then copy the rest in place */
2184 size = AOP_SIZE(op) - 1;
2185 l = aopGet(AOP(op),3,FALSE,FALSE);
2189 pic14_emitcode("cpl","acc.7");
2190 aopPut(AOP(result),"a",3);
2194 aopGet(AOP(op),offset,FALSE,FALSE),
2200 /*-----------------------------------------------------------------*/
2201 /* genUminus - unary minus code generation */
2202 /*-----------------------------------------------------------------*/
2203 static void genUminus (iCode *ic)
2206 sym_link *optype, *rtype;
2210 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2212 aopOp(IC_LEFT(ic),ic,FALSE);
2213 aopOp(IC_RESULT(ic),ic,TRUE);
2215 /* if both in bit space then special
2217 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2218 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2220 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0));
2221 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2222 emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0));
2227 optype = operandType(IC_LEFT(ic));
2228 rtype = operandType(IC_RESULT(ic));
2230 /* if float then do float stuff */
2231 if (IS_FLOAT(optype)) {
2232 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2236 /* otherwise subtract from zero by taking the 2's complement */
2237 size = AOP_SIZE(IC_LEFT(ic));
2239 for(i=0; i<size; i++) {
2240 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2241 emitpcode(POC_COMF, popGet(AOP(IC_LEFT(ic)),i));
2243 emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2244 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2248 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0));
2249 for(i=1; i<size; i++) {
2251 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),i));
2255 /* release the aops */
2256 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2257 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2260 /*-----------------------------------------------------------------*/
2261 /* saveRegisters - will look for a call and save the registers */
2262 /*-----------------------------------------------------------------*/
2263 static void saveRegisters(iCode *lic)
2272 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2274 for (ic = lic ; ic ; ic = ic->next)
2275 if (ic->op == CALL || ic->op == PCALL)
2279 fprintf(stderr,"found parameter push with no function call\n");
2283 /* if the registers have been saved already then
2285 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2288 /* find the registers in use at this time
2289 and push them away to safety */
2290 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2294 if (options.useXstack) {
2295 if (bitVectBitValue(rsave,R0_IDX))
2296 pic14_emitcode("mov","b,r0");
2297 pic14_emitcode("mov","r0,%s",spname);
2298 for (i = 0 ; i < pic14_nRegs ; i++) {
2299 if (bitVectBitValue(rsave,i)) {
2301 pic14_emitcode("mov","a,b");
2303 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2304 pic14_emitcode("movx","@r0,a");
2305 pic14_emitcode("inc","r0");
2308 pic14_emitcode("mov","%s,r0",spname);
2309 if (bitVectBitValue(rsave,R0_IDX))
2310 pic14_emitcode("mov","r0,b");
2312 //for (i = 0 ; i < pic14_nRegs ; i++) {
2313 // if (bitVectBitValue(rsave,i))
2314 // pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2317 dtype = operandType(IC_LEFT(ic));
2318 if (currFunc && dtype &&
2319 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2320 IFFUNC_ISISR(currFunc->type) &&
2323 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2326 /*-----------------------------------------------------------------*/
2327 /* unsaveRegisters - pop the pushed registers */
2328 /*-----------------------------------------------------------------*/
2329 static void unsaveRegisters (iCode *ic)
2336 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2337 /* find the registers in use at this time
2338 and push them away to safety */
2339 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2342 if (options.useXstack) {
2343 pic14_emitcode("mov","r0,%s",spname);
2344 for (i = pic14_nRegs ; i >= 0 ; i--) {
2345 if (bitVectBitValue(rsave,i)) {
2346 pic14_emitcode("dec","r0");
2347 pic14_emitcode("movx","a,@r0");
2349 pic14_emitcode("mov","b,a");
2351 pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2355 pic14_emitcode("mov","%s,r0",spname);
2356 if (bitVectBitValue(rsave,R0_IDX))
2357 pic14_emitcode("mov","r0,b");
2359 //for (i = pic14_nRegs ; i >= 0 ; i--) {
2360 // if (bitVectBitValue(rsave,i))
2361 // pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2367 /*-----------------------------------------------------------------*/
2369 /*-----------------------------------------------------------------*/
2370 static void pushSide(operand * oper, int size)
2374 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2376 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2377 if (AOP_TYPE(oper) != AOP_REG &&
2378 AOP_TYPE(oper) != AOP_DIR &&
2380 pic14_emitcode("mov","a,%s",l);
2381 pic14_emitcode("push","acc");
2383 pic14_emitcode("push","%s",l);
2388 /*-----------------------------------------------------------------*/
2389 /* assignResultValue - */
2390 /*-----------------------------------------------------------------*/
2391 static void assignResultValue(operand * oper)
2393 int size = AOP_SIZE(oper);
2398 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2400 DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2402 /* assign MSB first (passed via WREG) */
2404 get_returnvalue (oper, size, offset + GpsuedoStkPtr);
2410 /*-----------------------------------------------------------------*/
2411 /* genIpush - genrate code for pushing this gets a little complex */
2412 /*-----------------------------------------------------------------*/
2413 static void genIpush (iCode *ic)
2417 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2419 int size, offset = 0 ;
2423 /* if this is not a parm push : ie. it is spill push
2424 and spill push is always done on the local stack */
2425 if (!ic->parmPush) {
2427 /* and the item is spilt then do nothing */
2428 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2431 aopOp(IC_LEFT(ic),ic,FALSE);
2432 size = AOP_SIZE(IC_LEFT(ic));
2433 /* push it on the stack */
2435 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2440 pic14_emitcode("push","%s",l);
2445 /* this is a paramter push: in this case we call
2446 the routine to find the call and save those
2447 registers that need to be saved */
2450 /* then do the push */
2451 aopOp(IC_LEFT(ic),ic,FALSE);
2454 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2455 size = AOP_SIZE(IC_LEFT(ic));
2458 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2459 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
2460 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2462 pic14_emitcode("mov","a,%s",l);
2463 pic14_emitcode("push","acc");
2465 pic14_emitcode("push","%s",l);
2468 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2472 /*-----------------------------------------------------------------*/
2473 /* genIpop - recover the registers: can happen only for spilling */
2474 /*-----------------------------------------------------------------*/
2475 static void genIpop (iCode *ic)
2479 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2480 assert (!"genIpop -- unimplemented");
2485 /* if the temp was not pushed then */
2486 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2489 aopOp(IC_LEFT(ic),ic,FALSE);
2490 size = AOP_SIZE(IC_LEFT(ic));
2493 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2496 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2500 /*-----------------------------------------------------------------*/
2501 /* unsaverbank - restores the resgister bank from stack */
2502 /*-----------------------------------------------------------------*/
2503 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2507 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2513 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2515 if (options.useXstack) {
2517 r = getFreePtr(ic,&aop,FALSE);
2520 pic14_emitcode("mov","%s,_spx",r->name);
2521 pic14_emitcode("movx","a,@%s",r->name);
2522 pic14_emitcode("mov","psw,a");
2523 pic14_emitcode("dec","%s",r->name);
2526 pic14_emitcode ("pop","psw");
2529 for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2530 if (options.useXstack) {
2531 pic14_emitcode("movx","a,@%s",r->name);
2532 //pic14_emitcode("mov","(%s+%d),a",
2533 // regspic14[i].base,8*bank+regspic14[i].offset);
2534 pic14_emitcode("dec","%s",r->name);
2537 pic14_emitcode("pop",""); //"(%s+%d)",
2538 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2541 if (options.useXstack) {
2543 pic14_emitcode("mov","_spx,%s",r->name);
2544 freeAsmop(NULL,aop,ic,TRUE);
2550 /*-----------------------------------------------------------------*/
2551 /* saverbank - saves an entire register bank on the stack */
2552 /*-----------------------------------------------------------------*/
2553 static void saverbank (int bank, iCode *ic, bool pushPsw)
2557 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2563 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2564 if (options.useXstack) {
2567 r = getFreePtr(ic,&aop,FALSE);
2568 pic14_emitcode("mov","%s,_spx",r->name);
2572 for (i = 0 ; i < pic14_nRegs ;i++) {
2573 if (options.useXstack) {
2574 pic14_emitcode("inc","%s",r->name);
2575 //pic14_emitcode("mov","a,(%s+%d)",
2576 // regspic14[i].base,8*bank+regspic14[i].offset);
2577 pic14_emitcode("movx","@%s,a",r->name);
2579 pic14_emitcode("push","");// "(%s+%d)",
2580 //regspic14[i].base,8*bank+regspic14[i].offset);
2584 if (options.useXstack) {
2585 pic14_emitcode("mov","a,psw");
2586 pic14_emitcode("movx","@%s,a",r->name);
2587 pic14_emitcode("inc","%s",r->name);
2588 pic14_emitcode("mov","_spx,%s",r->name);
2589 freeAsmop (NULL,aop,ic,TRUE);
2592 pic14_emitcode("push","psw");
2594 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2600 /*-----------------------------------------------------------------*/
2601 /* genCall - generates a call statement */
2602 /*-----------------------------------------------------------------*/
2603 static void genCall (iCode *ic)
2612 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2614 /* if caller saves & we have not saved then */
2618 /* if we are calling a function that is not using
2619 the same register bank then we need to save the
2620 destination registers on the stack */
2621 dtype = operandType(IC_LEFT(ic));
2622 if (currFunc && dtype &&
2623 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2624 IFFUNC_ISISR(currFunc->type) &&
2627 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2629 /* if send set is not empty the assign */
2632 /* For the Pic port, there is no data stack.
2633 * So parameters passed to functions are stored
2634 * in registers. (The pCode optimizer will get
2635 * rid of most of these :).
2637 int psuedoStkPtr=-1;
2638 int firstTimeThruLoop = 1;
2640 _G.sendSet = reverseSet(_G.sendSet);
2642 /* First figure how many parameters are getting passed */
2643 for (sic = setFirstItem(_G.sendSet) ; sic ;
2644 sic = setNextItem(_G.sendSet)) {
2646 aopOp(IC_LEFT(sic),sic,FALSE);
2647 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2648 freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2651 for (sic = setFirstItem(_G.sendSet) ; sic ;
2652 sic = setNextItem(_G.sendSet)) {
2653 int size, offset = 0;
2655 aopOp(IC_LEFT(sic),sic,FALSE);
2656 size = AOP_SIZE(IC_LEFT(sic));
2659 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2660 AopType(AOP_TYPE(IC_LEFT(sic))));
2662 if(!firstTimeThruLoop) {
2663 /* If this is not the first time we've been through the loop
2664 * then we need to save the parameter in a temporary
2665 * register. The last byte of the last parameter is
2667 emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2670 firstTimeThruLoop=0;
2672 mov2w_op (IC_LEFT(sic), offset);
2675 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2680 sym = OP_SYMBOL(IC_LEFT(ic));
2681 name = sym->rname[0] ? sym->rname : sym->name;
2682 isExtern = IS_EXTERN(sym->etype);
2684 emitpcode(POC_PAGESEL,popGetWithString(name,1)); /* Extern functions maybe on another page - must call pagesel */
2686 emitpcode(POC_CALL,popGetWithString(name,isExtern));
2688 emitpcode(POC_PAGESEL,popGetWithString("$",0)); /* May have returned from another page - must call pagesel to restore PCLATH before next goto or call instruction */
2691 /* if we need assign a result value */
2692 if ((IS_ITEMP(IC_RESULT(ic)) &&
2693 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2694 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2695 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2698 aopOp(IC_RESULT(ic),ic,FALSE);
2701 assignResultValue(IC_RESULT(ic));
2703 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2704 AopType(AOP_TYPE(IC_RESULT(ic))));
2706 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2709 /* if register bank was saved then pop them */
2711 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2713 /* if we hade saved some registers then unsave them */
2714 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2715 unsaveRegisters (ic);
2720 /*-----------------------------------------------------------------*/
2721 /* genPcall - generates a call by pointer statement */
2722 /*-----------------------------------------------------------------*/
2723 static void genPcall (iCode *ic)
2726 symbol *albl = newiTempLabel(NULL);
2727 symbol *blbl = newiTempLabel(NULL);
2734 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2735 /* if caller saves & we have not saved then */
2739 /* if we are calling a function that is not using
2740 the same register bank then we need to save the
2741 destination registers on the stack */
2742 dtype = operandType(IC_LEFT(ic));
2743 if (currFunc && dtype &&
2744 IFFUNC_ISISR(currFunc->type) &&
2745 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2746 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2749 aopOp(left,ic,FALSE);
2750 DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2752 poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2754 pushSide(IC_LEFT(ic), FPTRSIZE);
2756 /* if send set is not empty, assign parameters */
2759 DEBUGpic14_emitcode ("; ***","%s %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2760 /* no way to pass args - W always gets used to make the call */
2762 /* first idea - factor out a common helper function and call it.
2763 But don't know how to get it generated only once in its own block
2765 if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2768 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2769 DEBUGpic14_emitcode ("; ***","%s %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2770 buffer = Safe_calloc(1,strlen(rname)+16);
2771 sprintf(buffer, "%s_goto_helper", rname);
2772 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2776 emitpcode(POC_CALL,popGetLabel(albl->key));
2777 pcop = popGetLabel(blbl->key);
2778 emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
2779 emitpcode(POC_GOTO,pcop);
2780 emitpLabel(albl->key);
2782 emitpcode(poc,popGetAddr(AOP(left),1,0));
2783 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2784 emitpcode(poc,popGetAddr(AOP(left),0,0));
2785 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2787 emitpLabel(blbl->key);
2789 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2791 /* if we need to assign a result value */
2792 if ((IS_ITEMP(IC_RESULT(ic)) &&
2793 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2794 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2795 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2798 aopOp(IC_RESULT(ic),ic,FALSE);
2803 assignResultValue(IC_RESULT(ic));
2805 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2808 /* if register bank was saved then unsave them */
2809 if (currFunc && dtype &&
2810 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2811 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2813 /* if we hade saved some registers then
2816 unsaveRegisters (ic);
2820 /*-----------------------------------------------------------------*/
2821 /* resultRemat - result is rematerializable */
2822 /*-----------------------------------------------------------------*/
2823 static int resultRemat (iCode *ic)
2825 // DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2828 if (SKIP_IC(ic) || ic->op == IFX)
2831 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2832 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2833 if (sym->remat && !POINTER_SET(ic))
2840 #if defined(__BORLANDC__) || defined(_MSC_VER)
2841 #define STRCASECMP stricmp
2843 #define STRCASECMP strcasecmp
2847 /*-----------------------------------------------------------------*/
2848 /* inExcludeList - return 1 if the string is in exclude Reg list */
2849 /*-----------------------------------------------------------------*/
2850 static bool inExcludeList(char *s)
2852 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2855 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2856 if (options.excludeRegs[i] &&
2857 STRCASECMP(options.excludeRegs[i],"none") == 0)
2860 for ( i = 0 ; options.excludeRegs[i]; i++) {
2861 if (options.excludeRegs[i] &&
2862 STRCASECMP(s,options.excludeRegs[i]) == 0)
2869 /*-----------------------------------------------------------------*/
2870 /* genFunction - generated code for function entry */
2871 /*-----------------------------------------------------------------*/
2872 static void genFunction (iCode *ic)
2879 DEBUGpic14_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2881 labelOffset += (max_key+4);
2885 /* create the function header */
2886 pic14_emitcode(";","-----------------------------------------");
2887 pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2888 pic14_emitcode(";","-----------------------------------------");
2890 pic14_emitcode("","%s:",sym->rname);
2891 addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2893 ftype = operandType(IC_LEFT(ic));
2895 /* if critical function then turn interrupts off */
2896 if (IFFUNC_ISCRITICAL(ftype))
2897 pic14_emitcode("clr","ea");
2899 /* here we need to generate the equates for the
2900 register bank if required */
2902 if (FUNC_REGBANK(ftype) != rbank) {
2905 rbank = FUNC_REGBANK(ftype);
2906 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2907 if (strcmp(regspic14[i].base,"0") == 0)
2908 pic14_emitcode("","%s = 0x%02x",
2910 8*rbank+regspic14[i].offset);
2912 pic14_emitcode ("","%s = %s + 0x%02x",
2915 8*rbank+regspic14[i].offset);
2920 /* if this is an interrupt service routine */
2921 if (IFFUNC_ISISR(sym->type)) {
2922 /* already done in pic14createInterruptVect() - delete me
2923 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2924 emitpcodeNULLop(POC_NOP);
2925 emitpcodeNULLop(POC_NOP);
2926 emitpcodeNULLop(POC_NOP);
2928 emitpcode(POC_MOVWF, popCopyReg(&pc_wsave));
2929 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2930 emitpcode(POC_CLRF, popCopyReg(&pc_status));
2931 emitpcode(POC_MOVWF, popCopyReg(&pc_ssave));
2932 emitpcode(POC_MOVFW, popCopyReg(&pc_pclath));
2933 emitpcode(POC_MOVWF, popCopyReg(&pc_psave));
2934 emitpcode(POC_CLRF, popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2936 pBlockConvert2ISR(pb);
2937 pic14_hasInterrupt = 1;
2939 if (!inExcludeList("acc"))
2940 pic14_emitcode ("push","acc");
2941 if (!inExcludeList("b"))
2942 pic14_emitcode ("push","b");
2943 if (!inExcludeList("dpl"))
2944 pic14_emitcode ("push","dpl");
2945 if (!inExcludeList("dph"))
2946 pic14_emitcode ("push","dph");
2947 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2949 pic14_emitcode ("push", "dpx");
2950 /* Make sure we're using standard DPTR */
2951 pic14_emitcode ("push", "dps");
2952 pic14_emitcode ("mov", "dps, #0x00");
2953 if (options.stack10bit)
2955 /* This ISR could conceivably use DPTR2. Better save it. */
2956 pic14_emitcode ("push", "dpl1");
2957 pic14_emitcode ("push", "dph1");
2958 pic14_emitcode ("push", "dpx1");
2961 /* if this isr has no bank i.e. is going to
2962 run with bank 0 , then we need to save more
2964 if (!FUNC_REGBANK(sym->type)) {
2966 /* if this function does not call any other
2967 function then we can be economical and
2968 save only those registers that are used */
2969 if (! IFFUNC_HASFCALL(sym->type)) {
2972 /* if any registers used */
2973 if (sym->regsUsed) {
2974 /* save the registers used */
2975 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2976 if (bitVectBitValue(sym->regsUsed,i) ||
2977 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2978 pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);
2983 /* this function has a function call cannot
2984 determines register usage so we will have the
2986 saverbank(0,ic,FALSE);
2991 /* if callee-save to be used for this function
2992 then save the registers being used in this function */
2993 if (IFFUNC_CALLEESAVES(sym->type)) {
2996 /* if any registers used */
2997 if (sym->regsUsed) {
2998 /* save the registers used */
2999 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3000 if (bitVectBitValue(sym->regsUsed,i) ||
3001 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
3002 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
3010 /* set the register bank to the desired value */
3011 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
3012 pic14_emitcode("push","psw");
3013 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);
3016 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3018 if (options.useXstack) {
3019 pic14_emitcode("mov","r0,%s",spname);
3020 pic14_emitcode("mov","a,_bp");
3021 pic14_emitcode("movx","@r0,a");
3022 pic14_emitcode("inc","%s",spname);
3026 /* set up the stack */
3027 pic14_emitcode ("push","_bp"); /* save the callers stack */
3029 pic14_emitcode ("mov","_bp,%s",spname);
3032 /* adjust the stack for the function */
3037 werror(W_STACK_OVERFLOW,sym->name);
3039 if (i > 3 && sym->recvSize < 4) {
3041 pic14_emitcode ("mov","a,sp");
3042 pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3043 pic14_emitcode ("mov","sp,a");
3048 pic14_emitcode("inc","sp");
3053 pic14_emitcode ("mov","a,_spx");
3054 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3055 pic14_emitcode ("mov","_spx,a");
3060 /*-----------------------------------------------------------------*/
3061 /* genEndFunction - generates epilogue for functions */
3062 /*-----------------------------------------------------------------*/
3063 static void genEndFunction (iCode *ic)
3065 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3069 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3071 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3073 pic14_emitcode ("mov","%s,_bp",spname);
3076 /* if use external stack but some variables were
3077 added to the local stack then decrement the
3079 if (options.useXstack && sym->stack) {
3080 pic14_emitcode("mov","a,sp");
3081 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3082 pic14_emitcode("mov","sp,a");
3086 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3087 if (options.useXstack) {
3088 pic14_emitcode("mov","r0,%s",spname);
3089 pic14_emitcode("movx","a,@r0");
3090 pic14_emitcode("mov","_bp,a");
3091 pic14_emitcode("dec","%s",spname);
3095 pic14_emitcode ("pop","_bp");
3099 /* restore the register bank */
3100 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3101 pic14_emitcode ("pop","psw");
3103 if (IFFUNC_ISISR(sym->type)) {
3105 /* now we need to restore the registers */
3106 /* if this isr has no bank i.e. is going to
3107 run with bank 0 , then we need to save more
3109 if (!FUNC_REGBANK(sym->type)) {
3111 /* if this function does not call any other
3112 function then we can be economical and
3113 save only those registers that are used */
3114 if (! IFFUNC_HASFCALL(sym->type)) {
3117 /* if any registers used */
3118 if (sym->regsUsed) {
3119 /* save the registers used */
3120 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3121 if (bitVectBitValue(sym->regsUsed,i) ||
3122 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3123 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3128 /* this function has a function call cannot
3129 determines register usage so we will have the
3131 unsaverbank(0,ic,FALSE);
3135 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3137 if (options.stack10bit)
3139 pic14_emitcode ("pop", "dpx1");
3140 pic14_emitcode ("pop", "dph1");
3141 pic14_emitcode ("pop", "dpl1");
3143 pic14_emitcode ("pop", "dps");
3144 pic14_emitcode ("pop", "dpx");
3146 if (!inExcludeList("dph"))
3147 pic14_emitcode ("pop","dph");
3148 if (!inExcludeList("dpl"))
3149 pic14_emitcode ("pop","dpl");
3150 if (!inExcludeList("b"))
3151 pic14_emitcode ("pop","b");
3152 if (!inExcludeList("acc"))
3153 pic14_emitcode ("pop","acc");
3155 if (IFFUNC_ISCRITICAL(sym->type))
3156 pic14_emitcode("setb","ea");
3159 /* if debug then send end of function */
3160 /* if (options.debug && currFunc) { */
3162 debugFile->writeEndFunction (currFunc, ic, 1);
3165 pic14_emitcode ("reti","");
3166 emitpcode(POC_MOVFW, popCopyReg(&pc_psave));
3167 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
3168 emitpcode(POC_CLRF, popCopyReg(&pc_status));
3169 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3170 emitpcode(POC_MOVWF, popCopyReg(&pc_status));
3171 emitpcode(POC_SWAPF, popCopyReg(&pc_wsave));
3172 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3173 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3174 emitpcodeNULLop(POC_RETFIE);
3177 if (IFFUNC_ISCRITICAL(sym->type))
3178 pic14_emitcode("setb","ea");
3180 if (IFFUNC_CALLEESAVES(sym->type)) {
3183 /* if any registers used */
3184 if (sym->regsUsed) {
3185 /* save the registers used */
3186 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3187 if (bitVectBitValue(sym->regsUsed,i) ||
3188 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3189 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3195 /* if debug then send end of function */
3197 debugFile->writeEndFunction (currFunc, ic, 1);
3200 pic14_emitcode ("return","");
3201 emitpcodeNULLop(POC_RETURN);
3203 /* Mark the end of a function */
3204 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3209 /*-----------------------------------------------------------------*/
3210 /* genRet - generate code for return statement */
3211 /*-----------------------------------------------------------------*/
3212 static void genRet (iCode *ic)
3214 int size,offset = 0;
3218 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3219 /* if we have no return value then
3220 just generate the "ret" */
3224 /* we have something to return then
3225 move the return value into place */
3226 aopOp(IC_LEFT(ic),ic,FALSE);
3227 size = AOP_SIZE(IC_LEFT(ic));
3229 for (offset = 0; offset < size; offset++)
3231 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
3234 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3237 /* generate a jump to the return label
3238 if the next is not the return statement */
3239 if (!(ic->next && ic->next->op == LABEL &&
3240 IC_LABEL(ic->next) == returnLabel)) {
3242 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3247 /*-----------------------------------------------------------------*/
3248 /* genLabel - generates a label */
3249 /*-----------------------------------------------------------------*/
3250 static void genLabel (iCode *ic)
3254 /* special case never generate */
3255 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3256 if (IC_LABEL(ic) == entryLabel)
3259 emitpLabel(IC_LABEL(ic)->key);
3260 pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3263 /*-----------------------------------------------------------------*/
3264 /* genGoto - generates a goto */
3265 /*-----------------------------------------------------------------*/
3267 static void genGoto (iCode *ic)
3271 emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3272 pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3276 /*-----------------------------------------------------------------*/
3277 /* genMultbits :- multiplication of bits */
3278 /*-----------------------------------------------------------------*/
3279 static void genMultbits (operand *left,
3284 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3286 if(!pic14_sameRegs(AOP(result),AOP(right)))
3287 emitpcode(POC_BSF, popGet(AOP(result),0));
3289 emitpcode(POC_BTFSC,popGet(AOP(right),0));
3290 emitpcode(POC_BTFSS,popGet(AOP(left),0));
3291 emitpcode(POC_BCF, popGet(AOP(result),0));
3296 /*-----------------------------------------------------------------*/
3297 /* genMultOneByte : 8 bit multiplication & division */
3298 /*-----------------------------------------------------------------*/
3299 static void genMultOneByte (operand *left,
3303 char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
3311 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3312 DEBUGpic14_AopType(__LINE__,left,right,result);
3313 DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3315 /* (if two literals, the value is computed before) */
3316 /* if one literal, literal on the right */
3317 if (AOP_TYPE(left) == AOP_LIT){
3323 assert (AOP_SIZE(left) == AOP_SIZE(right));
3325 size = min(AOP_SIZE(result),AOP_SIZE(left));
3326 offset = Gstack_base_addr - (2*size - 1);
3328 /* pass right operand as argument */
3329 for (i=0; i < size; i++)
3331 mov2w (AOP(right), i);
3332 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3335 /* pass left operand as argument */
3336 for (i=0; i < size; i++)
3338 mov2w (AOP(left), i);
3339 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3341 assert (offset == Gstack_base_addr);
3343 /* call library routine */
3344 assert (size > 0 && size <= 4);
3345 call_libraryfunc (func[size]);
3348 movwf (AOP(result), size-1);
3349 for (i=0; i < size - 1; i++)
3351 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
3352 movwf (AOP(result), size - 2 - i);
3355 /* now (zero-/sign) extend the result to its size */
3356 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
3359 /*-----------------------------------------------------------------*/
3360 /* genMult - generates code for multiplication */
3361 /*-----------------------------------------------------------------*/
3362 static void genMult (iCode *ic)
3364 operand *left = IC_LEFT(ic);
3365 operand *right = IC_RIGHT(ic);
3366 operand *result= IC_RESULT(ic);
3370 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3371 /* assign the amsops */
3372 aopOp (left,ic,FALSE);
3373 aopOp (right,ic,FALSE);
3374 aopOp (result,ic,TRUE);
3376 DEBUGpic14_AopType(__LINE__,left,right,result);
3378 /* special cases first */
3380 if (AOP_TYPE(left) == AOP_CRY &&
3381 AOP_TYPE(right)== AOP_CRY) {
3382 genMultbits(left,right,result);
3386 /* if both are of size == 1 */
3387 if (AOP_SIZE(left) == 1 &&
3388 AOP_SIZE(right) == 1 ) {
3389 genMultOneByte(left,right,result);
3393 /* should have been converted to function call */
3397 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3398 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3399 freeAsmop(result,NULL,ic,TRUE);
3402 /*-----------------------------------------------------------------*/
3403 /* genDivbits :- division of bits */
3404 /*-----------------------------------------------------------------*/
3405 static void genDivbits (operand *left,
3414 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3415 /* the result must be bit */
3416 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3417 l = aopGet(AOP(left),0,FALSE,FALSE);
3421 pic14_emitcode("div","ab");
3422 pic14_emitcode("rrc","a");
3423 aopPut(AOP(result),"c",0);
3426 /*-----------------------------------------------------------------*/
3427 /* genDivOneByte : 8 bit division */
3428 /*-----------------------------------------------------------------*/
3429 static void genDivOneByte (operand *left,
3436 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3438 assert (AOP_SIZE(result) == 1);
3439 assert (AOP_SIZE(right) == 1);
3440 assert (AOP_SIZE(left) == 1);
3442 size = min(AOP_SIZE(result),AOP_SIZE(left));
3444 if (AOP_TYPE(right) == AOP_LIT)
3446 /* XXX: might add specialized code */
3449 if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3451 /* unsigned division */
3453 mov2w(AOP(right),0);
3454 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3456 call_libraryfunc("__divuchar");
3457 movwf(AOP(result),0);
3462 temp = popGetTempReg();
3463 lbl = newiTempLabel(NULL);
3465 /* XXX: improve this naive approach:
3466 [result] = [a] / [b]
3467 ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
3471 movwf temp // temp <-- left
3472 movf right,W // W <-- right
3476 subwf temp,F // temp <-- temp - W
3477 skipNC // subwf clears CARRY (i.e. sets BORROW) if temp < W
3479 decf result // we just subtract once too often
3482 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3483 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
3486 emitpcode(POC_MOVWF, temp);
3487 mov2w(AOP(right),0);
3488 emitpcode(POC_CLRF, popGet(AOP(result),0));
3490 emitpLabel(lbl->key);
3491 emitpcode(POC_INCF, popGet(AOP(result),0));
3492 emitpcode(POC_SUBWF, temp);
3494 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3495 emitpcode(POC_DECF, popGet(AOP(result),0));
3500 /* signed division */
3501 mov2w(AOP(right),0);
3502 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3504 call_libraryfunc("__divschar");
3505 movwf(AOP(result),0);
3508 /* now performed the signed/unsigned division -- extend result */
3509 addSign(result, 1, !SPEC_USIGN(operandType(result)));
3512 /*-----------------------------------------------------------------*/
3513 /* genDiv - generates code for division */
3514 /*-----------------------------------------------------------------*/
3515 static void genDiv (iCode *ic)
3517 operand *left = IC_LEFT(ic);
3518 operand *right = IC_RIGHT(ic);
3519 operand *result= IC_RESULT(ic);
3522 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3523 /* assign the amsops */
3524 aopOp (left,ic,FALSE);
3525 aopOp (right,ic,FALSE);
3526 aopOp (result,ic,TRUE);
3528 /* special cases first */
3530 if (AOP_TYPE(left) == AOP_CRY &&
3531 AOP_TYPE(right)== AOP_CRY) {
3532 genDivbits(left,right,result);
3536 /* if both are of size == 1 */
3537 if (AOP_SIZE(left) == 1 &&
3538 AOP_SIZE(right) == 1 ) {
3539 genDivOneByte(left,right,result);
3543 /* should have been converted to function call */
3546 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3547 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3548 freeAsmop(result,NULL,ic,TRUE);
3551 /*-----------------------------------------------------------------*/
3552 /* genModbits :- modulus of bits */
3553 /*-----------------------------------------------------------------*/
3554 static void genModbits (operand *left,
3562 /* the result must be bit */
3563 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3564 l = aopGet(AOP(left),0,FALSE,FALSE);
3568 pic14_emitcode("div","ab");
3569 pic14_emitcode("mov","a,b");
3570 pic14_emitcode("rrc","a");
3571 aopPut(AOP(result),"c",0);
3574 /*-----------------------------------------------------------------*/
3575 /* genModOneByte : 8 bit modulus */
3576 /*-----------------------------------------------------------------*/
3577 static void genModOneByte (operand *left,
3584 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3586 assert (AOP_SIZE(result) == 1);
3587 assert (AOP_SIZE(right) == 1);
3588 assert (AOP_SIZE(left) == 1);
3590 size = min(AOP_SIZE(result),AOP_SIZE(left));
3592 if (AOP_TYPE(right) == AOP_LIT)
3594 /* XXX: might add specialized code */
3597 if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3599 /* unsigned division */
3601 mov2w(AOP(right),0);
3602 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3604 call_libraryfunc("__moduchar");
3605 movwf(AOP(result),0);
3610 lbl = newiTempLabel(NULL);
3612 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3614 /* XXX: improve this naive approach:
3615 [result] = [a] % [b]
3616 ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3620 movwf result // result <-- left
3621 movf right,W // W <-- right
3623 subwf result,F // result <-- result - W
3624 skipNC // subwf clears CARRY (i.e. sets BORROW) if result < W
3626 addwf result, F // we just subtract once too often
3629 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3630 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3632 if (!pic14_sameRegs(AOP(left), AOP(result)))
3635 emitpcode(POC_MOVWF, popGet(AOP(result),0));
3637 mov2w(AOP(right),0);
3639 emitpLabel(lbl->key);
3640 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3642 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3643 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3648 /* signed division */
3649 mov2w(AOP(right),0);
3650 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3652 call_libraryfunc("__modschar");
3653 movwf(AOP(result),0);
3656 /* now we performed the signed/unsigned modulus -- extend result */
3657 addSign(result, 1, !SPEC_USIGN(operandType(result)));
3660 /*-----------------------------------------------------------------*/
3661 /* genMod - generates code for division */
3662 /*-----------------------------------------------------------------*/
3663 static void genMod (iCode *ic)
3665 operand *left = IC_LEFT(ic);
3666 operand *right = IC_RIGHT(ic);
3667 operand *result= IC_RESULT(ic);
3670 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3671 /* assign the amsops */
3672 aopOp (left,ic,FALSE);
3673 aopOp (right,ic,FALSE);
3674 aopOp (result,ic,TRUE);
3676 /* special cases first */
3678 if (AOP_TYPE(left) == AOP_CRY &&
3679 AOP_TYPE(right)== AOP_CRY) {
3680 genModbits(left,right,result);
3684 /* if both are of size == 1 */
3685 if (AOP_SIZE(left) == 1 &&
3686 AOP_SIZE(right) == 1 ) {
3687 genModOneByte(left,right,result);
3691 /* should have been converted to function call */
3695 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3696 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3697 freeAsmop(result,NULL,ic,TRUE);
3700 /*-----------------------------------------------------------------*/
3701 /* genIfxJump :- will create a jump depending on the ifx */
3702 /*-----------------------------------------------------------------*/
3704 note: May need to add parameter to indicate when a variable is in bit space.
3706 static void genIfxJump (iCode *ic, char *jval)
3710 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3711 /* if true label then we jump if condition
3713 if ( IC_TRUE(ic) ) {
3715 if(strcmp(jval,"a") == 0)
3717 else if (strcmp(jval,"c") == 0)
3720 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3721 emitpcode(POC_BTFSC, newpCodeOpBit(jval,-1,1));
3724 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3725 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3729 /* false label is present */
3730 if(strcmp(jval,"a") == 0)
3732 else if (strcmp(jval,"c") == 0)
3735 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3736 emitpcode(POC_BTFSS, newpCodeOpBit(jval,-1,1));
3739 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3740 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3745 /* mark the icode as generated */
3750 /*-----------------------------------------------------------------*/
3752 /*-----------------------------------------------------------------*/
3753 static void genSkip(iCode *ifx,int status_bit)
3759 if ( IC_TRUE(ifx) ) {
3760 switch(status_bit) {
3775 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3776 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3780 switch(status_bit) {
3794 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3795 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3802 /*-----------------------------------------------------------------*/
3804 /*-----------------------------------------------------------------*/
3805 static void genSkipc(resolvedIfx *rifx)
3816 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3817 emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3818 rifx->generated = 1;
3822 /*-----------------------------------------------------------------*/
3824 /*-----------------------------------------------------------------*/
3825 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3831 if( (rifx->condition ^ invert_condition) & 1)
3836 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3837 rifx->generated = 1;
3842 /*-----------------------------------------------------------------*/
3844 /*-----------------------------------------------------------------*/
3845 static void genSkipz(iCode *ifx, int condition)
3848 assert (ifx != NULL);
3856 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3858 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3861 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3863 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3869 /*-----------------------------------------------------------------*/
3871 /*-----------------------------------------------------------------*/
3872 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3879 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3881 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3884 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3885 rifx->generated = 1;
3890 /*-----------------------------------------------------------------*/
3891 /* genChkZeroes :- greater or less than comparison */
3892 /* For each byte in a literal that is zero, inclusive or the */
3893 /* the corresponding byte in the operand with W */
3894 /* returns true if any of the bytes are zero */
3895 /*-----------------------------------------------------------------*/
3896 static int genChkZeroes(operand *op, int lit, int size)
3903 i = (lit >> (size*8)) & 0xff;
3907 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3909 emitpcode(POC_IORFW, popGet(AOP(op),size));
3919 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3920 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
3921 #define DEBUGpc emitpComment
3923 /*-----------------------------------------------------------------*/
3924 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
3925 /* aop (if it's NOT a literal) or from lit (if */
3926 /* aop is a literal) */
3927 /*-----------------------------------------------------------------*/
3928 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3929 if (aop->type == AOP_LIT) {
3930 emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3932 emitpcode (POC_MOVFW, popGet (aop, offset));
3936 /* genCmp performs a left < right comparison, stores
3937 * the outcome in result (if != NULL) and generates
3938 * control flow code for the ifx (if != NULL).
3940 * This version leaves in sequences like
3941 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3942 * which should be optmized by the peephole
3943 * optimizer - RN 2005-01-01 */
3944 static void genCmp (operand *left,operand *right,
3945 operand *result, iCode *ifx, int sign)
3955 int invert_result = 0;
3959 assert (AOP_SIZE(left) == AOP_SIZE(right));
3960 assert (left && right);
3962 size = AOP_SIZE(right) - 1;
3963 mask = (0x100UL << (size*8)) - 1;
3964 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3969 resolveIfx (&rIfx, ifx);
3971 /**********************************************************************
3972 * handle bits - bit compares are promoted to int compares seemingly! *
3973 **********************************************************************/
3975 // THIS IS COMPLETELY UNTESTED!
3976 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3977 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3978 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3979 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3982 // 1 < {0,1} is false --> clear C by skipping the next instruction
3983 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3984 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3985 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3986 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3987 emitCLRC; // only skipped for left=0 && right=1
3989 goto correct_result_in_carry;
3993 /*************************************************
3994 * make sure that left is register (or the like) *
3995 *************************************************/
3996 if (!isAOP_REGlike(left)) {
3997 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
3998 assert (isAOP_LIT(left));
3999 assert (isAOP_REGlike(right));
4000 // swap left and right
4001 // left < right <==> right > left <==> (right >= left + 1)
4002 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4004 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4005 // MAXVALUE < right? always false
4006 if (performedLt) emitCLRC; else emitSETC;
4007 goto correct_result_in_carry;
4010 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4011 // that's why we handled it above.
4018 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4019 } else if (isAOP_LIT(right)) {
4020 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4023 assert (isAOP_REGlike(left)); // left must be register or the like
4024 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4026 /*************************************************
4027 * special cases go here *
4028 *************************************************/
4030 if (isAOP_LIT(right)) {
4032 // unsigned comparison to a literal
4033 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4035 // unsigned left < 0? always false
4036 if (performedLt) emitCLRC; else emitSETC;
4037 goto correct_result_in_carry;
4040 // signed comparison to a literal
4041 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4042 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4043 // signed left < 0x80000000? always false
4044 if (performedLt) emitCLRC; else emitSETC;
4045 goto correct_result_in_carry;
4046 } else if (lit == 0) {
4047 // compare left < 0; set CARRY if SIGNBIT(left) is set
4048 if (performedLt) emitSETC; else emitCLRC;
4049 emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
4050 if (performedLt) emitCLRC; else emitSETC;
4051 goto correct_result_in_carry;
4054 } // right is literal
4056 /*************************************************
4057 * perform a general case comparison *
4058 * make sure we get CARRY==1 <==> left >= right *
4059 *************************************************/
4060 // compare most significant bytes
4061 //DEBUGpc ("comparing bytes at offset %d", size);
4063 // unsigned comparison
4064 pic14_mov2w_regOrLit (AOP(right), lit, size);
4065 emitpcode (POC_SUBFW, popGet (AOP(left), size));
4067 // signed comparison
4068 // (add 2^n to both operands then perform an unsigned comparison)
4069 if (isAOP_LIT(right)) {
4070 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4071 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4073 if (litbyte == 0x80) {
4074 // left >= 0x80 -- always true, but more bytes to come
4075 mov2w (AOP(left), size);
4076 emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
4079 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4080 mov2w (AOP(left), size);
4081 emitpcode (POC_ADDLW, popGetLit (0x80));
4082 emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4085 pCodeOp *pctemp = popGetTempReg();
4086 mov2w (AOP(left), size);
4087 emitpcode (POC_ADDLW, popGetLit (0x80));
4088 emitpcode (POC_MOVWF, pctemp);
4089 mov2w (AOP(right), size);
4090 emitpcode (POC_ADDLW, popGetLit (0x80));
4091 emitpcode (POC_SUBFW, pctemp);
4092 popReleaseTempReg(pctemp);
4096 // compare remaining bytes (treat as unsigned case from above)
4097 templbl = newiTempLabel ( NULL );
4100 //DEBUGpc ("comparing bytes at offset %d", offs);
4102 emitpcode (POC_GOTO, popGetLabel (templbl->key));
4103 pic14_mov2w_regOrLit (AOP(right), lit, offs);
4104 emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4106 emitpLabel (templbl->key);
4107 goto result_in_carry;
4111 /****************************************************
4112 * now CARRY contains the result of the comparison: *
4113 * SUBWF sets CARRY iff *
4114 * F-W >= 0 <==> F >= W <==> !(F < W) *
4115 * (F=left, W=right) *
4116 ****************************************************/
4120 // value will be used in the following genSkipc()
4121 rIfx.condition ^= 1;
4124 correct_result_in_carry:
4126 // assign result to variable (if neccessary)
4127 if (result && AOP_TYPE(result) != AOP_CRY) {
4128 //DEBUGpc ("assign result");
4129 size = AOP_SIZE(result);
4131 emitpcode (POC_CLRF, popGet (AOP(result), size));
4133 if (invert_result) {
4135 emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4137 emitpcode (POC_RLF, popGet (AOP(result), 0));
4141 // perform conditional jump
4143 //DEBUGpc ("generate control flow");
4151 /* OLD VERSION -- BUGGY, DO NOT USE */
4153 /*-----------------------------------------------------------------*/
4154 /* genCmp :- greater or less than comparison */
4155 /*-----------------------------------------------------------------*/
4156 static void genCmp (operand *left,operand *right,
4157 operand *result, iCode *ifx, int sign)
4159 int size; //, offset = 0 ;
4160 unsigned long lit = 0L,i = 0;
4161 resolvedIfx rFalseIfx;
4162 // resolvedIfx rTrueIfx;
4166 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4169 DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4170 DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4174 resolveIfx(&rFalseIfx,ifx);
4175 truelbl = newiTempLabel(NULL);
4176 size = max(AOP_SIZE(left),AOP_SIZE(right));
4178 DEBUGpic14_AopType(__LINE__,left,right,result);
4182 /* if literal is on the right then swap with left */
4183 if ((AOP_TYPE(right) == AOP_LIT)) {
4184 operand *tmp = right ;
4185 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4186 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4189 lit = (lit - 1) & mask;
4192 rFalseIfx.condition ^= 1;
4195 } else if ((AOP_TYPE(left) == AOP_LIT)) {
4196 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4200 //if(IC_TRUE(ifx) == NULL)
4201 /* if left & right are bit variables */
4202 if (AOP_TYPE(left) == AOP_CRY &&
4203 AOP_TYPE(right) == AOP_CRY ) {
4204 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4205 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4207 /* subtract right from left if at the
4208 end the carry flag is set then we know that
4209 left is greater than right */
4211 symbol *lbl = newiTempLabel(NULL);
4214 if(AOP_TYPE(right) == AOP_LIT) {
4216 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4218 DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4225 genSkipCond(&rFalseIfx,left,size-1,7);
4227 /* no need to compare to 0...*/
4228 /* NOTE: this is a de-generate compare that most certainly
4229 * creates some dead code. */
4230 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4232 if(ifx) ifx->generated = 1;
4239 //i = (lit >> (size*8)) & 0xff;
4240 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4242 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4244 i = ((0-lit) & 0xff);
4247 /* lit is 0x7f, all signed chars are less than
4248 * this except for 0x7f itself */
4249 emitpcode(POC_XORLW, popGetLit(0x7f));
4250 genSkipz2(&rFalseIfx,0);
4252 emitpcode(POC_ADDLW, popGetLit(0x80));
4253 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4254 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4259 genSkipz2(&rFalseIfx,1);
4261 emitpcode(POC_ADDLW, popGetLit(i));
4262 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4266 if(ifx) ifx->generated = 1;
4270 /* chars are out of the way. now do ints and longs */
4273 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4280 genSkipCond(&rFalseIfx,left,size,7);
4281 if(ifx) ifx->generated = 1;
4286 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4288 //rFalseIfx.condition ^= 1;
4289 //genSkipCond(&rFalseIfx,left,size,7);
4290 //rFalseIfx.condition ^= 1;
4292 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4293 if(rFalseIfx.condition)
4294 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4296 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4298 emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4299 emitpcode(POC_ADDFW, popGet(AOP(left),0));
4300 emitpcode(POC_MOVFW, popGet(AOP(left),1));
4303 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4305 if(rFalseIfx.condition) {
4307 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4313 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4314 emitpLabel(truelbl->key);
4315 if(ifx) ifx->generated = 1;
4322 if( (lit & 0xff) == 0) {
4323 /* lower byte is zero */
4324 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4325 i = ((lit >> 8) & 0xff) ^0x80;
4326 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4327 emitpcode(POC_ADDLW, popGetLit( 0x80));
4328 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4329 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4332 if(ifx) ifx->generated = 1;
4337 /* Special cases for signed longs */
4338 if( (lit & 0xffffff) == 0) {
4339 /* lower byte is zero */
4340 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4341 i = ((lit >> 8*3) & 0xff) ^0x80;
4342 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4343 emitpcode(POC_ADDLW, popGetLit( 0x80));
4344 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4345 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4348 if(ifx) ifx->generated = 1;
4356 if(lit & (0x80 << (size*8))) {
4357 /* lit is negative */
4358 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4360 //genSkipCond(&rFalseIfx,left,size,7);
4362 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4364 if(rFalseIfx.condition)
4365 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4367 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4371 /* lit is positive */
4372 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4373 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4374 if(rFalseIfx.condition)
4375 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4377 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4381 /* There are no more special cases, so perform a general compare */
4383 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4384 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4388 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4390 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4392 //rFalseIfx.condition ^= 1;
4393 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4395 emitpLabel(truelbl->key);
4397 if(ifx) ifx->generated = 1;
4404 /* sign is out of the way. So now do an unsigned compare */
4405 DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4408 /* General case - compare to an unsigned literal on the right.*/
4410 i = (lit >> (size*8)) & 0xff;
4411 emitpcode(POC_MOVLW, popGetLit(i));
4412 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4414 i = (lit >> (size*8)) & 0xff;
4417 emitpcode(POC_MOVLW, popGetLit(i));
4419 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4421 /* this byte of the lit is zero,
4422 *if it's not the last then OR in the variable */
4424 emitpcode(POC_IORFW, popGet(AOP(left),size));
4429 emitpLabel(lbl->key);
4430 //if(emitFinalCheck)
4431 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4433 emitpLabel(truelbl->key);
4435 if(ifx) ifx->generated = 1;
4442 if(AOP_TYPE(left) == AOP_LIT) {
4443 //symbol *lbl = newiTempLabel(NULL);
4445 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4448 DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4451 if((lit == 0) && (sign == 0)){
4454 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4456 emitpcode(POC_IORFW, popGet(AOP(right),--size));
4458 genSkipz2(&rFalseIfx,0);
4459 if(ifx) ifx->generated = 1;
4466 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4467 /* degenerate compare can never be true */
4468 if(rFalseIfx.condition == 0)
4469 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4471 if(ifx) ifx->generated = 1;
4476 /* signed comparisons to a literal byte */
4478 int lp1 = (lit+1) & 0xff;
4480 DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4483 rFalseIfx.condition ^= 1;
4484 genSkipCond(&rFalseIfx,right,0,7);
4487 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4488 emitpcode(POC_XORLW, popGetLit(0x7f));
4489 genSkipz2(&rFalseIfx,1);
4492 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4493 emitpcode(POC_ADDLW, popGetLit(0x80));
4494 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4495 rFalseIfx.condition ^= 1;
4496 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4499 if(ifx) ifx->generated = 1;
4501 /* unsigned comparisons to a literal byte */
4503 switch(lit & 0xff ) {
4505 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4506 genSkipz2(&rFalseIfx,0);
4507 if(ifx) ifx->generated = 1;
4510 genSkipCond(&rFalseIfx,right,0,7);
4511 if(ifx) ifx->generated = 1;
4515 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4516 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4517 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4518 rFalseIfx.condition ^= 1;
4519 if (AOP_TYPE(result) == AOP_CRY) {
4520 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4521 if(ifx) ifx->generated = 1;
4523 DEBUGpic14_emitcode ("; ***","%s %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4524 emitpcode(POC_CLRF, popGet(AOP(result),0));
4525 emitpcode(POC_RLF, popGet(AOP(result),0));
4526 emitpcode(POC_MOVLW, popGetLit(0x01));
4527 emitpcode(POC_XORWF, popGet(AOP(result),0));
4538 /* Size is greater than 1 */
4546 /* this means lit = 0xffffffff, or -1 */
4549 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4550 rFalseIfx.condition ^= 1;
4551 genSkipCond(&rFalseIfx,right,size,7);
4552 if(ifx) ifx->generated = 1;
4559 if(rFalseIfx.condition) {
4560 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4561 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4564 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4566 emitpcode(POC_IORFW, popGet(AOP(right),size));
4570 if(rFalseIfx.condition) {
4571 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4572 emitpLabel(truelbl->key);
4574 rFalseIfx.condition ^= 1;
4575 genSkipCond(&rFalseIfx,right,s,7);
4578 if(ifx) ifx->generated = 1;
4582 if((size == 1) && (0 == (lp1&0xff))) {
4583 /* lower byte of signed word is zero */
4584 DEBUGpic14_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
4585 i = ((lp1 >> 8) & 0xff) ^0x80;
4586 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4587 emitpcode(POC_ADDLW, popGetLit( 0x80));
4588 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4589 rFalseIfx.condition ^= 1;
4590 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4593 if(ifx) ifx->generated = 1;
4597 if(lit & (0x80 << (size*8))) {
4598 /* Lit is less than zero */
4599 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
4600 //rFalseIfx.condition ^= 1;
4601 //genSkipCond(&rFalseIfx,left,size,7);
4602 //rFalseIfx.condition ^= 1;
4603 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4604 //emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4606 if(rFalseIfx.condition)
4607 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4609 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4613 /* Lit is greater than or equal to zero */
4614 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
4615 //rFalseIfx.condition ^= 1;
4616 //genSkipCond(&rFalseIfx,right,size,7);
4617 //rFalseIfx.condition ^= 1;
4619 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4620 //emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4622 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4623 if(rFalseIfx.condition)
4624 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4626 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4631 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4632 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4636 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4638 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4640 rFalseIfx.condition ^= 1;
4641 //rFalseIfx.condition = 1;
4642 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4644 emitpLabel(truelbl->key);
4646 if(ifx) ifx->generated = 1;
4651 /* compare word or long to an unsigned literal on the right.*/
4656 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4659 break; /* handled above */
4662 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4664 emitpcode(POC_IORFW, popGet(AOP(right),size));
4665 genSkipz2(&rFalseIfx,0);
4669 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4671 emitpcode(POC_IORFW, popGet(AOP(right),size));
4674 if(rFalseIfx.condition)
4675 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4677 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4680 emitpcode(POC_MOVLW, popGetLit(lit+1));
4681 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4683 rFalseIfx.condition ^= 1;
4684 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4687 emitpLabel(truelbl->key);
4689 if(ifx) ifx->generated = 1;
4695 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4696 i = (lit >> (size*8)) & 0xff;
4698 emitpcode(POC_MOVLW, popGetLit(i));
4699 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4702 i = (lit >> (size*8)) & 0xff;
4705 emitpcode(POC_MOVLW, popGetLit(i));
4707 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4709 /* this byte of the lit is zero,
4710 *if it's not the last then OR in the variable */
4712 emitpcode(POC_IORFW, popGet(AOP(right),size));
4717 emitpLabel(lbl->key);
4719 rFalseIfx.condition ^= 1;
4720 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4724 emitpLabel(truelbl->key);
4725 if(ifx) ifx->generated = 1;
4729 /* Compare two variables */
4731 DEBUGpic14_emitcode(";sign","%d",sign);
4735 /* Sigh. thus sucks... */
4737 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4738 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4739 emitpcode(POC_MOVLW, popGetLit(0x80));
4740 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4741 emitpcode(POC_XORFW, popGet(AOP(right),size));
4742 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4744 /* Signed char comparison */
4745 /* Special thanks to Nikolai Golovchenko for this snippet */
4746 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4747 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4748 emitpcode(POC_RRFW, popGet(AOP(left),0)); /* could be any register */
4749 emitpcode(POC_XORFW, popGet(AOP(left),0));
4750 emitpcode(POC_XORFW, popGet(AOP(right),0));
4751 emitpcode(POC_ADDLW, popGetLit(0x80));
4753 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4754 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4756 if(ifx) ifx->generated = 1;
4762 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4763 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4767 /* The rest of the bytes of a multi-byte compare */
4771 emitpcode(POC_GOTO, popGetLabel(lbl->key));
4774 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4775 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4780 emitpLabel(lbl->key);
4782 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4783 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
4784 (AOP_TYPE(result) == AOP_REG)) {
4785 emitpcode(POC_CLRF, popGet(AOP(result),0));
4786 emitpcode(POC_RLF, popGet(AOP(result),0));
4788 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4790 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4791 if(ifx) ifx->generated = 1;
4798 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4799 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4800 pic14_outBitC(result);
4802 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4803 /* if the result is used in the next
4804 ifx conditional branch then generate
4805 code a little differently */
4807 genIfxJump (ifx,"c");
4809 pic14_outBitC(result);
4810 /* leave the result in acc */
4816 /*-----------------------------------------------------------------*/
4817 /* genCmpGt :- greater than comparison */
4818 /*-----------------------------------------------------------------*/
4819 static void genCmpGt (iCode *ic, iCode *ifx)
4821 operand *left, *right, *result;
4822 sym_link *letype , *retype;
4826 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4828 right= IC_RIGHT(ic);
4829 result = IC_RESULT(ic);
4831 letype = getSpec(operandType(left));
4832 retype =getSpec(operandType(right));
4833 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4834 /* assign the amsops */
4835 aopOp (left,ic,FALSE);
4836 aopOp (right,ic,FALSE);
4837 aopOp (result,ic,TRUE);
4839 genCmp(right, left, result, ifx, sign);
4841 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4842 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4843 freeAsmop(result,NULL,ic,TRUE);
4846 /*-----------------------------------------------------------------*/
4847 /* genCmpLt - less than comparisons */
4848 /*-----------------------------------------------------------------*/
4849 static void genCmpLt (iCode *ic, iCode *ifx)
4851 operand *left, *right, *result;
4852 sym_link *letype , *retype;
4856 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4858 right= IC_RIGHT(ic);
4859 result = IC_RESULT(ic);
4861 letype = getSpec(operandType(left));
4862 retype =getSpec(operandType(right));
4863 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4865 /* assign the amsops */
4866 aopOp (left,ic,FALSE);
4867 aopOp (right,ic,FALSE);
4868 aopOp (result,ic,TRUE);
4870 genCmp(left, right, result, ifx, sign);
4872 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4873 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4874 freeAsmop(result,NULL,ic,TRUE);
4878 /*-----------------------------------------------------------------*/
4879 /* genc16bit2lit - compare a 16 bit value to a literal */
4880 /*-----------------------------------------------------------------*/
4881 static void genc16bit2lit(operand *op, int lit, int offset)
4886 DEBUGpic14_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
4887 if( (lit&0xff) == 0)
4892 switch( BYTEofLONG(lit,i)) {
4894 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4897 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4900 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4903 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4904 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4909 switch( BYTEofLONG(lit,i)) {
4911 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4915 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4919 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4922 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4924 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4932 /*-----------------------------------------------------------------*/
4933 /* gencjneshort - compare and jump if not equal */
4934 /*-----------------------------------------------------------------*/
4935 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4937 int size = min(AOP_SIZE(left),AOP_SIZE(right));
4942 //unsigned long lit = 0L;
4944 if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4945 emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4948 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4949 DEBUGpic14_AopType(__LINE__,left,right,result);
4951 assert (!pic14_sameRegs (AOP(left), AOP(result)));
4952 assert (!pic14_sameRegs (AOP(right), AOP(result)));
4953 if (AOP_SIZE(result)) {
4954 for (offset = 0; offset < AOP_SIZE(result); offset++)
4955 emitpcode (POC_CLRF, popGet (AOP(result), offset));
4958 assert (AOP_SIZE(left) == AOP_SIZE(right));
4959 //resolveIfx(&rIfx,ifx);
4960 lbl = newiTempLabel (NULL);
4963 mov2w (AOP(right),size);
4964 emitpcode (POC_XORFW, popGet (AOP(left), size));
4968 emitpcode (POC_GOTO, popGetLabel (lbl->key));
4971 emitpLabel (lbl->key);
4972 if (AOP_SIZE(result)) {
4974 emitpcode (POC_INCF, popGet (AOP(result), 0));
4977 genSkipz (ifx, NULL != IC_TRUE(ifx));
4984 DEBUGpic14_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
4985 assert (!pic14_sameRegs (AOP(result), AOP(left)));
4986 assert (!pic14_sameRegs (AOP(result), AOP(right)));
4987 for (offset=0; offset < AOP_SIZE(result); offset++)
4989 emitpcode (POC_CLRF, popGet (AOP(result), offset));
4994 /* if the left side is a literal or
4995 if the right is in a pointer register and left
4997 if ((AOP_TYPE(left) == AOP_LIT) ||
4998 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5003 if(AOP_TYPE(right) == AOP_LIT)
5004 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5006 /* if the right side is a literal then anything goes */
5007 if (AOP_TYPE(right) == AOP_LIT &&
5008 AOP_TYPE(left) != AOP_DIR ) {
5011 genc16bit2lit(left, lit, 0);
5013 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5019 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5020 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5022 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5026 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5034 /* if the right side is in a register or in direct space or
5035 if the left is a pointer register & right is not */
5036 else if (AOP_TYPE(right) == AOP_REG ||
5037 AOP_TYPE(right) == AOP_DIR ||
5038 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5039 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5040 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5041 int lbl_key = lbl->key;
5044 DEBUGpic14_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
5045 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
5046 __FUNCTION__,__LINE__);
5050 /* switch(size) { */
5052 /* genc16bit2lit(left, lit, 0); */
5054 /* emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
5060 if((AOP_TYPE(left) == AOP_DIR) &&
5061 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5063 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5064 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5066 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5068 switch (lit & 0xff) {
5070 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5073 emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
5074 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5075 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5079 emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5080 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5081 //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5082 emitpcode(POC_GOTO,popGetLabel(lbl_key));
5086 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5087 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5092 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5095 if(AOP_TYPE(result) == AOP_CRY) {
5096 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5101 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5103 /* fix me. probably need to check result size too */
5104 //emitpcode(POC_CLRF,popGet(AOP(result),0));
5109 emitpcode(POC_GOTO,popGetLabel(lbl_key));
5119 } else if(AOP_TYPE(right) == AOP_REG &&
5120 AOP_TYPE(left) != AOP_DIR){
5124 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5125 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5126 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5131 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5136 /* right is a pointer reg need both a & b */
5139 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5141 pic14_emitcode("mov","b,%s",l);
5142 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5143 pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
5148 emitpcode(POC_INCF,popGet(AOP(result),0));
5150 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5152 emitpLabel(lbl->key);
5154 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5163 /*-----------------------------------------------------------------*/
5164 /* gencjne - compare and jump if not equal */
5165 /*-----------------------------------------------------------------*/
5166 static void gencjne(operand *left, operand *right, iCode *ifx)
5168 symbol *tlbl = newiTempLabel(NULL);
5170 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5171 gencjneshort(left, right, lbl);
5173 pic14_emitcode("mov","a,%s",one);
5174 pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5175 pic14_emitcode("","%05d_DS_:",lbl->key+100);
5176 pic14_emitcode("clr","a");
5177 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5179 emitpLabel(lbl->key);
5180 emitpLabel(tlbl->key);
5185 /*-----------------------------------------------------------------*/
5186 /* genCmpEq - generates code for equal to */
5187 /*-----------------------------------------------------------------*/
5188 static void genCmpEq (iCode *ic, iCode *ifx)
5190 operand *left, *right, *result;
5192 symbol *false_label;
5195 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5198 DEBUGpic14_emitcode ("; ifx is non-null","");
5200 DEBUGpic14_emitcode ("; ifx is null","");
5202 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5203 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5204 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5206 DEBUGpic14_AopType(__LINE__,left,right,result);
5208 /* if literal, move literal to right */
5209 if (op_isLitLike (IC_LEFT(ic))) {
5210 operand *tmp = right ;
5216 if (ifx && !IC_TRUE(ifx))
5218 assert (IC_FALSE(ifx));
5219 false_label = IC_FALSE(ifx);
5222 size = min(AOP_SIZE(left),AOP_SIZE(right));
5223 assert(!pic14_sameRegs(AOP(result),AOP(left)));
5224 assert(!pic14_sameRegs(AOP(result),AOP(right)));
5226 /* assume left != right */
5229 for (i=0; i < AOP_SIZE(result); i++)
5231 emitpcode(POC_CLRF, popGet(AOP(result),i));
5235 if (AOP_TYPE(right) == AOP_LIT)
5237 unsigned long lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
5239 size = AOP_SIZE(left);
5240 assert(!op_isLitLike(left));
5245 mov2w(AOP(left), 0);
5246 for (i=1; i < size; i++)
5247 emitpcode(POC_IORFW,popGet(AOP(left),i));
5248 /* now Z is set iff `left == right' */
5250 if (!false_label) false_label = newiTempLabel(NULL);
5251 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5255 for (i=0; i < size; i++)
5258 emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
5259 /* now Z is cleared if `left != right' */
5261 if (!false_label) false_label = newiTempLabel(NULL);
5262 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5269 /* right is no literal */
5272 for (i=0; i < size; i++)
5274 mov2w(AOP(right),i);
5275 emitpcode(POC_XORFW,popGet(AOP(left),i));
5276 /* now Z is cleared if `left != right' */
5278 if (!false_label) false_label = newiTempLabel(NULL);
5279 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5283 /* if we reach here, left == right */
5285 if (AOP_SIZE(result) > 0)
5287 emitpcode(POC_INCF, popGet(AOP(result),0));
5290 if (ifx && IC_TRUE(ifx))
5292 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5295 if (false_label && (!ifx || IC_TRUE(ifx)))
5296 emitpLabel(false_label->key);
5298 if (ifx) ifx->generated = 1;
5300 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5301 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5302 freeAsmop(result,NULL,ic,TRUE);
5305 /*-----------------------------------------------------------------*/
5306 /* ifxForOp - returns the icode containing the ifx for operand */
5307 /*-----------------------------------------------------------------*/
5308 static iCode *ifxForOp ( operand *op, iCode *ic )
5311 /* if true symbol then needs to be assigned */
5312 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5313 if (IS_TRUE_SYMOP(op))
5316 /* if this has register type condition and
5317 the next instruction is ifx with the same operand
5318 and live to of the operand is upto the ifx only then */
5320 ic->next->op == IFX &&
5321 IC_COND(ic->next)->key == op->key &&
5322 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5326 ic->next->op == IFX &&
5327 IC_COND(ic->next)->key == op->key) {
5328 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5332 DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5334 ic->next->op == IFX)
5335 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5338 ic->next->op == IFX &&
5339 IC_COND(ic->next)->key == op->key) {
5340 DEBUGpic14_emitcode ("; "," key is okay");
5341 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5342 OP_SYMBOL(op)->liveTo,
5349 /*-----------------------------------------------------------------*/
5350 /* genAndOp - for && operation */
5351 /*-----------------------------------------------------------------*/
5352 static void genAndOp (iCode *ic)
5354 operand *left,*right, *result;
5358 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5359 /* note here that && operations that are in an
5360 if statement are taken away by backPatchLabels
5361 only those used in arthmetic operations remain */
5362 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5363 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5364 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5366 DEBUGpic14_AopType(__LINE__,left,right,result);
5368 emitpcode(POC_MOVFW,popGet(AOP(left),0));
5369 emitpcode(POC_ANDFW,popGet(AOP(right),0));
5370 emitpcode(POC_MOVWF,popGet(AOP(result),0));
5372 /* if both are bit variables */
5373 /* if (AOP_TYPE(left) == AOP_CRY && */
5374 /* AOP_TYPE(right) == AOP_CRY ) { */
5375 /* pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5376 /* pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5377 /* pic14_outBitC(result); */
5379 /* tlbl = newiTempLabel(NULL); */
5380 /* pic14_toBoolean(left); */
5381 /* pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5382 /* pic14_toBoolean(right); */
5383 /* pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5384 /* pic14_outBitAcc(result); */
5387 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5388 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5389 freeAsmop(result,NULL,ic,TRUE);
5393 /*-----------------------------------------------------------------*/
5394 /* genOrOp - for || operation */
5395 /*-----------------------------------------------------------------*/
5398 modified this code, but it doesn't appear to ever get called
5401 static void genOrOp (iCode *ic)
5403 operand *left,*right, *result;
5407 /* note here that || operations that are in an
5408 if statement are taken away by backPatchLabels
5409 only those used in arthmetic operations remain */
5411 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5412 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5413 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5414 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5416 DEBUGpic14_AopType(__LINE__,left,right,result);
5418 for (i=0; i < AOP_SIZE(result); i++)
5420 emitpcode(POC_CLRF, popGet(AOP(result), i));
5423 tlbl = newiTempLabel(NULL);
5424 pic14_toBoolean(left);
5426 emitpcode(POC_GOTO, popGetLabel(tlbl->key));
5427 pic14_toBoolean(right);
5428 emitpLabel(tlbl->key);
5429 /* here Z is clear IFF `left || right' */
5431 emitpcode(POC_INCF, popGet(AOP(result), 0));
5433 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5434 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5435 freeAsmop(result,NULL,ic,TRUE);
5438 /*-----------------------------------------------------------------*/
5439 /* isLiteralBit - test if lit == 2^n */
5440 /*-----------------------------------------------------------------*/
5441 static int isLiteralBit(unsigned long lit)
5443 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5444 0x100L,0x200L,0x400L,0x800L,
5445 0x1000L,0x2000L,0x4000L,0x8000L,
5446 0x10000L,0x20000L,0x40000L,0x80000L,
5447 0x100000L,0x200000L,0x400000L,0x800000L,
5448 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5449 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5453 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5454 for(idx = 0; idx < 32; idx++)
5460 /*-----------------------------------------------------------------*/
5461 /* continueIfTrue - */
5462 /*-----------------------------------------------------------------*/
5463 static void continueIfTrue (iCode *ic)
5466 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5468 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5472 /*-----------------------------------------------------------------*/
5474 /*-----------------------------------------------------------------*/
5475 static void jumpIfTrue (iCode *ic)
5478 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5480 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5484 /*-----------------------------------------------------------------*/
5485 /* jmpTrueOrFalse - */
5486 /*-----------------------------------------------------------------*/
5487 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5490 // ugly but optimized by peephole
5491 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5493 symbol *nlbl = newiTempLabel(NULL);
5494 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5495 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5496 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5497 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5500 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5501 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5506 /*-----------------------------------------------------------------*/
5507 /* genAnd - code for and */
5508 /*-----------------------------------------------------------------*/
5509 static void genAnd (iCode *ic, iCode *ifx)
5511 operand *left, *right, *result;
5513 unsigned long lit = 0L;
5518 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5519 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5520 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5521 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5523 resolveIfx(&rIfx,ifx);
5525 /* if left is a literal & right is not then exchange them */
5526 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5527 AOP_NEEDSACC(left)) {
5528 operand *tmp = right ;
5533 /* if result = right then exchange them */
5534 if(pic14_sameRegs(AOP(result),AOP(right))){
5535 operand *tmp = right ;
5540 /* if right is bit then exchange them */
5541 if (AOP_TYPE(right) == AOP_CRY &&
5542 AOP_TYPE(left) != AOP_CRY){
5543 operand *tmp = right ;
5547 if(AOP_TYPE(right) == AOP_LIT)
5548 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5550 size = AOP_SIZE(result);
5552 DEBUGpic14_AopType(__LINE__,left,right,result);
5555 // result = bit & yy;
5556 if (AOP_TYPE(left) == AOP_CRY){
5557 // c = bit & literal;
5558 if(AOP_TYPE(right) == AOP_LIT){
5560 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5563 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5566 if(size && (AOP_TYPE(result) == AOP_CRY)){
5567 pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5570 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5574 pic14_emitcode("clr","c");
5577 if (AOP_TYPE(right) == AOP_CRY){
5579 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5580 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5583 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5585 pic14_emitcode("rrc","a");
5586 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5592 pic14_outBitC(result);
5594 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5595 genIfxJump(ifx, "c");
5599 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5600 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5601 if((AOP_TYPE(right) == AOP_LIT) &&
5602 (AOP_TYPE(result) == AOP_CRY) &&
5603 (AOP_TYPE(left) != AOP_CRY)){
5604 int posbit = isLiteralBit(lit);
5608 //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5611 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5616 while (posbit > 7) {
5620 emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5621 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5622 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5629 symbol *tlbl = newiTempLabel(NULL);
5630 int sizel = AOP_SIZE(left);
5632 pic14_emitcode("setb","c");
5634 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5635 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5637 if((posbit = isLiteralBit(bytelit)) != 0)
5638 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5640 if(bytelit != 0x0FFL)
5641 pic14_emitcode("anl","a,%s",
5642 aopGet(AOP(right),offset,FALSE,TRUE));
5643 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5648 // bit = left & literal
5650 pic14_emitcode("clr","c");
5651 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5653 // if(left & literal)
5656 jmpTrueOrFalse(ifx, tlbl);
5660 pic14_outBitC(result);
5664 /* if left is same as result */
5665 if(pic14_sameRegs(AOP(result),AOP(left))){
5667 for(;size--; offset++,lit>>=8) {
5668 if(AOP_TYPE(right) == AOP_LIT){
5669 switch(lit & 0xff) {
5671 /* and'ing with 0 has clears the result */
5672 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5675 /* and'ing with 0xff is a nop when the result and left are the same */
5680 int p = my_powof2( (~lit) & 0xff );
5682 /* only one bit is set in the literal, so use a bcf instruction */
5683 emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5686 if(know_W != (int)(lit&0xff))
5687 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5689 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5694 if (AOP_TYPE(left) == AOP_ACC) {
5695 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5697 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5698 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5705 // left & result in different registers
5706 if(AOP_TYPE(result) == AOP_CRY){
5708 // if(size), result in bit
5709 // if(!size && ifx), conditional oper: if(left & right)
5710 symbol *tlbl = newiTempLabel(NULL);
5711 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5713 pic14_emitcode("setb","c");
5715 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5716 pic14_emitcode("anl","a,%s",
5717 aopGet(AOP(left),offset,FALSE,FALSE));
5718 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5723 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5724 pic14_outBitC(result);
5726 jmpTrueOrFalse(ifx, tlbl);
5728 for(;(size--);offset++) {
5730 // result = left & right
5731 if(AOP_TYPE(right) == AOP_LIT){
5732 int t = (lit >> (offset*8)) & 0x0FFL;
5735 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5738 if(AOP_TYPE(left) != AOP_ACC) {
5739 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5741 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5744 if(AOP_TYPE(left) == AOP_ACC) {
5745 emitpcode(POC_ANDLW, popGetLit(t));
5747 emitpcode(POC_MOVLW, popGetLit(t));
5748 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5750 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5755 if (AOP_TYPE(left) == AOP_ACC) {
5756 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5758 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5759 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5761 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5767 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5768 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5769 freeAsmop(result,NULL,ic,TRUE);
5772 /*-----------------------------------------------------------------*/
5773 /* genOr - code for or */
5774 /*-----------------------------------------------------------------*/
5775 static void genOr (iCode *ic, iCode *ifx)
5777 operand *left, *right, *result;
5779 unsigned long lit = 0L;
5782 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5784 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5785 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5786 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5788 DEBUGpic14_AopType(__LINE__,left,right,result);
5790 /* if left is a literal & right is not then exchange them */
5791 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5792 AOP_NEEDSACC(left)) {
5793 operand *tmp = right ;
5798 /* if result = right then exchange them */
5799 if(pic14_sameRegs(AOP(result),AOP(right))){
5800 operand *tmp = right ;
5805 /* if right is bit then exchange them */
5806 if (AOP_TYPE(right) == AOP_CRY &&
5807 AOP_TYPE(left) != AOP_CRY){
5808 operand *tmp = right ;
5813 DEBUGpic14_AopType(__LINE__,left,right,result);
5815 if(AOP_TYPE(right) == AOP_LIT)
5816 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5818 size = AOP_SIZE(result);
5822 if (AOP_TYPE(left) == AOP_CRY){
5823 if(AOP_TYPE(right) == AOP_LIT){
5824 // c = bit & literal;
5826 // lit != 0 => result = 1
5827 if(AOP_TYPE(result) == AOP_CRY){
5829 emitpcode(POC_BSF, popGet(AOP(result),0));
5830 //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5831 // AOP(result)->aopu.aop_dir,
5832 // AOP(result)->aopu.aop_dir);
5834 continueIfTrue(ifx);
5838 // lit == 0 => result = left
5839 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5841 pic14_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5844 if (AOP_TYPE(right) == AOP_CRY){
5845 if(pic14_sameRegs(AOP(result),AOP(left))){
5847 emitpcode(POC_BCF, popGet(AOP(result),0));
5848 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5849 emitpcode(POC_BSF, popGet(AOP(result),0));
5851 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5852 AOP(result)->aopu.aop_dir,
5853 AOP(result)->aopu.aop_dir);
5854 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5855 AOP(right)->aopu.aop_dir,
5856 AOP(right)->aopu.aop_dir);
5857 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5858 AOP(result)->aopu.aop_dir,
5859 AOP(result)->aopu.aop_dir);
5861 if( AOP_TYPE(result) == AOP_ACC) {
5862 emitpcode(POC_MOVLW, popGetLit(0));
5863 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5864 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5865 emitpcode(POC_MOVLW, popGetLit(1));
5869 emitpcode(POC_BCF, popGet(AOP(result),0));
5870 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5871 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5872 emitpcode(POC_BSF, popGet(AOP(result),0));
5874 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5875 AOP(result)->aopu.aop_dir,
5876 AOP(result)->aopu.aop_dir);
5877 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5878 AOP(right)->aopu.aop_dir,
5879 AOP(right)->aopu.aop_dir);
5880 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5881 AOP(left)->aopu.aop_dir,
5882 AOP(left)->aopu.aop_dir);
5883 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5884 AOP(result)->aopu.aop_dir,
5885 AOP(result)->aopu.aop_dir);
5890 symbol *tlbl = newiTempLabel(NULL);
5891 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5894 emitpcode(POC_BCF, popGet(AOP(result),0));
5895 if( AOP_TYPE(right) == AOP_ACC) {
5896 emitpcode(POC_IORLW, popGetLit(0));
5898 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5899 emitpcode(POC_BSF, popGet(AOP(result),0));
5904 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5905 pic14_emitcode(";XXX setb","c");
5906 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5907 AOP(left)->aopu.aop_dir,tlbl->key+100);
5908 pic14_toBoolean(right);
5909 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5910 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5911 jmpTrueOrFalse(ifx, tlbl);
5915 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5922 pic14_outBitC(result);
5924 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5925 genIfxJump(ifx, "c");
5929 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5930 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5931 if((AOP_TYPE(right) == AOP_LIT) &&
5932 (AOP_TYPE(result) == AOP_CRY) &&
5933 (AOP_TYPE(left) != AOP_CRY)){
5935 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5938 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5940 continueIfTrue(ifx);
5943 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5944 // lit = 0, result = boolean(left)
5946 pic14_emitcode(";XXX setb","c");
5947 pic14_toBoolean(right);
5949 symbol *tlbl = newiTempLabel(NULL);
5950 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5952 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5954 genIfxJump (ifx,"a");
5958 pic14_outBitC(result);
5962 /* if left is same as result */
5963 if(pic14_sameRegs(AOP(result),AOP(left))){
5965 for(;size--; offset++,lit>>=8) {
5966 if(AOP_TYPE(right) == AOP_LIT){
5967 if((lit & 0xff) == 0)
5968 /* or'ing with 0 has no effect */
5971 int p = my_powof2(lit & 0xff);
5973 /* only one bit is set in the literal, so use a bsf instruction */
5975 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5977 if(know_W != (int)(lit & 0xff))
5978 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5979 know_W = lit & 0xff;
5980 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5985 if (AOP_TYPE(left) == AOP_ACC) {
5986 emitpcode(POC_IORFW, popGet(AOP(right),offset));
5987 pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5989 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
5990 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5992 pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5993 pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5999 // left & result in different registers
6000 if(AOP_TYPE(result) == AOP_CRY){
6002 // if(size), result in bit
6003 // if(!size && ifx), conditional oper: if(left | right)
6004 symbol *tlbl = newiTempLabel(NULL);
6005 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6006 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6010 pic14_emitcode(";XXX setb","c");
6012 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6013 pic14_emitcode(";XXX orl","a,%s",
6014 aopGet(AOP(left),offset,FALSE,FALSE));
6015 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6020 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6021 pic14_outBitC(result);
6023 jmpTrueOrFalse(ifx, tlbl);
6024 } else for(;(size--);offset++){
6026 // result = left | right
6027 if(AOP_TYPE(right) == AOP_LIT){
6028 int t = (lit >> (offset*8)) & 0x0FFL;
6031 if (AOP_TYPE(left) != AOP_ACC) {
6032 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
6034 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6038 if (AOP_TYPE(left) == AOP_ACC) {
6039 emitpcode(POC_IORLW, popGetLit(t));
6041 emitpcode(POC_MOVLW, popGetLit(t));
6042 emitpcode(POC_IORFW, popGet(AOP(left),offset));
6044 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6049 // faster than result <- left, anl result,right
6050 // and better if result is SFR
6051 if (AOP_TYPE(left) == AOP_ACC) {
6052 emitpcode(POC_IORFW,popGet(AOP(right),offset));
6054 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6055 emitpcode(POC_IORFW,popGet(AOP(left),offset));
6057 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6062 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6063 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6064 freeAsmop(result,NULL,ic,TRUE);
6067 /*-----------------------------------------------------------------*/
6068 /* genXor - code for xclusive or */
6069 /*-----------------------------------------------------------------*/
6070 static void genXor (iCode *ic, iCode *ifx)
6072 operand *left, *right, *result;
6074 unsigned long lit = 0L;
6077 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6079 aopOp((left = IC_LEFT(ic)),ic,FALSE);
6080 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6081 aopOp((result=IC_RESULT(ic)),ic,TRUE);
6083 /* if left is a literal & right is not ||
6084 if left needs acc & right does not */
6085 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6086 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6087 operand *tmp = right ;
6092 /* if result = right then exchange them */
6093 if(pic14_sameRegs(AOP(result),AOP(right))){
6094 operand *tmp = right ;
6099 /* if right is bit then exchange them */
6100 if (AOP_TYPE(right) == AOP_CRY &&
6101 AOP_TYPE(left) != AOP_CRY){
6102 operand *tmp = right ;
6106 if(AOP_TYPE(right) == AOP_LIT)
6107 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6109 size = AOP_SIZE(result);
6113 if (AOP_TYPE(left) == AOP_CRY){
6114 if(AOP_TYPE(right) == AOP_LIT){
6115 // c = bit & literal;
6117 // lit>>1 != 0 => result = 1
6118 if(AOP_TYPE(result) == AOP_CRY){
6120 {emitpcode(POC_BSF, popGet(AOP(result),offset));
6121 pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6123 continueIfTrue(ifx);
6126 pic14_emitcode("setb","c");
6130 // lit == 0, result = left
6131 if(size && pic14_sameRegs(AOP(result),AOP(left)))
6133 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6135 // lit == 1, result = not(left)
6136 if(size && pic14_sameRegs(AOP(result),AOP(left))){
6137 emitpcode(POC_MOVLW, popGet(AOP(result),offset));
6138 emitpcode(POC_XORWF, popGet(AOP(result),offset));
6139 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6142 assert ( !"incomplete genXor" );
6143 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6144 pic14_emitcode("cpl","c");
6151 symbol *tlbl = newiTempLabel(NULL);
6152 if (AOP_TYPE(right) == AOP_CRY){
6154 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6157 int sizer = AOP_SIZE(right);
6159 // if val>>1 != 0, result = 1
6160 pic14_emitcode("setb","c");
6162 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6164 // test the msb of the lsb
6165 pic14_emitcode("anl","a,#0xfe");
6166 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6170 pic14_emitcode("rrc","a");
6172 pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6173 pic14_emitcode("cpl","c");
6174 pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6179 pic14_outBitC(result);
6181 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6182 genIfxJump(ifx, "c");
6186 if(pic14_sameRegs(AOP(result),AOP(left))){
6187 /* if left is same as result */
6188 for(;size--; offset++) {
6189 if(AOP_TYPE(right) == AOP_LIT){
6190 int t = (lit >> (offset*8)) & 0x0FFL;
6194 if (IS_AOP_PREG(left)) {
6195 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6196 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6197 aopPut(AOP(result),"a",offset);
6199 emitpcode(POC_MOVLW, popGetLit(t));
6200 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6201 pic14_emitcode("xrl","%s,%s",
6202 aopGet(AOP(left),offset,FALSE,TRUE),
6203 aopGet(AOP(right),offset,FALSE,FALSE));
6206 if (AOP_TYPE(left) == AOP_ACC)
6207 pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6209 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6210 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6212 if (IS_AOP_PREG(left)) {
6213 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6214 aopPut(AOP(result),"a",offset);
6216 pic14_emitcode("xrl","%s,a",
6217 aopGet(AOP(left),offset,FALSE,TRUE));
6223 // left & result in different registers
6224 if(AOP_TYPE(result) == AOP_CRY){
6226 // if(size), result in bit
6227 // if(!size && ifx), conditional oper: if(left ^ right)
6228 symbol *tlbl = newiTempLabel(NULL);
6229 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6231 pic14_emitcode("setb","c");
6233 if((AOP_TYPE(right) == AOP_LIT) &&
6234 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6235 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6237 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6238 pic14_emitcode("xrl","a,%s",
6239 aopGet(AOP(left),offset,FALSE,FALSE));
6241 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6246 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6247 pic14_outBitC(result);
6249 jmpTrueOrFalse(ifx, tlbl);
6250 } else for(;(size--);offset++){
6252 // result = left & right
6253 if(AOP_TYPE(right) == AOP_LIT){
6254 int t = (lit >> (offset*8)) & 0x0FFL;
6257 if (AOP_TYPE(left) != AOP_ACC) {
6258 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6260 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6261 pic14_emitcode("movf","%s,w",
6262 aopGet(AOP(left),offset,FALSE,FALSE));
6263 pic14_emitcode("movwf","%s",
6264 aopGet(AOP(result),offset,FALSE,FALSE));
6267 if (AOP_TYPE(left) == AOP_ACC) {
6268 emitpcode(POC_XORLW, popGetLit(t));
6270 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6272 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6275 if (AOP_TYPE(left) == AOP_ACC) {
6276 emitpcode(POC_XORLW, popGetLit(t));
6278 emitpcode(POC_MOVLW, popGetLit(t));
6279 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6281 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6282 pic14_emitcode("movlw","0x%x",t);
6283 pic14_emitcode("xorwf","%s,w",
6284 aopGet(AOP(left),offset,FALSE,FALSE));
6285 pic14_emitcode("movwf","%s",
6286 aopGet(AOP(result),offset,FALSE,FALSE));
6292 // faster than result <- left, anl result,right
6293 // and better if result is SFR
6294 if (AOP_TYPE(left) == AOP_ACC) {
6295 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6297 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6298 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6300 if ( AOP_TYPE(result) != AOP_ACC){
6301 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6307 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6308 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6309 freeAsmop(result,NULL,ic,TRUE);
6312 /*-----------------------------------------------------------------*/
6313 /* genInline - write the inline code out */
6314 /*-----------------------------------------------------------------*/
6315 static void genInline (iCode *ic)
6317 char *buffer, *bp, *bp1;
6320 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6322 _G.inLine += (!options.asmpeep);
6324 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6325 strcpy(buffer,IC_INLINE(ic));
6327 /* emit each line as a code */
6333 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6341 /* print label, use this special format with NULL directive
6342 * to denote that the argument should not be indented with tab */
6343 addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6350 if ((bp1 != bp) && *bp1)
6351 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6355 _G.inLine -= (!options.asmpeep);
6358 /*-----------------------------------------------------------------*/
6359 /* genRRC - rotate right with carry */
6360 /*-----------------------------------------------------------------*/
6361 static void genRRC (iCode *ic)
6363 operand *left , *result ;
6364 int size, offset = 0, same;
6367 /* rotate right with carry */
6369 result=IC_RESULT(ic);
6370 aopOp (left,ic,FALSE);
6371 aopOp (result,ic,FALSE);
6373 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6375 same = pic14_sameRegs(AOP(result),AOP(left));
6377 size = AOP_SIZE(result);
6379 /* get the lsb and put it into the carry */
6380 emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6387 emitpcode(POC_RRF, popGet(AOP(left),offset));
6389 emitpcode(POC_RRFW, popGet(AOP(left),offset));
6390 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6396 freeAsmop(left,NULL,ic,TRUE);
6397 freeAsmop(result,NULL,ic,TRUE);
6400 /*-----------------------------------------------------------------*/
6401 /* genRLC - generate code for rotate left with carry */
6402 /*-----------------------------------------------------------------*/
6403 static void genRLC (iCode *ic)
6405 operand *left , *result ;
6406 int size, offset = 0;
6410 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6411 /* rotate right with carry */
6413 result=IC_RESULT(ic);
6414 aopOp (left,ic,FALSE);
6415 aopOp (result,ic,FALSE);
6417 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6419 same = pic14_sameRegs(AOP(result),AOP(left));
6421 /* move it to the result */
6422 size = AOP_SIZE(result);
6424 /* get the msb and put it into the carry */
6425 emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6432 emitpcode(POC_RLF, popGet(AOP(left),offset));
6434 emitpcode(POC_RLFW, popGet(AOP(left),offset));
6435 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6442 freeAsmop(left,NULL,ic,TRUE);
6443 freeAsmop(result,NULL,ic,TRUE);
6446 /*-----------------------------------------------------------------*/
6447 /* genGetHbit - generates code get highest order bit */
6448 /*-----------------------------------------------------------------*/
6449 static void genGetHbit (iCode *ic)
6451 operand *left, *result;
6453 result=IC_RESULT(ic);
6454 aopOp (left,ic,FALSE);
6455 aopOp (result,ic,FALSE);
6458 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6459 /* get the highest order byte into a */
6460 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6461 if(AOP_TYPE(result) == AOP_CRY){
6462 pic14_emitcode("rlc","a");
6463 pic14_outBitC(result);
6466 pic14_emitcode("rl","a");
6467 pic14_emitcode("anl","a,#0x01");
6468 pic14_outAcc(result);
6472 freeAsmop(left,NULL,ic,TRUE);
6473 freeAsmop(result,NULL,ic,TRUE);
6476 /*-----------------------------------------------------------------*/
6477 /* AccLsh - shift left accumulator by known count */
6478 /* MARK: pic14 always rotates through CARRY! */
6479 /*-----------------------------------------------------------------*/
6480 static void AccLsh (pCodeOp *pcop,int shCount)
6483 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6484 shCount &= 0x0007; // shCount : 0..7
6491 emitpcode(POC_RLF,pcop);
6495 emitpcode(POC_RLF,pcop);
6496 emitpcode(POC_RLF,pcop);
6499 emitpcode(POC_RLF,pcop);
6500 emitpcode(POC_RLF,pcop);
6501 emitpcode(POC_RLF,pcop);
6504 emitpcode(POC_SWAPF,pcop);
6507 emitpcode(POC_SWAPF,pcop);
6508 emitpcode(POC_RLF,pcop);
6511 emitpcode(POC_SWAPF,pcop);
6512 emitpcode(POC_RLF,pcop);
6513 emitpcode(POC_RLF,pcop);
6516 emitpcode(POC_RRFW,pcop);
6517 emitpcode(POC_RRF,pcop);
6520 /* clear invalid bits */
6521 emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6522 emitpcode(POC_ANDWF, pcop);
6525 /*-----------------------------------------------------------------*/
6526 /* AccRsh - shift right accumulator by known count */
6527 /* MARK: pic14 always rotates through CARRY! */
6528 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6529 /* 1: mask out invalid bits (zero-extend) */
6530 /* 2: sign-extend result (pretty slow) */
6531 /*-----------------------------------------------------------------*/
6532 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6535 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6536 shCount &= 0x0007; // shCount : 0..7
6542 /* load sign if needed */
6543 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6544 else if (mask_mode == 1) emitCLRC;
6545 emitpcode(POC_RRF,pcop);
6549 /* load sign if needed */
6550 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6551 emitpcode(POC_RRF,pcop);
6552 /* load sign if needed */
6553 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6554 emitpcode(POC_RRF,pcop);
6555 if (mask_mode == 2) return;
6558 /* load sign if needed */
6559 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6560 emitpcode(POC_RRF,pcop);
6561 /* load sign if needed */
6562 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6563 emitpcode(POC_RRF,pcop);
6564 /* load sign if needed */
6565 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6566 emitpcode(POC_RRF,pcop);
6567 if (mask_mode == 2) return;
6570 emitpcode(POC_SWAPF,pcop);
6573 emitpcode(POC_SWAPF,pcop);
6574 emitpcode(POC_RRF,pcop);
6577 emitpcode(POC_SWAPF,pcop);
6578 emitpcode(POC_RRF,pcop);
6579 emitpcode(POC_RRF,pcop);
6585 emitpcode(POC_RLFW,pcop);
6586 emitpcode(POC_CLRF,pcop);
6588 emitpcode(POC_COMF,pcop);
6591 emitpcode(POC_RLFW,pcop);
6592 emitpcode(POC_RLF,pcop);
6599 /* leave invalid bits undefined */
6603 /* clear invalid bits -- zero-extend */
6604 emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6605 emitpcode(POC_ANDWF, pcop);
6607 if (mask_mode == 2) {
6609 emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6610 emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6611 emitpcode(POC_IORWF, pcop);
6616 /*-----------------------------------------------------------------*/
6617 /* AccSRsh - signed right shift accumulator by known count */
6618 /*-----------------------------------------------------------------*/
6619 static void AccSRsh (int shCount)
6622 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6625 pic14_emitcode("mov","c,acc.7");
6626 pic14_emitcode("rrc","a");
6627 } else if(shCount == 2){
6628 pic14_emitcode("mov","c,acc.7");
6629 pic14_emitcode("rrc","a");
6630 pic14_emitcode("mov","c,acc.7");
6631 pic14_emitcode("rrc","a");
6633 tlbl = newiTempLabel(NULL);
6634 /* rotate right accumulator */
6635 AccRol(8 - shCount);
6636 /* and kill the higher order bits */
6637 pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6638 pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6639 pic14_emitcode("orl","a,#0x%02x",
6640 (unsigned char)~SRMask[shCount]);
6641 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6646 /*-----------------------------------------------------------------*/
6647 /* shiftR1Left2Result - shift right one byte from left to result */
6648 /*-----------------------------------------------------------------*/
6649 static void shiftR1Left2ResultSigned (operand *left, int offl,
6650 operand *result, int offr,
6656 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6658 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6662 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6664 emitpcode(POC_RRF, popGet(AOP(result),offr));
6666 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6667 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6673 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6675 emitpcode(POC_RRF, popGet(AOP(result),offr));
6677 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6678 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6680 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6681 emitpcode(POC_RRF, popGet(AOP(result),offr));
6687 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6689 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6690 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6693 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6694 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6695 emitpcode(POC_ANDLW, popGetLit(0x1f));
6697 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6698 emitpcode(POC_IORLW, popGetLit(0xe0));
6700 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6704 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6705 emitpcode(POC_ANDLW, popGetLit(0x0f));
6706 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6707 emitpcode(POC_IORLW, popGetLit(0xf0));
6708 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6712 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6714 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6715 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6717 emitpcode(POC_RRFW, popGet(AOP(result),offr));
6718 emitpcode(POC_ANDLW, popGetLit(0x07));
6719 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6720 emitpcode(POC_IORLW, popGetLit(0xf8));
6721 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6726 emitpcode(POC_MOVLW, popGetLit(0x00));
6727 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6728 emitpcode(POC_MOVLW, popGetLit(0xfe));
6729 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6730 emitpcode(POC_IORLW, popGetLit(0x01));
6731 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6733 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6734 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6735 emitpcode(POC_DECF, popGet(AOP(result),offr));
6736 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6737 emitpcode(POC_BCF, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6743 emitpcode(POC_MOVLW, popGetLit(0x00));
6744 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6745 emitpcode(POC_MOVLW, popGetLit(0xff));
6746 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6748 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6749 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6750 emitpcode(POC_DECF, popGet(AOP(result),offr));
6758 /*-----------------------------------------------------------------*/
6759 /* shiftR1Left2Result - shift right one byte from left to result */
6760 /*-----------------------------------------------------------------*/
6761 static void shiftR1Left2Result (operand *left, int offl,
6762 operand *result, int offr,
6763 int shCount, int sign)
6768 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6770 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6772 /* Copy the msb into the carry if signed. */
6774 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6784 emitpcode(POC_RRF, popGet(AOP(result),offr));
6786 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6787 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6793 emitpcode(POC_RRF, popGet(AOP(result),offr));
6795 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6796 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6799 emitpcode(POC_RRF, popGet(AOP(result),offr));
6804 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6806 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6807 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6810 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6811 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6812 emitpcode(POC_ANDLW, popGetLit(0x1f));
6813 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6817 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6818 emitpcode(POC_ANDLW, popGetLit(0x0f));
6819 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6823 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6824 emitpcode(POC_ANDLW, popGetLit(0x0f));
6825 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6827 emitpcode(POC_RRF, popGet(AOP(result),offr));
6832 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6833 emitpcode(POC_ANDLW, popGetLit(0x80));
6834 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6835 emitpcode(POC_RLF, popGet(AOP(result),offr));
6836 emitpcode(POC_RLF, popGet(AOP(result),offr));
6841 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6842 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6843 emitpcode(POC_RLF, popGet(AOP(result),offr));
6852 /*-----------------------------------------------------------------*/
6853 /* shiftL1Left2Result - shift left one byte from left to result */
6854 /*-----------------------------------------------------------------*/
6855 static void shiftL1Left2Result (operand *left, int offl,
6856 operand *result, int offr, int shCount)
6862 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6864 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6865 DEBUGpic14_emitcode ("; ***","same = %d",same);
6866 // l = aopGet(AOP(left),offl,FALSE,FALSE);
6868 /* shift left accumulator */
6869 //AccLsh(shCount); // don't comment out just yet...
6870 // aopPut(AOP(result),"a",offr);
6874 /* Shift left 1 bit position */
6875 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6877 emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6879 emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6880 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6884 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6885 emitpcode(POC_ANDLW,popGetLit(0x7e));
6886 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6887 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6890 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6891 emitpcode(POC_ANDLW,popGetLit(0x3e));
6892 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6893 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6894 emitpcode(POC_RLF, popGet(AOP(result),offr));
6897 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6898 emitpcode(POC_ANDLW, popGetLit(0xf0));
6899 emitpcode(POC_MOVWF,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));
6905 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6908 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6909 emitpcode(POC_ANDLW, popGetLit(0x30));
6910 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6911 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6912 emitpcode(POC_RLF, popGet(AOP(result),offr));
6915 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6916 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6917 emitpcode(POC_RRF, popGet(AOP(result),offr));
6921 DEBUGpic14_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6927 /*-----------------------------------------------------------------*/
6928 /* movLeft2Result - move byte from left to result */
6929 /*-----------------------------------------------------------------*/
6930 static void movLeft2Result (operand *left, int offl,
6931 operand *result, int offr)
6935 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6936 if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6937 l = aopGet(AOP(left),offl,FALSE,FALSE);
6939 if (*l == '@' && (IS_AOP_PREG(result))) {
6940 pic14_emitcode("mov","a,%s",l);
6941 aopPut(AOP(result),"a",offr);
6943 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6944 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6949 /*-----------------------------------------------------------------*/
6950 /* shiftLeft_Left2ResultLit - shift left by known count */
6951 /*-----------------------------------------------------------------*/
6953 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6955 int size, same, offr, i;
6957 size = AOP_SIZE(left);
6958 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6960 same = pic14_sameRegs (AOP(left), AOP(result));
6963 shCount = shCount & 0x07;
6969 case 0: /* takes 0 or 2N cycles (for offr==0) */
6970 if (!same || offr) {
6971 for (i=size-1; i >= 0; i--)
6972 movLeft2Result (left, i, result, offr + i);
6976 case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6978 shiftLeft_Left2ResultLit (left, result, 8 * offr);
6979 shiftLeft_Left2ResultLit (result, result, shCount);
6980 return; /* prevent clearing result again */
6983 for (i=0; i < size; i++) {
6984 if (same && !offr) {
6985 emitpcode (POC_RLF, popGet (AOP(left), i));
6987 emitpcode (POC_RLFW, popGet (AOP(left), i));
6988 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6994 case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
6995 /* works in-place/with offr as well */
6996 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
6997 emitpcode (POC_ANDLW, popGetLit (0xF0));
6998 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
7000 for (i = size - 2; i >= 0; i--)
7002 emitpcode (POC_SWAPFW, popGet (AOP(left), i));
7003 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7004 emitpcode (POC_ANDLW, popGetLit (0x0F));
7005 emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
7006 emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
7010 case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
7011 /* works in-place/with offr as well */
7012 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
7013 for (i = size-2; i >= 0; i--) {
7014 emitpcode (POC_RRFW, popGet (AOP(left), i));
7015 emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
7017 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7018 emitpcode (POC_RRF, popGet (AOP(result), offr));
7022 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
7023 shiftLeft_Left2ResultLit (result, result, 1);
7024 return; /* prevent clearing result again */
7030 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7034 /*-----------------------------------------------------------------*/
7035 /* shiftRight_Left2ResultLit - shift right by known count */
7036 /*-----------------------------------------------------------------*/
7038 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
7040 int size, same, offr, i;
7042 size = AOP_SIZE(left);
7043 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7045 same = pic14_sameRegs (AOP(left), AOP(result));
7048 shCount = shCount & 0x07;
7056 case 0: /* takes 0 or 2N cycles (for offr==0) */
7057 if (!same || offr) {
7058 for (i=0; i < size; i++)
7059 movLeft2Result (left, i + offr, result, i);
7063 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7064 emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7066 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7067 shiftRight_Left2ResultLit (result, result, shCount, sign);
7068 return; /* prevent sign-extending result again */
7072 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7075 for (i = size-1; i >= 0; i--) {
7076 if (same && !offr) {
7077 emitpcode (POC_RRF, popGet (AOP(left), i));
7079 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7080 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7086 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7087 /* works in-place/with offr as well */
7088 emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7089 emitpcode (POC_ANDLW, popGetLit (0x0F));
7090 emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7092 for (i = 1; i < size; i++)
7094 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7095 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7096 emitpcode (POC_ANDLW, popGetLit (0xF0));
7097 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7098 emitpcode (POC_XORWF, popGet (AOP(result), i));
7103 emitpcode (POC_MOVLW, popGetLit (0xF0));
7104 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7105 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7109 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7110 /* works in-place/with offr as well */
7111 emitpcode (POC_RLFW, popGet (AOP(left), offr));
7112 for (i = 0; i < size-1; i++) {
7113 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7114 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7116 emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7118 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7121 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7126 shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7127 shiftRight_Left2ResultLit (result, result, 1, sign);
7128 return; /* prevent sign extending result again */
7133 addSign (result, size, sign);
7137 /*-----------------------------------------------------------------*/
7138 /* shiftL2Left2Result - shift left two bytes from left to result */
7139 /*-----------------------------------------------------------------*/
7140 static void shiftL2Left2Result (operand *left, int offl,
7141 operand *result, int offr, int shCount)
7145 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7147 if(pic14_sameRegs(AOP(result), AOP(left))) {
7155 emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7156 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7157 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7161 emitpcode(POC_RLF, popGet(AOP(result),offr));
7162 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7168 emitpcode(POC_MOVLW, popGetLit(0x0f));
7169 emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7170 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7171 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7172 emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7173 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7174 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7176 emitpcode(POC_RLF, popGet(AOP(result),offr));
7177 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7181 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7182 emitpcode(POC_RRF, popGet(AOP(result),offr));
7183 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7184 emitpcode(POC_RRF, popGet(AOP(result),offr));
7185 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7186 emitpcode(POC_ANDLW,popGetLit(0xc0));
7187 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7188 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7189 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7190 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7193 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7194 emitpcode(POC_RRFW, popGet(AOP(result),offr));
7195 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7196 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7197 emitpcode(POC_RRF, popGet(AOP(result),offr));
7207 /* note, use a mov/add for the shift since the mov has a
7208 chance of getting optimized out */
7209 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7210 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7211 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7212 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7213 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7217 emitpcode(POC_RLF, popGet(AOP(result),offr));
7218 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7224 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7225 emitpcode(POC_ANDLW, popGetLit(0xF0));
7226 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7227 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7228 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7229 emitpcode(POC_ANDLW, popGetLit(0xF0));
7230 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7231 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7235 emitpcode(POC_RLF, popGet(AOP(result),offr));
7236 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7240 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7241 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7242 emitpcode(POC_RRFW, popGet(AOP(result),offl));
7243 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7245 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7246 emitpcode(POC_RRF, popGet(AOP(result),offr));
7247 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7248 emitpcode(POC_ANDLW,popGetLit(0xc0));
7249 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7250 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7251 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7252 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7255 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7256 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7257 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7258 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7259 emitpcode(POC_RRF, popGet(AOP(result),offr));
7265 /*-----------------------------------------------------------------*/
7266 /* shiftR2Left2Result - shift right two bytes from left to result */
7267 /*-----------------------------------------------------------------*/
7268 static void shiftR2Left2Result (operand *left, int offl,
7269 operand *result, int offr,
7270 int shCount, int sign)
7275 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7276 same = pic14_sameRegs(AOP(result), AOP(left));
7278 if(same && ((offl + MSB16) == offr)){
7280 /* don't crash result[offr] */
7281 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7282 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7285 movLeft2Result(left,offl, result, offr);
7286 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7289 /* a:x >> shCount (x = lsb(result))*/
7292 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7294 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7303 emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7308 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7309 emitpcode(POC_RRF,popGet(AOP(result),offr));
7311 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7312 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7313 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7314 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7319 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7322 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7323 emitpcode(POC_RRF,popGet(AOP(result),offr));
7330 emitpcode(POC_MOVLW, popGetLit(0xf0));
7331 emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7332 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7334 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7335 emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7336 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7337 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7339 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7340 emitpcode(POC_ANDLW, popGetLit(0x0f));
7341 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7343 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7344 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7345 emitpcode(POC_ANDLW, popGetLit(0xf0));
7346 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7347 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7351 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7352 emitpcode(POC_RRF, popGet(AOP(result),offr));
7356 emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7357 emitpcode(POC_BTFSC,
7358 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7359 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7367 emitpcode(POC_RLF, popGet(AOP(result),offr));
7368 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7370 emitpcode(POC_RLF, popGet(AOP(result),offr));
7371 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7372 emitpcode(POC_RLFW, popGet(AOP(result),offr));
7373 emitpcode(POC_ANDLW,popGetLit(0x03));
7375 emitpcode(POC_BTFSC,
7376 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7377 emitpcode(POC_IORLW,popGetLit(0xfc));
7379 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7380 emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7381 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7382 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7384 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7385 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7386 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7387 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7388 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7389 emitpcode(POC_RLF, popGet(AOP(result),offr));
7390 emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7391 emitpcode(POC_ANDLW,popGetLit(0x03));
7393 emitpcode(POC_BTFSC,
7394 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7395 emitpcode(POC_IORLW,popGetLit(0xfc));
7397 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7398 //emitpcode(POC_RLF, popGet(AOP(result),offr));
7405 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7406 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7407 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7408 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7411 emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7413 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7417 /*-----------------------------------------------------------------*/
7418 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7419 /*-----------------------------------------------------------------*/
7420 static void shiftLLeftOrResult (operand *left, int offl,
7421 operand *result, int offr, int shCount)
7424 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7426 /* shift left accumulator */
7427 AccLsh(left,offl,shCount);
7428 /* or with result */
7429 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7430 assert ( !"broken (modifies left, fails for left==result))" );
7433 /*-----------------------------------------------------------------*/
7434 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7435 /*-----------------------------------------------------------------*/
7436 static void shiftRLeftOrResult (operand *left, int offl,
7437 operand *result, int offr, int shCount)
7440 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7442 /* shift right accumulator */
7443 AccRsh(left,offl,shCount);
7444 /* or with result */
7445 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7446 assert ( !"broken (modifies left, fails for left==result))" );
7449 /*-----------------------------------------------------------------*/
7450 /* genlshOne - left shift a one byte quantity by known count */
7451 /*-----------------------------------------------------------------*/
7452 static void genlshOne (operand *result, operand *left, int shCount)
7455 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7456 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7459 /*-----------------------------------------------------------------*/
7460 /* genlshTwo - left shift two bytes by known amount != 0 */
7461 /*-----------------------------------------------------------------*/
7462 static void genlshTwo (operand *result,operand *left, int shCount)
7467 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7468 size = pic14_getDataSize(result);
7470 /* if shCount >= 8 */
7476 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7478 movLeft2Result(left, LSB, result, MSB16);
7480 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7483 /* 1 <= shCount <= 7 */
7486 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7488 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7492 /*-----------------------------------------------------------------*/
7493 /* shiftLLong - shift left one long from left to result */
7494 /* offl = LSB or MSB16 */
7495 /*-----------------------------------------------------------------*/
7496 static void shiftLLong (operand *left, operand *result, int offr )
7499 int size = AOP_SIZE(result);
7502 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7503 if(size >= LSB+offr){
7504 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7506 pic14_emitcode("add","a,acc");
7507 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7508 size >= MSB16+offr && offr != LSB )
7509 pic14_emitcode("xch","a,%s",
7510 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7512 aopPut(AOP(result),"a",LSB+offr);
7515 if(size >= MSB16+offr){
7516 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7517 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7520 pic14_emitcode("rlc","a");
7521 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7522 size >= MSB24+offr && offr != LSB)
7523 pic14_emitcode("xch","a,%s",
7524 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7526 aopPut(AOP(result),"a",MSB16+offr);
7529 if(size >= MSB24+offr){
7530 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7531 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7534 pic14_emitcode("rlc","a");
7535 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7536 size >= MSB32+offr && offr != LSB )
7537 pic14_emitcode("xch","a,%s",
7538 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7540 aopPut(AOP(result),"a",MSB24+offr);
7543 if(size > MSB32+offr){
7544 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7545 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7548 pic14_emitcode("rlc","a");
7549 aopPut(AOP(result),"a",MSB32+offr);
7552 aopPut(AOP(result),zero,LSB);
7555 /*-----------------------------------------------------------------*/
7556 /* genlshFour - shift four byte by a known amount != 0 */
7557 /*-----------------------------------------------------------------*/
7558 static void genlshFour (operand *result, operand *left, int shCount)
7563 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7564 size = AOP_SIZE(result);
7566 /* if shifting more that 3 bytes */
7567 if (shCount >= 24 ) {
7570 /* lowest order of left goes to the highest
7571 order of the destination */
7572 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7574 movLeft2Result(left, LSB, result, MSB32);
7575 aopPut(AOP(result),zero,LSB);
7576 aopPut(AOP(result),zero,MSB16);
7577 aopPut(AOP(result),zero,MSB32);
7581 /* more than two bytes */
7582 else if ( shCount >= 16 ) {
7583 /* lower order two bytes goes to higher order two bytes */
7585 /* if some more remaining */
7587 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7589 movLeft2Result(left, MSB16, result, MSB32);
7590 movLeft2Result(left, LSB, result, MSB24);
7592 aopPut(AOP(result),zero,MSB16);
7593 aopPut(AOP(result),zero,LSB);
7597 /* if more than 1 byte */
7598 else if ( shCount >= 8 ) {
7599 /* lower order three bytes goes to higher order three bytes */
7603 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7605 movLeft2Result(left, LSB, result, MSB16);
7607 else{ /* size = 4 */
7609 movLeft2Result(left, MSB24, result, MSB32);
7610 movLeft2Result(left, MSB16, result, MSB24);
7611 movLeft2Result(left, LSB, result, MSB16);
7612 aopPut(AOP(result),zero,LSB);
7614 else if(shCount == 1)
7615 shiftLLong(left, result, MSB16);
7617 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7618 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7619 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7620 aopPut(AOP(result),zero,LSB);
7625 /* 1 <= shCount <= 7 */
7626 else if(shCount <= 2){
7627 shiftLLong(left, result, LSB);
7629 shiftLLong(result, result, LSB);
7631 /* 3 <= shCount <= 7, optimize */
7633 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7634 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7635 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7641 /*-----------------------------------------------------------------*/
7642 /* genLeftShiftLiteral - left shifting by known count */
7643 /*-----------------------------------------------------------------*/
7644 static void genLeftShiftLiteral (operand *left,
7649 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7653 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7654 freeAsmop(right,NULL,ic,TRUE);
7656 aopOp(left,ic,FALSE);
7657 aopOp(result,ic,FALSE);
7659 size = getSize(operandType(result));
7662 pic14_emitcode("; shift left ","result %d, left %d",size,
7666 /* I suppose that the left size >= result size */
7669 movLeft2Result(left, size, result, size);
7673 else if(shCount >= (size * 8))
7675 aopPut(AOP(result),zero,size);
7679 genlshOne (result,left,shCount);
7684 genlshTwo (result,left,shCount);
7688 genlshFour (result,left,shCount);
7692 freeAsmop(left,NULL,ic,TRUE);
7693 freeAsmop(result,NULL,ic,TRUE);
7697 /*-----------------------------------------------------------------*
7698 * genMultiAsm - repeat assembly instruction for size of register.
7699 * if endian == 1, then the high byte (i.e base address + size of
7700 * register) is used first else the low byte is used first;
7701 *-----------------------------------------------------------------*/
7702 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7708 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7721 emitpcode(poc, popGet(AOP(reg),offset));
7728 /*-----------------------------------------------------------------*/
7729 /* genLeftShift - generates code for left shifting */
7730 /*-----------------------------------------------------------------*/
7731 static void genLeftShift (iCode *ic)
7733 operand *left,*right, *result;
7735 unsigned long lit = 0L;
7737 symbol *tlbl , *tlbl1;
7741 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7743 right = IC_RIGHT(ic);
7745 result = IC_RESULT(ic);
7747 aopOp(right,ic,FALSE);
7748 aopOp(left,ic,FALSE);
7749 aopOp(result,ic,FALSE);
7752 /* if the shift count is known then do it
7753 as efficiently as possible */
7754 if (AOP_TYPE(right) == AOP_LIT) {
7755 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7759 /* shift count is unknown then we have to form
7760 a loop get the loop count in B : Note: we take
7761 only the lower order byte since shifting
7762 more that 32 bits make no sense anyway, ( the
7763 largest size of an object can be only 32 bits ) */
7765 /* this code fails for RIGHT == RESULT */
7766 assert (!pic14_sameRegs (AOP(right), AOP(result)));
7768 /* now move the left to the result if they are not the
7770 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
7771 AOP_SIZE(result) > 1) {
7773 size = AOP_SIZE(result);
7776 l = aopGet(AOP(left),offset,FALSE,TRUE);
7777 if (*l == '@' && (IS_AOP_PREG(result))) {
7779 pic14_emitcode("mov","a,%s",l);
7780 aopPut(AOP(result),"a",offset);
7782 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
7783 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7784 //aopPut(AOP(result),l,offset);
7790 if(AOP_TYPE(left) == AOP_LIT)
7791 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7793 size = AOP_SIZE(result);
7795 /* if it is only one byte then */
7797 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7798 emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7799 emitpcode(POC_ANDLW, popGetLit(0xf0));
7800 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7801 emitpcode(POC_MOVFW, popGet(AOP(left),0));
7802 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7803 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7804 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7805 emitpcode(POC_RLFW, popGet(AOP(result),0));
7806 emitpcode(POC_ANDLW, popGetLit(0xfe));
7807 emitpcode(POC_ADDFW, popGet(AOP(result),0));
7808 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7809 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7812 tlbl = newiTempLabel(NULL);
7813 if (!pic14_sameRegs(AOP(left),AOP(result))) {
7814 mov2w (AOP(left), 0);
7815 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7818 emitpcode(POC_COMFW, popGet(AOP(right),0));
7819 emitpcode(POC_RRF, popGet(AOP(result),0));
7820 emitpLabel(tlbl->key);
7821 emitpcode(POC_RLF, popGet(AOP(result),0));
7822 emitpcode(POC_ADDLW, popGetLit(1));
7824 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7829 if (pic14_sameRegs(AOP(left),AOP(result))) {
7831 tlbl = newiTempLabel(NULL);
7832 emitpcode(POC_COMFW, popGet(AOP(right),0));
7833 genMultiAsm(POC_RRF, result, size,1);
7834 emitpLabel(tlbl->key);
7835 genMultiAsm(POC_RLF, result, size,0);
7836 emitpcode(POC_ADDLW, popGetLit(1));
7838 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7842 //tlbl = newiTempLabel(NULL);
7844 //tlbl1 = newiTempLabel(NULL);
7846 //reAdjustPreg(AOP(result));
7848 //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7849 //pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7850 //l = aopGet(AOP(result),offset,FALSE,FALSE);
7852 //pic14_emitcode("add","a,acc");
7853 //aopPut(AOP(result),"a",offset++);
7855 // l = aopGet(AOP(result),offset,FALSE,FALSE);
7857 // pic14_emitcode("rlc","a");
7858 // aopPut(AOP(result),"a",offset++);
7860 //reAdjustPreg(AOP(result));
7862 //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7863 //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7866 tlbl = newiTempLabel(NULL);
7867 tlbl1= newiTempLabel(NULL);
7869 size = AOP_SIZE(result);
7872 pctemp = popGetTempReg(); /* grab a temporary working register. */
7874 emitpcode(POC_MOVFW, popGet(AOP(right),0));
7876 /* offset should be 0, 1 or 3 */
7877 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7879 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
7881 emitpcode(POC_MOVWF, pctemp);
7884 emitpLabel(tlbl->key);
7887 emitpcode(POC_RLF, popGet(AOP(result),0));
7889 emitpcode(POC_RLF, popGet(AOP(result),offset++));
7891 emitpcode(POC_DECFSZ, pctemp);
7892 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7893 emitpLabel(tlbl1->key);
7895 popReleaseTempReg(pctemp);
7899 freeAsmop (right,NULL,ic,TRUE);
7900 freeAsmop(left,NULL,ic,TRUE);
7901 freeAsmop(result,NULL,ic,TRUE);
7906 /*-----------------------------------------------------------------*/
7907 /* genrshOne - right shift a one byte quantity by known count */
7908 /*-----------------------------------------------------------------*/
7909 static void genrshOne (operand *result, operand *left,
7910 int shCount, int sign)
7913 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7914 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7917 /*-----------------------------------------------------------------*/
7918 /* genrshTwo - right shift two bytes by known amount != 0 */
7919 /*-----------------------------------------------------------------*/
7920 static void genrshTwo (operand *result,operand *left,
7921 int shCount, int sign)
7924 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7925 /* if shCount >= 8 */
7929 shiftR1Left2Result(left, MSB16, result, LSB,
7932 movLeft2Result(left, MSB16, result, LSB);
7934 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7937 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7938 emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7942 /* 1 <= shCount <= 7 */
7944 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
7947 /*-----------------------------------------------------------------*/
7948 /* shiftRLong - shift right one long from left to result */
7949 /* offl = LSB or MSB16 */
7950 /*-----------------------------------------------------------------*/
7951 static void shiftRLong (operand *left, int offl,
7952 operand *result, int sign)
7957 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7959 size = AOP_SIZE(left);
7960 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7963 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7967 assert (offl >= 0 && offl < size);
7969 same = pic14_sameRegs (AOP(left), AOP(result));
7971 /* perform the shift */
7974 if (same && !offl) {
7975 emitpcode (POC_RRF, popGet (AOP(result), size));
7977 emitpcode (POC_RRFW, popGet (AOP(left), size));
7978 emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7982 addSign (result, AOP_SIZE(left) - offl, sign);
7985 /*-----------------------------------------------------------------*/
7986 /* genrshFour - shift four byte by a known amount != 0 */
7987 /*-----------------------------------------------------------------*/
7988 static void genrshFour (operand *result, operand *left,
7989 int shCount, int sign)
7992 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7993 /* if shifting more that 3 bytes */
7994 if(shCount >= 24 ) {
7997 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7999 movLeft2Result(left, MSB32, result, LSB);
8001 addSign(result, MSB16, sign);
8003 else if(shCount >= 16){
8006 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8008 movLeft2Result(left, MSB24, result, LSB);
8009 movLeft2Result(left, MSB32, result, MSB16);
8011 addSign(result, MSB24, sign);
8013 else if(shCount >= 8){
8016 shiftRLong(left, MSB16, result, sign);
8017 else if(shCount == 0){
8018 movLeft2Result(left, MSB16, result, LSB);
8019 movLeft2Result(left, MSB24, result, MSB16);
8020 movLeft2Result(left, MSB32, result, MSB24);
8021 addSign(result, MSB32, sign);
8024 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8025 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8026 /* the last shift is signed */
8027 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8028 addSign(result, MSB32, sign);
8031 else{ /* 1 <= shCount <= 7 */
8033 shiftRLong(left, LSB, result, sign);
8035 shiftRLong(result, LSB, result, sign);
8038 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8039 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8040 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8045 /*-----------------------------------------------------------------*/
8046 /* genRightShiftLiteral - right shifting by known count */
8047 /*-----------------------------------------------------------------*/
8048 static void genRightShiftLiteral (operand *left,
8054 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8058 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8059 freeAsmop(right,NULL,ic,TRUE);
8061 aopOp(left,ic,FALSE);
8062 aopOp(result,ic,FALSE);
8065 pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8069 lsize = pic14_getDataSize(left);
8070 res_size = pic14_getDataSize(result);
8071 /* test the LEFT size !!! */
8073 /* I suppose that the left size >= result size */
8076 movLeft2Result(left, res_size, result, res_size);
8079 else if(shCount >= (lsize * 8)){
8082 emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8084 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8085 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8090 emitpcode(POC_MOVLW, popGetLit(0));
8091 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8092 emitpcode(POC_MOVLW, popGetLit(0xff));
8094 emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8099 emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8106 genrshOne (result,left,shCount,sign);
8110 genrshTwo (result,left,shCount,sign);
8114 genrshFour (result,left,shCount,sign);
8122 freeAsmop(left,NULL,ic,TRUE);
8123 freeAsmop(result,NULL,ic,TRUE);
8128 /*-----------------------------------------------------------------*/
8129 /* genSignedRightShift - right shift of signed number */
8130 /*-----------------------------------------------------------------*/
8131 static void genSignedRightShift (iCode *ic)
8133 operand *right, *left, *result;
8136 symbol *tlbl, *tlbl1 ;
8139 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8141 /* we do it the hard way put the shift count in b
8142 and loop thru preserving the sign */
8144 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8146 right = IC_RIGHT(ic);
8148 result = IC_RESULT(ic);
8150 aopOp(right,ic,FALSE);
8151 aopOp(left,ic,FALSE);
8152 aopOp(result,ic,FALSE);
8155 if ( AOP_TYPE(right) == AOP_LIT) {
8156 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8157 //genRightShiftLiteral (left,right,result,ic,1);
8160 /* shift count is unknown then we have to form
8161 a loop get the loop count in B : Note: we take
8162 only the lower order byte since shifting
8163 more that 32 bits make no sense anyway, ( the
8164 largest size of an object can be only 32 bits ) */
8166 //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8167 //pic14_emitcode("inc","b");
8168 //freeAsmop (right,NULL,ic,TRUE);
8169 //aopOp(left,ic,FALSE);
8170 //aopOp(result,ic,FALSE);
8172 /* now move the left to the result if they are not the
8174 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
8175 AOP_SIZE(result) > 1) {
8177 size = AOP_SIZE(result);
8181 l = aopGet(AOP(left),offset,FALSE,TRUE);
8182 if (*l == '@' && IS_AOP_PREG(result)) {
8183 pic14_emitcode("mov","a,%s",l);
8184 aopPut(AOP(result),"a",offset);
8186 aopPut(AOP(result),l,offset);
8188 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8189 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8195 /* mov the highest order bit to OVR */
8196 tlbl = newiTempLabel(NULL);
8197 tlbl1= newiTempLabel(NULL);
8199 size = AOP_SIZE(result);
8202 pctemp = popGetTempReg(); /* grab a temporary working register. */
8204 emitpcode(POC_MOVFW, popGet(AOP(right),0));
8206 /* offset should be 0, 1 or 3 */
8207 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8209 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8211 emitpcode(POC_MOVWF, pctemp);
8214 emitpLabel(tlbl->key);
8216 emitpcode(POC_RLFW, popGet(AOP(result),offset));
8217 emitpcode(POC_RRF, popGet(AOP(result),offset));
8220 emitpcode(POC_RRF, popGet(AOP(result),--offset));
8223 emitpcode(POC_DECFSZ, pctemp);
8224 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8225 emitpLabel(tlbl1->key);
8227 popReleaseTempReg(pctemp);
8229 size = AOP_SIZE(result);
8231 pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8232 pic14_emitcode("rlc","a");
8233 pic14_emitcode("mov","ov,c");
8234 /* if it is only one byte then */
8236 l = aopGet(AOP(left),0,FALSE,FALSE);
8238 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8239 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8240 pic14_emitcode("mov","c,ov");
8241 pic14_emitcode("rrc","a");
8242 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8243 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8244 aopPut(AOP(result),"a",0);
8248 reAdjustPreg(AOP(result));
8249 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8250 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8251 pic14_emitcode("mov","c,ov");
8253 l = aopGet(AOP(result),offset,FALSE,FALSE);
8255 pic14_emitcode("rrc","a");
8256 aopPut(AOP(result),"a",offset--);
8258 reAdjustPreg(AOP(result));
8259 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8260 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8265 freeAsmop(left,NULL,ic,TRUE);
8266 freeAsmop(result,NULL,ic,TRUE);
8267 freeAsmop(right,NULL,ic,TRUE);
8271 /*-----------------------------------------------------------------*/
8272 /* loadSignToC - load the operand's sign bit into CARRY */
8273 /*-----------------------------------------------------------------*/
8275 static void loadSignToC (operand *op)
8278 assert (op && AOP(op) && AOP_SIZE(op));
8281 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8285 /*-----------------------------------------------------------------*/
8286 /* genRightShift - generate code for right shifting */
8287 /*-----------------------------------------------------------------*/
8288 static void genGenericShift (iCode *ic, int shiftRight)
8290 operand *right, *left, *result;
8293 symbol *tlbl, *tlbl1, *inverselbl;
8296 /* if signed then we do it the hard way preserve the
8297 sign bit moving it inwards */
8298 retype = getSpec(operandType(IC_RESULT(ic)));
8299 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8301 /* signed & unsigned types are treated the same : i.e. the
8302 signed is NOT propagated inwards : quoting from the
8303 ANSI - standard : "for E1 >> E2, is equivalent to division
8304 by 2**E2 if unsigned or if it has a non-negative value,
8305 otherwise the result is implementation defined ", MY definition
8306 is that the sign does not get propagated */
8308 right = IC_RIGHT(ic);
8310 result = IC_RESULT(ic);
8312 aopOp(right,ic,FALSE);
8313 aopOp(left,ic,FALSE);
8314 aopOp(result,ic,FALSE);
8316 /* if the shift count is known then do it
8317 as efficiently as possible */
8318 if (AOP_TYPE(right) == AOP_LIT) {
8319 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8323 shiftRight = !shiftRight;
8327 shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8329 shiftLeft_Left2ResultLit (left, result, lit);
8330 //genRightShiftLiteral (left,right,result,ic, 0);
8334 /* shift count is unknown then we have to form
8335 a loop get the loop count in B : Note: we take
8336 only the lower order byte since shifting
8337 more that 32 bits make no sense anyway, ( the
8338 largest size of an object can be only 32 bits ) */
8340 /* we must not overwrite the shift counter */
8341 assert (!pic14_sameRegs(AOP(right),AOP(result)));
8343 /* now move the left to the result if they are not the
8345 if (!pic14_sameRegs(AOP(left),AOP(result)))
8347 size = min(AOP_SIZE(result), AOP_SIZE(left));
8349 mov2w(AOP(left), size);
8350 movwf(AOP(result), size);
8352 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8355 tlbl = newiTempLabel(NULL);
8356 tlbl1= newiTempLabel(NULL);
8358 size = AOP_SIZE(result);
8360 mov2w(AOP(right),0);
8361 if (!SPEC_USIGN(operandType(right)))
8363 inverselbl = newiTempLabel(NULL);
8364 /* signed shift count -- invert shift direction for c<0 */
8365 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8366 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8368 emitpcode(POC_SUBLW, popGetLit(0)); /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8369 /* check for `a = b >> c' with `-c == 0' */
8371 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8372 emitpLabel(tlbl->key);
8373 /* propagate the sign bit inwards for SIGNED result */
8374 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8375 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8376 emitpcode(POC_ADDLW, popGetLit(1)); /* clears CARRY (unless W==0 afterwards) */
8378 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8380 if (!SPEC_USIGN(operandType(right)))
8382 symbol *inv_loop = newiTempLabel(NULL);
8384 shiftRight = !shiftRight; /* invert shift direction */
8386 /* we came here from the code above -- we are done */
8387 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8389 /* emit code for shifting N<0 steps, count is already in W */
8390 emitpLabel(inverselbl->key);
8391 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8392 emitpLabel(inv_loop->key);
8393 /* propagate the sign bit inwards for SIGNED result */
8394 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8395 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8396 emitpcode(POC_ADDLW, popGetLit(1));
8398 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8401 emitpLabel(tlbl1->key);
8403 freeAsmop(left,NULL,ic,TRUE);
8404 freeAsmop (right,NULL,ic,TRUE);
8405 freeAsmop(result,NULL,ic,TRUE);
8408 static void genRightShift (iCode *ic)
8410 genGenericShift(ic, 1);
8413 static void genLeftShift (iCode *ic)
8415 genGenericShift(ic, 0);
8418 /*-----------------------------------------------------------------*/
8419 /* SetIrp - Set IRP bit */
8420 /*-----------------------------------------------------------------*/
8421 void SetIrp(operand *result) {
8423 if (AOP_TYPE(result) == AOP_LIT) {
8424 unsigned lit = (unsigned)operandLitValue(result);
8430 if (PCOP(AOP(result))->type == PO_LITERAL) {
8431 int addrs = PCOL(AOP(result))->lit;
8437 emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8438 if(AOP_SIZE(result) > 1) {
8439 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8447 setup_fsr (operand *ptr)
8450 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8452 /* also setup-up IRP */
8456 /*-----------------------------------------------------------------*/
8457 /* emitPtrByteGet - emits code to get a byte into WREG from an */
8458 /* arbitrary pointer (__code, __data, generic) */
8459 /*-----------------------------------------------------------------*/
8461 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8468 if (!alreadyAddressed) setup_fsr (src);
8469 emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8473 assert( AOP_SIZE(src) == 2 );
8475 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8477 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8478 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
8479 call_libraryfunc ("__gptrget1");
8483 assert( AOP_SIZE(src) == 3 );
8485 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8487 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8489 call_libraryfunc ("__gptrget1");
8493 assert( !"unhandled pointer type" );
8498 /*-----------------------------------------------------------------*/
8499 /* emitPtrByteSet - emits code to set a byte from src through a */
8500 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR). */
8501 /*-----------------------------------------------------------------*/
8503 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8510 if (!alreadyAddressed) setup_fsr (dst);
8511 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8515 assert( !"trying to assign to __code pointer" );
8519 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8521 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8523 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8525 call_libraryfunc ("__gptrput1");
8529 assert( !"unhandled pointer type" );
8534 /*-----------------------------------------------------------------*/
8535 /* genUnpackBits - generates code for unpacking bits */
8536 /*-----------------------------------------------------------------*/
8537 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8539 int rsize; /* result size */
8540 sym_link *etype; /* bitfield type information */
8541 int blen; /* bitfield length */
8542 int bstr; /* bitfield starting bit within byte */
8545 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8546 etype = getSpec(operandType(result));
8547 rsize = getSize (operandType (result));
8548 blen = SPEC_BLEN (etype);
8549 bstr = SPEC_BSTR (etype);
8551 /* single bit field case */
8553 if (ifx) { /* that is for an if statement */
8556 resolveIfx(&rIfx,ifx);
8557 if (ptype == -1) /* direct */
8558 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8560 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8561 emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8562 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8566 assert (!pic14_sameRegs (AOP(result), AOP(left)));
8567 for (i=0; i < AOP_SIZE(result); i++)
8568 emitpcode (POC_CLRF, popGet (AOP(result), i));
8573 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8574 /* adjust result below */
8581 emitPtrByteGet (left, ptype, FALSE);
8582 emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8584 /* adjust result below */
8588 assert( !"unhandled pointer type" );
8591 /* move sign-/zero extended bit to result */
8592 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8593 emitpcode (POC_INCF, popGet (AOP(result), 0));
8595 emitpcode (POC_DECF, popGet (AOP(result), 0));
8597 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8601 else if (blen <= 8 && ((blen + bstr) <= 8))
8606 for (i=0; i < AOP_SIZE(result); i++)
8607 emitpcode (POC_CLRF, popGet (AOP(result), i));
8612 mov2w(AOP(left), 0);
8619 emitPtrByteGet (left, ptype, FALSE);
8623 assert( !"unhandled pointer type" );
8627 emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8628 movwf(AOP(result), 0);
8629 AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8631 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8633 /* signed bitfield */
8634 assert (bstr + blen > 0);
8635 emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8636 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8637 emitpcode(POC_IORWF, popGet(AOP(result),0));
8639 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8643 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8647 /*-----------------------------------------------------------------*/
8648 /* genDataPointerGet - generates code when ptr offset is known */
8649 /*-----------------------------------------------------------------*/
8650 static void genDataPointerGet (operand *left,
8654 int size , offset = 0;
8657 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8660 /* optimization - most of the time, left and result are the same
8661 * address, but different types. for the pic code, we could omit
8664 aopOp(result,ic,TRUE);
8666 if (pic14_sameRegs (AOP(left), AOP(result)))
8669 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8671 //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8673 size = AOP_SIZE(result);
8674 if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8678 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8679 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8683 freeAsmop(left,NULL,ic,TRUE);
8684 freeAsmop(result,NULL,ic,TRUE);
8688 /*-----------------------------------------------------------------*/
8689 /* genNearPointerGet - pic14_emitcode for near pointer fetch */
8690 /*-----------------------------------------------------------------*/
8691 static void genNearPointerGet (operand *left,
8696 sym_link *ltype = operandType(left);
8697 sym_link *rtype = operandType(result);
8698 sym_link *retype= getSpec(rtype); /* bitfield type information */
8702 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8705 aopOp(left,ic,FALSE);
8707 /* if left is rematerialisable and
8708 result is not bit variable type and
8709 the left is pointer to data space i.e
8710 lower 128 bytes of space */
8711 if (AOP_TYPE(left) == AOP_PCODE && //AOP_TYPE(left) == AOP_IMMD &&
8712 !IS_BITVAR(retype) &&
8713 PIC_IS_DATA_PTR(ltype)) {
8714 genDataPointerGet (left,result,ic);
8718 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8719 aopOp (result,ic,FALSE);
8721 /* Check if can access directly instead of via a pointer */
8722 if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8723 && AOP_SIZE(result) == 1)
8728 if (IS_BITFIELD(getSpec(operandType(result))))
8730 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8734 /* If the pointer value is not in a the FSR then need to put it in */
8735 /* Must set/reset IRP bit for use with FSR. */
8740 /* if bitfield then unpack the bits */
8742 /* we have can just get the values */
8743 int size = AOP_SIZE(result);
8746 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8750 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8752 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8753 if (AOP_TYPE(result) == AOP_LIT) {
8754 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8756 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8758 if (size && !direct)
8759 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8764 /* now some housekeeping stuff */
8766 /* we had to allocate for this iCode */
8767 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8768 freeAsmop(NULL,aop,ic,TRUE);
8770 /* we did not allocate which means left
8771 already in a pointer register, then
8772 if size > 0 && this could be used again
8773 we have to point it back to where it
8775 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8776 if (AOP_SIZE(result) > 1 &&
8777 !OP_SYMBOL(left)->remat &&
8778 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8780 int size = AOP_SIZE(result) - 1;
8782 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8788 freeAsmop(left,NULL,ic,TRUE);
8789 freeAsmop(result,NULL,ic,TRUE);
8794 /*-----------------------------------------------------------------*/
8795 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch */
8796 /*-----------------------------------------------------------------*/
8797 static void genPagedPointerGet (operand *left,
8804 sym_link *rtype, *retype;
8807 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8809 rtype = operandType(result);
8810 retype= getSpec(rtype);
8812 aopOp(left,ic,FALSE);
8814 /* if the value is already in a pointer register
8815 then don't need anything more */
8816 if (!AOP_INPREG(AOP(left))) {
8817 /* otherwise get a free pointer register */
8819 preg = getFreePtr(ic,&aop,FALSE);
8820 pic14_emitcode("mov","%s,%s",
8822 aopGet(AOP(left),0,FALSE,TRUE));
8823 rname = preg->name ;
8825 rname = aopGet(AOP(left),0,FALSE,FALSE);
8827 freeAsmop(left,NULL,ic,TRUE);
8828 aopOp (result,ic,FALSE);
8830 /* if bitfield then unpack the bits */
8831 if (IS_BITFIELD(retype))
8832 genUnpackBits (result,left,rname,PPOINTER,0);
8834 /* we have can just get the values */
8835 int size = AOP_SIZE(result);
8840 pic14_emitcode("movx","a,@%s",rname);
8841 aopPut(AOP(result),"a",offset);
8846 pic14_emitcode("inc","%s",rname);
8850 /* now some housekeeping stuff */
8852 /* we had to allocate for this iCode */
8853 freeAsmop(NULL,aop,ic,TRUE);
8855 /* we did not allocate which means left
8856 already in a pointer register, then
8857 if size > 0 && this could be used again
8858 we have to point it back to where it
8860 if (AOP_SIZE(result) > 1 &&
8861 !OP_SYMBOL(left)->remat &&
8862 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8864 int size = AOP_SIZE(result) - 1;
8866 pic14_emitcode("dec","%s",rname);
8871 freeAsmop(result,NULL,ic,TRUE);
8876 /*-----------------------------------------------------------------*/
8877 /* genFarPointerGet - gget value from far space */
8878 /*-----------------------------------------------------------------*/
8879 static void genFarPointerGet (operand *left,
8880 operand *result, iCode *ic)
8883 sym_link *retype = getSpec(operandType(result));
8886 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8888 aopOp(left,ic,FALSE);
8890 /* if the operand is already in dptr
8891 then we do nothing else we move the value to dptr */
8892 if (AOP_TYPE(left) != AOP_STR) {
8893 /* if this is remateriazable */
8894 if (AOP_TYPE(left) == AOP_IMMD)
8895 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8896 else { /* we need to get it byte by byte */
8897 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8898 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8899 if (options.model == MODEL_FLAT24)
8901 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8905 /* so dptr know contains the address */
8906 freeAsmop(left,NULL,ic,TRUE);
8907 aopOp(result,ic,FALSE);
8909 /* if bit then unpack */
8910 if (IS_BITFIELD(retype))
8911 genUnpackBits(result,left,"dptr",FPOINTER,0);
8913 size = AOP_SIZE(result);
8917 pic14_emitcode("movx","a,@dptr");
8918 aopPut(AOP(result),"a",offset++);
8920 pic14_emitcode("inc","dptr");
8924 freeAsmop(result,NULL,ic,TRUE);
8929 /*-----------------------------------------------------------------*/
8930 /* genCodePointerGet - get value from code space */
8931 /*-----------------------------------------------------------------*/
8932 static void genCodePointerGet (operand *left,
8933 operand *result, iCode *ic)
8936 sym_link *retype = getSpec(operandType(result));
8938 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8940 aopOp(left,ic,FALSE);
8942 /* if the operand is already in dptr
8943 then we do nothing else we move the value to dptr */
8944 if (AOP_TYPE(left) != AOP_STR) {
8945 /* if this is remateriazable */
8946 if (AOP_TYPE(left) == AOP_IMMD)
8947 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8948 else { /* we need to get it byte by byte */
8949 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8950 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8951 if (options.model == MODEL_FLAT24)
8953 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8957 /* so dptr know contains the address */
8958 freeAsmop(left,NULL,ic,TRUE);
8959 aopOp(result,ic,FALSE);
8961 /* if bit then unpack */
8962 if (IS_BITFIELD(retype))
8963 genUnpackBits(result,left,"dptr",CPOINTER,0);
8965 size = AOP_SIZE(result);
8969 pic14_emitcode("clr","a");
8970 pic14_emitcode("movc","a,@a+dptr");
8971 aopPut(AOP(result),"a",offset++);
8973 pic14_emitcode("inc","dptr");
8977 freeAsmop(result,NULL,ic,TRUE);
8980 /*-----------------------------------------------------------------*/
8981 /* genGenPointerGet - gget value from generic pointer space */
8982 /*-----------------------------------------------------------------*/
8983 static void genGenPointerGet (operand *left,
8984 operand *result, iCode *ic)
8987 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8988 aopOp(left,ic,FALSE);
8989 aopOp(result,ic,FALSE);
8992 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8994 if (IS_BITFIELD(getSpec(operandType(result))))
8996 genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
9001 /* emit call to __gptrget */
9002 char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
9003 int size = AOP_SIZE(result);
9006 assert (size > 0 && size <= 4);
9008 /* pass arguments */
9009 assert (AOP_SIZE(left) == 3);
9010 mov2w(AOP(left), 0);
9011 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9012 mov2w(AOP(left), 1);
9013 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9014 mov2w(AOP(left), 2);
9015 call_libraryfunc (func[size]);
9018 movwf (AOP(result), --size);
9020 emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
9021 movwf (AOP(result), size);
9025 freeAsmop(left,NULL,ic,TRUE);
9026 freeAsmop(result,NULL,ic,TRUE);
9030 /*-----------------------------------------------------------------*/
9031 /* genConstPointerGet - get value from const generic pointer space */
9032 /*-----------------------------------------------------------------*/
9033 static void genConstPointerGet (operand *left,
9034 operand *result, iCode *ic)
9036 //sym_link *retype = getSpec(operandType(result));
9038 symbol *albl, *blbl;//, *clbl;
9045 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9046 aopOp(left,ic,FALSE);
9047 aopOp(result,ic,FALSE);
9049 size = AOP_SIZE(result);
9051 DEBUGpic14_AopType(__LINE__,left,NULL,result);
9053 DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
9055 lit = op_isLitLike (left);
9056 poc = lit ? POC_MOVLW : POC_MOVFW;
9058 if (IS_BITFIELD(getSpec(operandType(result))))
9060 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
9065 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
9066 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
9067 assert (size > 0 && size <= 4);
9070 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9072 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9073 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
9074 call_libraryfunc (func[size]);
9076 movwf(AOP(result),size-1);
9077 for (i = 1; i < size; i++)
9079 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
9080 movwf(AOP(result),size - 1 - i);
9085 freeAsmop(left,NULL,ic,TRUE);
9086 freeAsmop(result,NULL,ic,TRUE);
9089 /*-----------------------------------------------------------------*/
9090 /* genPointerGet - generate code for pointer get */
9091 /*-----------------------------------------------------------------*/
9092 static void genPointerGet (iCode *ic)
9094 operand *left, *result ;
9095 sym_link *type, *etype;
9099 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9102 result = IC_RESULT(ic) ;
9104 /* depending on the type of pointer we need to
9105 move it to the correct pointer register */
9106 type = operandType(left);
9107 etype = getSpec(type);
9109 if (IS_PTR_CONST(type))
9110 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9112 /* if left is of type of pointer then it is simple */
9113 if (IS_PTR(type) && !IS_FUNC(type->next))
9114 p_type = DCL_TYPE(type);
9116 /* we have to go by the storage class */
9117 p_type = PTR_TYPE(SPEC_OCLS(etype));
9119 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9121 if (SPEC_OCLS(etype)->codesp ) {
9122 DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9123 //p_type = CPOINTER ;
9126 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9127 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9128 /*p_type = FPOINTER ;*/
9130 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9131 DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9132 /* p_type = PPOINTER; */
9134 if (SPEC_OCLS(etype) == idata )
9135 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9136 /* p_type = IPOINTER; */
9138 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9139 /* p_type = POINTER ; */
9142 /* now that we have the pointer type we assign
9143 the pointer values */
9149 genNearPointerGet (left,result,ic);
9153 genPagedPointerGet(left,result,ic);
9157 genFarPointerGet (left,result,ic);
9161 genConstPointerGet (left,result,ic);
9165 genGenPointerGet (left,result,ic);
9168 assert ( !"unhandled pointer type" );
9174 /*-----------------------------------------------------------------*/
9175 /* genPackBits - generates code for packed bit storage */
9176 /*-----------------------------------------------------------------*/
9177 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9179 int blen; /* bitfield length */
9180 int bstr; /* bitfield starting bit within byte */
9181 int litval; /* source literal value (if AOP_LIT) */
9182 unsigned char mask; /* bitmask within current byte */
9185 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9187 blen = SPEC_BLEN (etype);
9188 bstr = SPEC_BSTR (etype);
9190 /* If the bitfield length is less than a byte and does not cross byte boundaries */
9191 if ((blen <= 8) && ((bstr + blen) <= 8))
9193 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9194 (unsigned char) (0xFF >> (8 - bstr)));
9196 if (AOP_TYPE (right) == AOP_LIT)
9198 /* Case with a bitfield length <8 and literal source */
9199 int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9206 if (AOP(result)->type == AOP_PCODE)
9207 pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9209 pcop = popGet(AOP(result),0);
9210 emitpcode(lit?POC_BSF:POC_BCF,pcop);
9216 emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9220 assert( !"trying to assign to bitfield via pointer to __code space" );
9224 emitPtrByteGet(result, p_type, FALSE);
9226 emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9228 emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9230 emitPtrByteSet(result, p_type, TRUE);
9234 assert( !"unhandled pointer type" );
9236 } // switch (p_type)
9239 litval = lit << bstr;
9240 litval &= (~mask) & 0x00ff;
9245 mov2w (AOP(result), 0);
9246 if ((litval|mask) != 0x00ff)
9247 emitpcode(POC_ANDLW, popGetLit (mask));
9249 emitpcode(POC_IORLW, popGetLit (litval));
9250 movwf (AOP(result), 0);
9256 emitPtrByteGet(result, p_type, FALSE);
9257 if ((litval|mask) != 0x00ff)
9258 emitpcode(POC_ANDLW, popGetLit (mask));
9260 emitpcode(POC_IORLW, popGetLit (litval));
9261 emitPtrByteSet(result, p_type, TRUE);
9265 assert( !"trying to assign to bitfield via pointer to __code space" );
9269 assert( !"unhandled pointer type" );
9276 /* right is no literal */
9281 /* Note more efficient code, of pre clearing bit then only setting it if required,
9282 * can only be done if it is known that the result is not a SFR */
9283 emitpcode(POC_RRFW,popGet(AOP(right),0));
9285 emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9287 emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9293 emitPtrByteGet (result, p_type, FALSE);
9294 emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9295 emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9296 emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9297 emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9298 emitPtrByteSet (result, p_type, TRUE);
9302 assert( !"trying to assign to bitfield via pointer to __code space" );
9306 assert( !"unhandled pointer type" );
9311 /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9312 pCodeOp *temp = popGetTempReg ();
9314 mov2w (AOP(right), 0);
9316 emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9318 emitpcode(POC_MOVWF, temp);
9320 AccLsh (temp, bstr);
9326 mov2w (AOP(result), 0);
9327 emitpcode(POC_ANDLW, popGetLit (mask));
9328 emitpcode(POC_IORFW, temp);
9329 movwf (AOP(result), 0);
9335 emitPtrByteGet (result, p_type, FALSE);
9336 emitpcode(POC_ANDLW, popGetLit (mask));
9337 emitpcode(POC_IORFW, temp);
9338 emitPtrByteSet (result, p_type, TRUE);
9342 assert( !"trying to assign to bitfield via pointer to __code space" );
9346 assert( !"unhandled pointer type" );
9350 popReleaseTempReg (temp);
9352 } // if (AOP(right)->type != AOP_LIT)
9354 } // if (blen <= 8 && ((blen + bstr) <= 8))
9356 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9360 bitpatternFromVal (value *val)
9367 assert (sizeof (float) == sizeof (long));
9369 //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));
9371 switch (SPEC_NOUN(val->type))
9375 return (unsigned long)floatFromVal (val);
9379 float_long.d = floatFromVal (val);
9380 return float_long.l;
9383 assert( !"unhandled value type" );
9387 float_long.d = floatFromVal (val);
9388 return float_long.l;
9391 /*-----------------------------------------------------------------*/
9392 /* genDataPointerSet - remat pointer to data space */
9393 /*-----------------------------------------------------------------*/
9394 static void genDataPointerSet(operand *right,
9398 int size, offset = 0 ;
9402 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9403 aopOp(right,ic,FALSE);
9404 aopOp(result,ic,FALSE);
9406 assert (IS_SYMOP(result));
9407 assert (IS_PTR(OP_SYM_TYPE(result)));
9409 size = AOP_SIZE(right);
9410 ressize = getSize(OP_SYM_ETYPE(result));
9411 if (size > ressize) size = ressize;
9412 //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9414 //assert( !"what's going on here?" );
9417 if ( AOP_TYPE(result) == AOP_PCODE) {
9418 fprintf(stderr,"genDataPointerSet %s, %d\n",
9419 AOP(result)->aopu.pcop->name,
9420 PCOI(AOP(result)->aopu.pcop)->offset);
9424 // tsd, was l+1 - the underline `_' prefix was being stripped
9426 emitpComment ("%s:%u: size=%d/%d, offset=%i", __FILE__,__LINE__, size, ressize, offset);
9428 if (AOP_TYPE(right) == AOP_LIT) {
9429 /* XXX: might be float... */
9430 unsigned int lit = bitpatternFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9431 lit = lit >> (8*offset);
9432 //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9434 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9435 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9437 emitpcode(POC_CLRF, popGet(AOP(result),offset));
9440 //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9441 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9442 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9448 freeAsmop(right,NULL,ic,TRUE);
9449 freeAsmop(result,NULL,ic,TRUE);
9452 /*-----------------------------------------------------------------*/
9453 /* genNearPointerSet - pic14_emitcode for near pointer put */
9454 /*-----------------------------------------------------------------*/
9455 static void genNearPointerSet (operand *right,
9460 sym_link *ptype = operandType(result);
9461 sym_link *retype = getSpec(operandType(right));
9462 sym_link *letype = getSpec(ptype);
9467 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9468 aopOp(result,ic,FALSE);
9471 /* if the result is rematerializable &
9472 in data space & not a bit variable */
9473 //if (AOP_TYPE(result) == AOP_IMMD &&
9474 if (AOP_TYPE(result) == AOP_PCODE &&
9475 PIC_IS_DATA_PTR(ptype) &&
9476 !IS_BITVAR (retype) &&
9477 !IS_BITVAR (letype)) {
9478 genDataPointerSet (right,result,ic);
9479 freeAsmop(result,NULL,ic,TRUE);
9484 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9485 aopOp(right,ic,FALSE);
9486 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9488 /* Check if can access directly instead of via a pointer */
9489 if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9493 if (IS_BITFIELD (letype))
9495 genPackBits (letype, result, right, direct?-1:POINTER);
9499 /* If the pointer value is not in a the FSR then need to put it in */
9500 /* Must set/reset IRP bit for use with FSR. */
9501 /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9506 /* we have can just get the values */
9507 int size = AOP_SIZE(right);
9510 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9512 char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9514 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9516 if (AOP_TYPE(right) == AOP_LIT) {
9517 emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9519 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9522 emitpcode(POC_MOVWF,popGet(AOP(result),0));
9524 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9526 if (size && !direct)
9527 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9532 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9533 /* now some housekeeping stuff */
9535 /* we had to allocate for this iCode */
9536 freeAsmop(NULL,aop,ic,TRUE);
9538 /* we did not allocate which means left
9539 already in a pointer register, then
9540 if size > 0 && this could be used again
9541 we have to point it back to where it
9543 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9544 if (AOP_SIZE(right) > 1 &&
9545 !OP_SYMBOL(result)->remat &&
9546 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9548 int size = AOP_SIZE(right) - 1;
9550 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9554 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9557 freeAsmop(right,NULL,ic,TRUE);
9558 freeAsmop(result,NULL,ic,TRUE);
9562 /*-----------------------------------------------------------------*/
9563 /* genPagedPointerSet - pic14_emitcode for Paged pointer put */
9564 /*-----------------------------------------------------------------*/
9565 static void genPagedPointerSet (operand *right,
9575 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9577 retype= getSpec(operandType(right));
9579 aopOp(result,ic,FALSE);
9581 /* if the value is already in a pointer register
9582 then don't need anything more */
9583 if (!AOP_INPREG(AOP(result))) {
9584 /* otherwise get a free pointer register */
9586 preg = getFreePtr(ic,&aop,FALSE);
9587 pic14_emitcode("mov","%s,%s",
9589 aopGet(AOP(result),0,FALSE,TRUE));
9590 rname = preg->name ;
9592 rname = aopGet(AOP(result),0,FALSE,FALSE);
9594 freeAsmop(result,NULL,ic,TRUE);
9595 aopOp (right,ic,FALSE);
9597 /* if bitfield then unpack the bits */
9598 if (IS_BITFIELD(retype))
9599 genPackBits (retype,result,right,rname,PPOINTER);
9601 /* we have can just get the values */
9602 int size = AOP_SIZE(right);
9606 l = aopGet(AOP(right),offset,FALSE,TRUE);
9609 pic14_emitcode("movx","@%s,a",rname);
9612 pic14_emitcode("inc","%s",rname);
9618 /* now some housekeeping stuff */
9620 /* we had to allocate for this iCode */
9621 freeAsmop(NULL,aop,ic,TRUE);
9623 /* we did not allocate which means left
9624 already in a pointer register, then
9625 if size > 0 && this could be used again
9626 we have to point it back to where it
9628 if (AOP_SIZE(right) > 1 &&
9629 !OP_SYMBOL(result)->remat &&
9630 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9632 int size = AOP_SIZE(right) - 1;
9634 pic14_emitcode("dec","%s",rname);
9639 freeAsmop(right,NULL,ic,TRUE);
9644 /*-----------------------------------------------------------------*/
9645 /* genFarPointerSet - set value from far space */
9646 /*-----------------------------------------------------------------*/
9647 static void genFarPointerSet (operand *right,
9648 operand *result, iCode *ic)
9651 sym_link *retype = getSpec(operandType(right));
9654 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9655 aopOp(result,ic,FALSE);
9657 /* if the operand is already in dptr
9658 then we do nothing else we move the value to dptr */
9659 if (AOP_TYPE(result) != AOP_STR) {
9660 /* if this is remateriazable */
9661 if (AOP_TYPE(result) == AOP_IMMD)
9662 pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9663 else { /* we need to get it byte by byte */
9664 pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9665 pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9666 if (options.model == MODEL_FLAT24)
9668 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9672 /* so dptr know contains the address */
9673 freeAsmop(result,NULL,ic,TRUE);
9674 aopOp(right,ic,FALSE);
9676 /* if bit then unpack */
9677 if (IS_BITFIELD(retype))
9678 genPackBits(retype,result,right,"dptr",FPOINTER);
9680 size = AOP_SIZE(right);
9684 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9686 pic14_emitcode("movx","@dptr,a");
9688 pic14_emitcode("inc","dptr");
9692 freeAsmop(right,NULL,ic,TRUE);
9696 /*-----------------------------------------------------------------*/
9697 /* genGenPointerSet - set value from generic pointer space */
9698 /*-----------------------------------------------------------------*/
9699 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9701 sym_link *retype = getSpec(operandType(result));
9704 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9705 aopOp(right,ic,FALSE);
9706 aopOp(result,ic,FALSE);
9709 DEBUGpic14_AopType(__LINE__,right,NULL,result);
9711 if (IS_BITFIELD(retype))
9713 genPackBits (retype, result, right, GPOINTER);
9718 /* emit call to __gptrput */
9719 char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9720 int size = AOP_SIZE(right);
9723 assert (size == getSize(OP_SYM_ETYPE(result)));
9724 assert (size > 0 && size <= 4);
9726 /* pass arguments */
9727 /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9733 mov2w_op (right, off);
9734 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9739 assert (AOP_SIZE(result) == 3);
9740 mov2w(AOP(result), 0);
9741 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9742 mov2w(AOP(result), 1);
9743 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9744 mov2w(AOP(result), 2);
9745 call_libraryfunc (func[size]);
9748 freeAsmop(right,NULL,ic,TRUE);
9749 freeAsmop(result,NULL,ic,TRUE);
9752 /*-----------------------------------------------------------------*/
9753 /* genPointerSet - stores the value into a pointer location */
9754 /*-----------------------------------------------------------------*/
9755 static void genPointerSet (iCode *ic)
9757 operand *right, *result ;
9758 sym_link *type, *etype;
9762 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9764 right = IC_RIGHT(ic);
9765 result = IC_RESULT(ic) ;
9767 /* depending on the type of pointer we need to
9768 move it to the correct pointer register */
9769 type = operandType(result);
9770 etype = getSpec(type);
9771 /* if left is of type of pointer then it is simple */
9772 if (IS_PTR(type) && !IS_FUNC(type->next)) {
9773 p_type = DCL_TYPE(type);
9776 /* we have to go by the storage class */
9777 p_type = PTR_TYPE(SPEC_OCLS(etype));
9779 /* if (SPEC_OCLS(etype)->codesp ) { */
9780 /* p_type = CPOINTER ; */
9783 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9784 /* p_type = FPOINTER ; */
9786 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9787 /* p_type = PPOINTER ; */
9789 /* if (SPEC_OCLS(etype) == idata ) */
9790 /* p_type = IPOINTER ; */
9792 /* p_type = POINTER ; */
9795 /* now that we have the pointer type we assign
9796 the pointer values */
9802 genNearPointerSet (right,result,ic);
9806 genPagedPointerSet (right,result,ic);
9810 genFarPointerSet (right,result,ic);
9814 genGenPointerSet (right,result,ic);
9818 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9819 "genPointerSet: illegal pointer type");
9823 /*-----------------------------------------------------------------*/
9824 /* genIfx - generate code for Ifx statement */
9825 /*-----------------------------------------------------------------*/
9826 static void genIfx (iCode *ic, iCode *popIc)
9828 operand *cond = IC_COND(ic);
9832 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9834 aopOp(cond,ic,FALSE);
9836 /* get the value into acc */
9837 if (AOP_TYPE(cond) != AOP_CRY)
9838 pic14_toBoolean(cond);
9842 /* if there was something to be popped then do it */
9848 /* This assumes that CARRY is set iff cond is true */
9851 assert (!IC_FALSE(ic));
9852 emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
9854 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9856 assert (IC_FALSE(ic));
9857 emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
9859 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9863 static int hasWarned = 0;
9866 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
9873 /* now Z is set iff !cond */
9876 assert (!IC_FALSE(ic));
9878 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9881 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9887 /* the result is now in the accumulator */
9888 freeAsmop(cond,NULL,ic,TRUE);
9891 /*-----------------------------------------------------------------*/
9892 /* genAddrOf - generates code for address of */
9893 /*-----------------------------------------------------------------*/
9894 static void genAddrOf (iCode *ic)
9896 operand *right, *result, *left;
9900 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9903 //aopOp(IC_RESULT(ic),ic,FALSE);
9905 aopOp((left=IC_LEFT(ic)),ic,FALSE);
9906 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9907 aopOp((result=IC_RESULT(ic)),ic,TRUE);
9909 DEBUGpic14_AopType(__LINE__,left,right,result);
9910 assert (IS_SYMOP (left));
9912 /* sanity check: generic pointers to code space are not yet supported,
9913 * pionters to codespace must not be assigned addresses of __data values. */
9915 fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9916 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)));
9917 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)));
9918 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)));
9919 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)));
9922 if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9923 fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9924 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9925 OP_SYMBOL(left)->name);
9926 } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9927 fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9928 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9929 OP_SYMBOL(left)->name);
9932 size = AOP_SIZE(IC_RESULT(ic));
9933 if (IS_GENPTR(OP_SYM_TYPE(result))) {
9935 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9940 /* fixing bug #863624, reported from (errolv) */
9941 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9942 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9945 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9946 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9951 if (IS_GENPTR(OP_SYM_TYPE(result)))
9953 /* provide correct tag */
9954 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9955 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9956 movwf (AOP(result), 2);
9959 freeAsmop(left,NULL,ic,FALSE);
9960 freeAsmop(result,NULL,ic,TRUE);
9965 /*-----------------------------------------------------------------*/
9966 /* genFarFarAssign - assignment when both are in far space */
9967 /*-----------------------------------------------------------------*/
9968 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9970 int size = AOP_SIZE(right);
9973 /* first push the right side on to the stack */
9975 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9977 pic14_emitcode ("push","acc");
9980 freeAsmop(right,NULL,ic,FALSE);
9981 /* now assign DPTR to result */
9982 aopOp(result,ic,FALSE);
9983 size = AOP_SIZE(result);
9985 pic14_emitcode ("pop","acc");
9986 aopPut(AOP(result),"a",--offset);
9988 freeAsmop(result,NULL,ic,FALSE);
9993 /*-----------------------------------------------------------------*/
9994 /* genAssign - generate code for assignment */
9995 /*-----------------------------------------------------------------*/
9996 static void genAssign (iCode *ic)
9998 operand *result, *right;
9999 int size, offset,know_W;
10000 unsigned long lit = 0L;
10002 result = IC_RESULT(ic);
10003 right = IC_RIGHT(ic) ;
10006 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10008 /* if they are the same */
10009 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10012 aopOp(right,ic,FALSE);
10013 aopOp(result,ic,TRUE);
10015 DEBUGpic14_AopType(__LINE__,NULL,right,result);
10017 /* if they are the same registers */
10018 if (pic14_sameRegs(AOP(right),AOP(result)))
10021 /* special case: assign from __code */
10022 if (!IS_ITEMP(right) /* --> iTemps never reside in __code */
10023 && IS_SYMOP (right) /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
10024 && !IS_FUNC(OP_SYM_TYPE(right)) /* --> we would want its address instead of the first instruction */
10025 && !IS_CODEPTR(OP_SYM_TYPE(right)) /* --> get symbols address instread */
10026 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
10028 emitpComment ("genAssign from CODESPACE");
10029 genConstPointerGet (right, result, ic);
10033 /* just for symmetry reasons... */
10034 if (!IS_ITEMP(result)
10035 && IS_SYMOP (result)
10036 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
10038 assert ( !"cannot write to CODESPACE" );
10041 /* if the result is a bit */
10042 if (AOP_TYPE(result) == AOP_CRY) {
10044 /* if the right size is a literal then
10045 we know what the value is */
10046 if (AOP_TYPE(right) == AOP_LIT) {
10048 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10049 popGet(AOP(result),0));
10051 if (((int) operandLitValue(right)))
10052 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10053 AOP(result)->aopu.aop_dir,
10054 AOP(result)->aopu.aop_dir);
10056 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10057 AOP(result)->aopu.aop_dir,
10058 AOP(result)->aopu.aop_dir);
10062 /* the right is also a bit variable */
10063 if (AOP_TYPE(right) == AOP_CRY) {
10064 emitpcode(POC_BCF, popGet(AOP(result),0));
10065 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10066 emitpcode(POC_BSF, popGet(AOP(result),0));
10068 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10069 AOP(result)->aopu.aop_dir,
10070 AOP(result)->aopu.aop_dir);
10071 pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
10072 AOP(right)->aopu.aop_dir,
10073 AOP(right)->aopu.aop_dir);
10074 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10075 AOP(result)->aopu.aop_dir,
10076 AOP(result)->aopu.aop_dir);
10080 /* we need to or */
10081 emitpcode(POC_BCF, popGet(AOP(result),0));
10082 pic14_toBoolean(right);
10084 emitpcode(POC_BSF, popGet(AOP(result),0));
10085 //aopPut(AOP(result),"a",0);
10089 /* bit variables done */
10091 size = AOP_SIZE(result);
10093 if(AOP_TYPE(right) == AOP_LIT)
10094 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10096 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
10097 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10098 if(aopIdx(AOP(result),0) == 4) {
10099 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10100 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10101 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10104 DEBUGpic14_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
10109 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10110 if(AOP_TYPE(right) == AOP_LIT) {
10112 if(know_W != (int)(lit&0xff))
10113 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10115 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10117 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10121 } else if (AOP_TYPE(right) == AOP_CRY) {
10122 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10124 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10125 emitpcode(POC_INCF, popGet(AOP(result),0));
10128 mov2w_op (right, offset);
10129 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10137 freeAsmop (right,NULL,ic,FALSE);
10138 freeAsmop (result,NULL,ic,TRUE);
10141 /*-----------------------------------------------------------------*/
10142 /* genJumpTab - genrates code for jump table */
10143 /*-----------------------------------------------------------------*/
10144 static void genJumpTab (iCode *ic)
10150 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10152 aopOp(IC_JTCOND(ic),ic,FALSE);
10153 /* get the condition into accumulator */
10154 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10156 /* multiply by three */
10157 pic14_emitcode("add","a,acc");
10158 pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10160 jtab = newiTempLabel(NULL);
10161 pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10162 pic14_emitcode("jmp","@a+dptr");
10163 pic14_emitcode("","%05d_DS_:",jtab->key+100);
10165 emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10166 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10167 emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10168 emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10170 emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10171 emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10172 emitpLabel(jtab->key);
10174 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10176 /* now generate the jump labels */
10177 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10178 jtab = setNextItem(IC_JTLABELS(ic))) {
10179 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10180 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10186 /*-----------------------------------------------------------------*/
10187 /* genMixedOperation - gen code for operators between mixed types */
10188 /*-----------------------------------------------------------------*/
10190 TSD - Written for the PIC port - but this unfortunately is buggy.
10191 This routine is good in that it is able to efficiently promote
10192 types to different (larger) sizes. Unfortunately, the temporary
10193 variables that are optimized out by this routine are sometimes
10194 used in other places. So until I know how to really parse the
10195 iCode tree, I'm going to not be using this routine :(.
10197 static int genMixedOperation (iCode *ic)
10201 operand *result = IC_RESULT(ic);
10202 sym_link *ctype = operandType(IC_LEFT(ic));
10203 operand *right = IC_RIGHT(ic);
10209 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10211 pic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10217 nextright = IC_RIGHT(nextic);
10218 nextleft = IC_LEFT(nextic);
10219 nextresult = IC_RESULT(nextic);
10221 aopOp(right,ic,FALSE);
10222 aopOp(result,ic,FALSE);
10223 aopOp(nextright, nextic, FALSE);
10224 aopOp(nextleft, nextic, FALSE);
10225 aopOp(nextresult, nextic, FALSE);
10227 if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10229 operand *t = right;
10233 pic14_emitcode(";remove right +","");
10235 } else if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10237 operand *t = right;
10241 pic14_emitcode(";remove left +","");
10245 big = AOP_SIZE(nextleft);
10246 small = AOP_SIZE(nextright);
10248 switch(nextic->op) {
10251 pic14_emitcode(";optimize a +","");
10252 /* if unsigned or not an integral type */
10253 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10254 pic14_emitcode(";add a bit to something","");
10257 pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10259 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10260 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10261 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10263 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10271 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10272 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10273 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10276 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10278 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10279 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10280 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10281 pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10282 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10285 pic14_emitcode("rlf","known_zero,w");
10292 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10293 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10294 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10296 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10306 freeAsmop(right,NULL,ic,TRUE);
10307 freeAsmop(result,NULL,ic,TRUE);
10308 freeAsmop(nextright,NULL,ic,TRUE);
10309 freeAsmop(nextleft,NULL,ic,TRUE);
10311 nextic->generated = 1;
10318 /*-----------------------------------------------------------------*/
10319 /* genCast - gen code for casting */
10320 /*-----------------------------------------------------------------*/
10321 static void genCast (iCode *ic)
10323 operand *result = IC_RESULT(ic);
10324 sym_link *restype = operandType(result);
10325 sym_link *rtype = operandType(IC_RIGHT(ic));
10326 operand *right = IC_RIGHT(ic);
10330 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10331 /* if they are equivalent then do nothing */
10332 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10335 aopOp(right,ic,FALSE) ;
10336 aopOp(result,ic,FALSE);
10338 DEBUGpic14_AopType(__LINE__,NULL,right,result);
10340 /* if the result is a bit */
10341 if (AOP_TYPE(result) == AOP_CRY) {
10342 assert(!"assigning to bit variables is not supported");
10345 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10347 size = AOP_SIZE(result);
10349 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10351 emitpcode(POC_CLRF, popGet(AOP(result),0));
10352 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10353 emitpcode(POC_INCF, popGet(AOP(result),0));
10356 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
10361 if (IS_PTR(restype))
10363 operand *result = IC_RESULT(ic);
10364 //operand *left = IC_LEFT(ic);
10365 operand *right = IC_RIGHT(ic);
10368 /* copy common part */
10369 int max, size = AOP_SIZE(result);
10370 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10371 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10373 /* warn if we discard generic opinter tag */
10374 if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10376 //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10382 mov2w_op (right, size);
10383 movwf (AOP(result), size);
10386 /* upcast into generic pointer type? */
10387 if (IS_GENPTR(restype)
10388 && (size < AOP_SIZE(result))
10389 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10391 //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10394 switch (DCL_TYPE(rtype))
10396 case POINTER: /* __data */
10397 case FPOINTER: /* __data */
10398 assert (AOP_SIZE(right) == 2);
10399 tag = GPTRTAG_DATA;
10402 case CPOINTER: /* __code */
10403 assert (AOP_SIZE(right) == 2);
10404 tag = GPTRTAG_CODE;
10407 case GPOINTER: /* unknown destination, __data or __code */
10408 /* assume __data space (address of immediate) */
10409 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10410 if (AOP(right)->code)
10411 tag = GPTRTAG_CODE;
10413 tag = GPTRTAG_DATA;
10417 assert (!"unhandled pointer type");
10420 /* convert other values into pointers to __data space */
10421 tag = GPTRTAG_DATA;
10424 assert (AOP_SIZE(result) == 3);
10426 emitpcode(POC_CLRF, popGet(AOP(result), 2));
10428 emitpcode(POC_MOVLW, popGetLit(tag));
10429 movwf(AOP(result), 2);
10432 addSign(result, max, 0);
10437 /* if they are the same size : or less */
10438 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10440 /* if they are in the same place */
10441 if (pic14_sameRegs(AOP(right),AOP(result)))
10444 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10445 if (IS_PTR_CONST(rtype))
10446 DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10447 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10448 DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10450 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10451 emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10452 emitpcode(POC_MOVWF, popGet(AOP(result),0));
10453 emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10454 emitpcode(POC_MOVWF, popGet(AOP(result),1));
10455 if(AOP_SIZE(result) <2)
10456 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10460 /* if they in different places then copy */
10461 size = AOP_SIZE(result);
10464 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10465 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10467 //aopPut(AOP(result),
10468 // aopGet(AOP(right),offset,FALSE,FALSE),
10477 /* so we now know that the size of destination is greater
10478 than the size of the source.
10479 Now, if the next iCode is an operator then we might be
10480 able to optimize the operation without performing a cast.
10482 if(0 && genMixedOperation(ic)) {
10483 /* XXX: cannot optimize: must copy regs! */
10487 /* we move to result for the size of source */
10488 size = AOP_SIZE(right);
10491 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10492 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10496 addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10499 freeAsmop(right,NULL,ic,TRUE);
10500 freeAsmop(result,NULL,ic,TRUE);
10504 /*-----------------------------------------------------------------*/
10505 /* genDjnz - generate decrement & jump if not zero instrucion */
10506 /*-----------------------------------------------------------------*/
10507 static int genDjnz (iCode *ic, iCode *ifx)
10509 symbol *lbl, *lbl1;
10511 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10516 /* if the if condition has a false label
10517 then we cannot save */
10521 /* if the minus is not of the form
10523 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10524 !IS_OP_LITERAL(IC_RIGHT(ic)))
10527 if (operandLitValue(IC_RIGHT(ic)) != 1)
10530 /* if the size of this greater than one then no
10532 if (getSize(operandType(IC_RESULT(ic))) > 1)
10535 /* otherwise we can save BIG */
10536 lbl = newiTempLabel(NULL);
10537 lbl1= newiTempLabel(NULL);
10539 aopOp(IC_RESULT(ic),ic,FALSE);
10541 if (IS_AOP_PREG(IC_RESULT(ic))) {
10542 pic14_emitcode("dec","%s",
10543 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10544 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10545 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10549 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10550 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10552 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10553 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10556 /* pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10557 /* pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10558 /* pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10559 /* pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10562 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10563 ifx->generated = 1;
10567 /*-----------------------------------------------------------------*/
10568 /* genReceive - generate code for a receive iCode */
10569 /*-----------------------------------------------------------------*/
10570 static void genReceive (iCode *ic)
10573 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10575 if (isOperandInFarSpace(IC_RESULT(ic)) &&
10576 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10577 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10579 int size = getSize(operandType(IC_RESULT(ic)));
10580 int offset = fReturnSizePic - size;
10582 pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10583 fReturn[fReturnSizePic - offset - 1] : "acc"));
10586 aopOp(IC_RESULT(ic),ic,FALSE);
10587 size = AOP_SIZE(IC_RESULT(ic));
10590 pic14_emitcode ("pop","acc");
10591 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10596 aopOp(IC_RESULT(ic),ic,FALSE);
10598 assignResultValue(IC_RESULT(ic));
10601 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10604 /*-----------------------------------------------------------------*/
10605 /* genDummyRead - generate code for dummy read of volatiles */
10606 /*-----------------------------------------------------------------*/
10608 genDummyRead (iCode * ic)
10611 pic14_emitcode ("; genDummyRead","");
10612 pic14_emitcode ("; not implemented","");
10617 /*-----------------------------------------------------------------*/
10618 /* genpic14Code - generate code for pic14 based controllers */
10619 /*-----------------------------------------------------------------*/
10621 * At this point, ralloc.c has gone through the iCode and attempted
10622 * to optimize in a way suitable for a PIC. Now we've got to generate
10623 * PIC instructions that correspond to the iCode.
10625 * Once the instructions are generated, we'll pass through both the
10626 * peep hole optimizer and the pCode optimizer.
10627 *-----------------------------------------------------------------*/
10629 void genpic14Code (iCode *lic)
10636 lineHead = lineCurr = NULL;
10638 pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10641 /* if debug information required */
10642 if (options.debug && currFunc) {
10644 debugFile->writeFunction (currFunc, lic);
10649 for (ic = lic ; ic ; ic = ic->next ) {
10651 //DEBUGpic14_emitcode(";ic","");
10652 //fprintf (stderr, "in ic loop\n");
10653 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10654 //ic->lineno, printCLine(ic->filename, ic->lineno));
10656 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10658 //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10659 cline = printCLine (ic->filename, ic->lineno);
10660 if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10661 addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10662 //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10665 if (options.iCodeInAsm) {
10666 emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10668 /* if the result is marked as
10669 spilt and rematerializable or code for
10670 this has already been generated then
10672 if (resultRemat(ic) || ic->generated )
10675 /* depending on the operation */
10694 /* IPOP happens only when trying to restore a
10695 spilt live range, if there is an ifx statement
10696 following this pop then the if statement might
10697 be using some of the registers being popped which
10698 would destory the contents of the register so
10699 we need to check for this condition and handle it */
10701 ic->next->op == IFX &&
10702 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10703 genIfx (ic->next,ic);
10721 genEndFunction (ic);
10741 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10758 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
10762 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10769 /* note these two are xlated by algebraic equivalence
10770 during parsing SDCC.y */
10771 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10772 "got '>=' or '<=' shouldn't have come here");
10776 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10788 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10792 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10796 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10820 genRightShift (ic);
10823 case GET_VALUE_AT_ADDRESS:
10828 if (POINTER_SET(ic))
10855 addSet(&_G.sendSet,ic);
10858 case DUMMY_READ_VOLATILE:
10863 fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10870 /* now we are ready to call the
10871 peep hole optimizer */
10872 if (!options.nopeep) {
10873 peepHole (&lineHead);
10875 /* now do the actual printing */
10876 printLine (lineHead,codeOutFile);
10879 DFPRINTF((stderr,"printing pBlock\n\n"));
10880 printpBlock(stdout,pb);
10886 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10887 * (meaning: representing its own address) or not (referencing its contents).
10888 * This can only be decided based on the operand's type. */
10890 aop_isLitLike (asmop *aop)
10893 if (aop->type == AOP_LIT) return 1;
10894 if (aop->type == AOP_IMMD) return 1;
10895 if ((aop->type == AOP_PCODE) &&
10896 ((aop->aopu.pcop->type == PO_LITERAL)))
10898 /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10899 * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10906 op_isLitLike (operand *op)
10909 if (aop_isLitLike (AOP(op))) return 1;
10910 if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10911 if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;