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"
47 /* When changing these, you must also update the assembler template
48 * in device/lib/libsdcc/macros.inc */
49 #define GPTRTAG_DATA 0x00
50 #define GPTRTAG_CODE 0x80
52 /* The PIC port(s) need not differentiate between POINTER and FPOINTER. */
53 #define PIC_IS_DATA_PTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
54 #define PIC_IS_FARPTR(x) (PIC_IS_DATA_PTR(x))
56 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
57 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
58 void genMult8X8_8 (operand *, operand *,operand *);
59 extern void printpBlock(FILE *of, pBlock *pb);
61 static int labelOffset=0;
62 extern int debug_verbose;
63 extern int pic14_hasInterrupt;
64 //static int optimized_for_speed = 0;
66 /* max_key keeps track of the largest label number used in
67 a function. This is then used to adjust the label offset
68 for the next function.
71 static int GpsuedoStkPtr=0;
73 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
74 extern char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
75 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_strdup(s);
1217 aop->coff = offset ;
1218 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1221 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1223 return aop->aopu.aop_str[offset];
1227 pCodeOp *pcop = aop->aopu.pcop;
1228 DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1231 DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
1232 sprintf(s,"(%s+%d)", pcop->name,offset);
1234 DEBUGpic14_emitcode(";","%s",pcop->name);
1235 sprintf(s,"%s", pcop->name);
1238 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1241 rs = Safe_calloc(1,strlen(s)+1);
1247 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1248 "aopget got unsupported aop->type");
1253 /*-----------------------------------------------------------------*/
1254 /* popGetTempReg - create a new temporary pCodeOp */
1255 /*-----------------------------------------------------------------*/
1256 pCodeOp *popGetTempReg(void)
1261 pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1262 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1263 PCOR(pcop)->r->wasUsed=1;
1264 PCOR(pcop)->r->isFree=0;
1270 /*-----------------------------------------------------------------*/
1271 /* popReleaseTempReg - create a new temporary pCodeOp */
1272 /*-----------------------------------------------------------------*/
1273 void popReleaseTempReg(pCodeOp *pcop)
1276 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1277 PCOR(pcop)->r->isFree = 1;
1280 /*-----------------------------------------------------------------*/
1281 /* popGetLabel - create a new pCodeOp of type PO_LABEL */
1282 /*-----------------------------------------------------------------*/
1283 pCodeOp *popGetLabel(unsigned int key)
1286 DEBUGpic14_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1288 if(key>(unsigned int)max_key)
1291 return newpCodeOpLabel(NULL,key+100+labelOffset);
1294 /*-------------------------------------------------------------------*/
1295 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1296 /*-------------------------------------------------------------------*/
1297 pCodeOp *popGetHighLabel(unsigned int key)
1300 pcop = popGetLabel(key);
1301 PCOLAB(pcop)->offset = 1;
1305 /*-----------------------------------------------------------------*/
1306 /* popGetLit - asm operator to pcode operator conversion */
1307 /*-----------------------------------------------------------------*/
1308 pCodeOp *popGetLit(unsigned int lit)
1311 return newpCodeOpLit((unsigned char)lit);
1314 /*-----------------------------------------------------------------*/
1315 /* popGetImmd - asm operator to pcode immediate conversion */
1316 /*-----------------------------------------------------------------*/
1317 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1320 return newpCodeOpImmd(name, offset,index, 0, is_func);
1323 extern set *externs;
1325 /*-----------------------------------------------------------------*/
1326 /* popGetWithString - asm operator to pcode operator conversion */
1327 /*-----------------------------------------------------------------*/
1328 pCodeOp *popGetWithString(char *str, int isExtern)
1334 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1338 pcop = newpCodeOp(str,PO_STR);
1339 PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1344 pCodeOp *popGetExternal (char *str)
1346 pCodeOp *pcop = popGetWithString (str, 1);
1352 for (sym = setFirstItem (externs); !found && sym; sym = setNextItem (externs))
1354 if (!strcmp (str, sym->rname))
1360 sym = newSymbol(str, 0);
1361 strncpy(sym->rname, str, SDCC_NAME_MAX);
1362 addSet (&externs, sym);
1368 /*-----------------------------------------------------------------*/
1369 /* popRegFromString - */
1370 /*-----------------------------------------------------------------*/
1371 pCodeOp *popRegFromString(char *str, int size, int offset)
1374 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1375 pcop->type = PO_DIR;
1377 DEBUGpic14_emitcode(";","%d",__LINE__);
1382 pcop->name = Safe_calloc(1,strlen(str)+1);
1383 strcpy(pcop->name,str);
1385 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1387 PCOR(pcop)->r = dirregWithName(pcop->name);
1388 if(PCOR(pcop)->r == NULL) {
1389 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1390 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1391 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1393 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1395 PCOR(pcop)->instance = offset;
1400 /*-----------------------------------------------------------------*/
1401 /*-----------------------------------------------------------------*/
1402 pCodeOp *popRegFromIdx(int rIdx)
1406 DEBUGpic14_emitcode ("; ***","%s,%d , rIdx=0x%x",
1407 __FUNCTION__,__LINE__,rIdx);
1409 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1411 PCOR(pcop)->rIdx = rIdx;
1412 PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1413 PCOR(pcop)->r->isFree = 0;
1414 PCOR(pcop)->r->wasUsed = 1;
1416 pcop->type = PCOR(pcop)->r->pc_type;
1422 /*-----------------------------------------------------------------*/
1423 /* popGet - asm operator to pcode operator conversion */
1424 /*-----------------------------------------------------------------*/
1425 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1427 //char *s = buffer ;
1432 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1433 /* offset is greater than
1438 /* XXX: still needed for BIT operands (AOP_CRY) */
1439 if (offset > (aop->size - 1) &&
1440 aop->type != AOP_LIT)
1441 return NULL; //zero;
1443 /* depending on type */
1444 switch (aop->type) {
1451 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1455 DEBUGpic14_emitcode(";","%d",__LINE__);
1456 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1459 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1461 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1462 pcop->type = PO_DIR;
1464 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1465 strcpy(pcop->name,aop->aopu.aop_dir);
1466 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1467 if(PCOR(pcop)->r == NULL) {
1468 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1469 PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1470 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1472 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1474 PCOR(pcop)->instance = offset;
1482 assert (offset < aop->size);
1483 rIdx = aop->aopu.aop_reg[offset]->rIdx;
1485 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1486 PCOR(pcop)->rIdx = rIdx;
1487 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1488 PCOR(pcop)->r->wasUsed=1;
1489 PCOR(pcop)->r->isFree=0;
1491 PCOR(pcop)->instance = offset;
1492 pcop->type = PCOR(pcop)->r->pc_type;
1493 //rs = aop->aopu.aop_reg[offset]->name;
1494 DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1499 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1500 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1501 //if(PCOR(pcop)->r == NULL)
1502 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1506 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1509 DEBUGpic14_emitcode(";","%d %s",__LINE__,aop->aopu.aop_str[offset]);
1510 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1512 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1513 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1514 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1515 pcop->type = PCOR(pcop)->r->pc_type;
1516 pcop->name = PCOR(pcop)->r->name;
1523 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1525 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1526 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1527 switch (aop->aopu.pcop->type)
1530 pcop = pCodeOpCopy (aop->aopu.pcop);
1531 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1532 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1533 PCOI(pcop)->index += offset;
1534 //PCOI(pcop)->offset = 0;
1537 pcop = pCodeOpCopy (aop->aopu.pcop);
1538 PCOR(pcop)->instance = offset;
1541 assert ( !"unhandled pCode type" );
1547 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1548 "popGet got unsupported aop->type");
1552 /*-----------------------------------------------------------------*/
1553 /* popGetAddr - access the low/high word of a symbol (immediate) */
1554 /* (for non-PO_IMMEDIATEs this is the same as popGet) */
1555 /*-----------------------------------------------------------------*/
1556 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1558 if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1560 pCodeOp *pcop = aop->aopu.pcop;
1561 assert (offset <= GPTRSIZE);
1563 /* special case: index >= 2 should return GPOINTER-style values */
1566 pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1570 pcop = pCodeOpCopy (pcop);
1571 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1572 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1573 PCOI(pcop)->offset += offset;
1574 PCOI(pcop)->index += index;
1575 //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);
1578 return popGet (aop, offset + index);
1582 /*-----------------------------------------------------------------*/
1583 /* aopPut - puts a string for a aop */
1584 /*-----------------------------------------------------------------*/
1585 void aopPut (asmop *aop, char *s, int offset)
1590 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1592 if (aop->size && offset > ( aop->size - 1)) {
1593 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1594 "aopPut got offset > aop->size");
1598 /* will assign value to value */
1599 /* depending on where it is ofcourse */
1600 switch (aop->type) {
1603 sprintf(d,"(%s + %d)",
1604 aop->aopu.aop_dir,offset);
1605 fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1608 sprintf(d,"%s",aop->aopu.aop_dir);
1611 DEBUGpic14_emitcode(";","%d",__LINE__);
1613 pic14_emitcode("movf","%s,w",s);
1614 pic14_emitcode("movwf","%s",d);
1617 pic14_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
1618 if(offset >= aop->size) {
1619 emitpcode(POC_CLRF,popGet(aop,offset));
1622 emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
1625 emitpcode(POC_MOVWF,popGet(aop,offset));
1631 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1632 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1635 strcmp(s,"r0") == 0 ||
1636 strcmp(s,"r1") == 0 ||
1637 strcmp(s,"r2") == 0 ||
1638 strcmp(s,"r3") == 0 ||
1639 strcmp(s,"r4") == 0 ||
1640 strcmp(s,"r5") == 0 ||
1641 strcmp(s,"r6") == 0 ||
1642 strcmp(s,"r7") == 0 )
1643 pic14_emitcode("mov","%s,%s ; %d",
1644 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1648 if(strcmp(s,"W")==0 )
1649 pic14_emitcode("movf","%s,w ; %d",s,__LINE__);
1651 pic14_emitcode("movwf","%s",
1652 aop->aopu.aop_reg[offset]->name);
1654 if(strcmp(s,zero)==0) {
1655 emitpcode(POC_CLRF,popGet(aop,offset));
1657 } else if(strcmp(s,"W")==0) {
1658 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1659 pcop->type = PO_GPR_REGISTER;
1661 PCOR(pcop)->rIdx = -1;
1662 PCOR(pcop)->r = NULL;
1664 DEBUGpic14_emitcode(";","%d",__LINE__);
1665 pcop->name = Safe_strdup(s);
1666 emitpcode(POC_MOVFW,pcop);
1667 emitpcode(POC_MOVWF,popGet(aop,offset));
1668 } else if(strcmp(s,one)==0) {
1669 emitpcode(POC_CLRF,popGet(aop,offset));
1670 emitpcode(POC_INCF,popGet(aop,offset));
1672 emitpcode(POC_MOVWF,popGet(aop,offset));
1680 if (aop->type == AOP_DPTR2)
1686 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1687 "aopPut writting to code space");
1691 while (offset > aop->coff) {
1693 pic14_emitcode ("inc","dptr");
1696 while (offset < aop->coff) {
1698 pic14_emitcode("lcall","__decdptr");
1703 /* if not in accumulater */
1706 pic14_emitcode ("movx","@dptr,a");
1708 if (aop->type == AOP_DPTR2)
1716 while (offset > aop->coff) {
1718 pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1720 while (offset < aop->coff) {
1722 pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1728 pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1733 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1735 if (strcmp(s,"r0") == 0 ||
1736 strcmp(s,"r1") == 0 ||
1737 strcmp(s,"r2") == 0 ||
1738 strcmp(s,"r3") == 0 ||
1739 strcmp(s,"r4") == 0 ||
1740 strcmp(s,"r5") == 0 ||
1741 strcmp(s,"r6") == 0 ||
1742 strcmp(s,"r7") == 0 ) {
1744 sprintf(buffer,"a%s",s);
1745 pic14_emitcode("mov","@%s,%s",
1746 aop->aopu.aop_ptr->name,buffer);
1748 pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1753 if (strcmp(s,"a") == 0)
1754 pic14_emitcode("push","acc");
1756 pic14_emitcode("push","%s",s);
1761 /* if bit variable */
1762 if (!aop->aopu.aop_dir) {
1763 pic14_emitcode("clr","a");
1764 pic14_emitcode("rlc","a");
1767 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1770 pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1773 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1775 lbl = newiTempLabel(NULL);
1777 if (strcmp(s,"a")) {
1780 pic14_emitcode("clr","c");
1781 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1782 pic14_emitcode("cpl","c");
1783 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1784 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1791 if (strcmp(aop->aopu.aop_str[offset],s))
1792 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1797 if (!offset && (strcmp(s,"acc") == 0))
1800 if (strcmp(aop->aopu.aop_str[offset],s))
1801 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1805 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1806 "aopPut got unsupported aop->type");
1812 /*-----------------------------------------------------------------*/
1813 /* mov2w_op - generate either a MOVLW or MOVFW based operand type */
1814 /*-----------------------------------------------------------------*/
1815 static void mov2w_op (operand *op, int offset)
1820 /* for PO_IMMEDIATEs: use address or value? */
1821 if (op_isLitLike (op))
1823 /* access address of op */
1824 if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
1825 if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
1827 if (offset == GPTRSIZE-1)
1828 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1830 emitpcode (POC_MOVLW, popGetLit (0));
1833 emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
1835 /* access value stored in op */
1836 mov2w (AOP(op), offset);
1841 /*-----------------------------------------------------------------*/
1842 /* mov2w - generate either a MOVLW or MOVFW based operand type */
1843 /*-----------------------------------------------------------------*/
1844 void mov2w (asmop *aop, int offset)
1850 DEBUGpic14_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
1852 if ( aop_isLitLike (aop) )
1853 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1855 emitpcode(POC_MOVFW,popGet(aop,offset));
1859 static void movwf (asmop *op, int offset)
1861 emitpcode (POC_MOVWF, popGet(op, offset));
1864 static pCodeOp *get_argument_pcop (int idx)
1866 assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1867 return popRegFromIdx (Gstack_base_addr - (idx - 1));
1870 static pCodeOp *get_return_val_pcop (int offset)
1872 assert (offset > 0 && "the most significant byte is returned via WREG");
1873 return popRegFromIdx (Gstack_base_addr - (offset - 1));
1876 static void pass_argument (operand *op, int offset, int idx)
1879 mov2w_op (op, offset);
1881 emitpcode(POC_MOVWF, get_argument_pcop (idx));
1884 static void get_returnvalue (operand *op, int offset, int idx)
1887 emitpcode(POC_MOVFW, get_return_val_pcop (idx));
1888 movwf(AOP(op), offset);
1891 static void call_libraryfunc (char *name)
1893 /* library code might reside in different page... */
1894 emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1895 /* call the library function */
1896 emitpcode (POC_CALL, popGetExternal (name));
1897 /* might return from different page... */
1898 emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1901 /*-----------------------------------------------------------------*/
1902 /* reAdjustPreg - points a register back to where it should */
1903 /*-----------------------------------------------------------------*/
1904 static void reAdjustPreg (asmop *aop)
1908 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1910 if ((size = aop->size) <= 1)
1913 switch (aop->type) {
1917 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1921 if (aop->type == AOP_DPTR2)
1927 pic14_emitcode("lcall","__decdptr");
1930 if (aop->type == AOP_DPTR2)
1943 /*-----------------------------------------------------------------*/
1944 /* opIsGptr: returns non-zero if the passed operand is */
1945 /* a generic pointer type. */
1946 /*-----------------------------------------------------------------*/
1947 static int opIsGptr(operand *op)
1949 sym_link *type = operandType(op);
1951 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1952 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1960 /*-----------------------------------------------------------------*/
1961 /* pic14_getDataSize - get the operand data size */
1962 /*-----------------------------------------------------------------*/
1963 int pic14_getDataSize(operand *op)
1967 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1970 size = getSize(OP_SYM_ETYPE(op));
1972 //return AOP_SIZE(op);
1974 // tsd- in the pic port, the genptr size is 1, so this code here
1975 // fails. ( in the 8051 port, the size was 4).
1977 size = AOP_SIZE(op);
1978 if (IS_GENPTR(OP_SYM_TYPE(op)))
1980 sym_link *type = operandType(op);
1981 if (IS_GENPTR(type))
1983 /* generic pointer; arithmetic operations
1984 * should ignore the high byte (pointer type).
1987 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1994 /*-----------------------------------------------------------------*/
1995 /* pic14_outAcc - output Acc */
1996 /*-----------------------------------------------------------------*/
1997 void pic14_outAcc(operand *result)
2000 DEBUGpic14_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2001 DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
2004 size = pic14_getDataSize(result);
2006 emitpcode(POC_MOVWF,popGet(AOP(result),0));
2009 /* unsigned or positive */
2011 emitpcode(POC_CLRF,popGet(AOP(result),offset++));
2016 /*-----------------------------------------------------------------*/
2017 /* pic14_outBitC - output a bit C */
2018 /*-----------------------------------------------------------------*/
2019 void pic14_outBitC(operand *result)
2022 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2023 /* if the result is bit */
2024 if (AOP_TYPE(result) == AOP_CRY)
2025 aopPut(AOP(result),"c",0);
2027 pic14_emitcode("clr","a ; %d", __LINE__);
2028 pic14_emitcode("rlc","a");
2029 pic14_outAcc(result);
2033 /*-----------------------------------------------------------------*/
2034 /* pic14_toBoolean - emit code for orl a,operator(sizeop) */
2035 /*-----------------------------------------------------------------*/
2036 void pic14_toBoolean(operand *oper)
2038 int size = AOP_SIZE(oper);
2041 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2046 /* MOVFW does not load the flags... */
2047 if (AOP_TYPE(oper) == AOP_ACC) {
2048 emitpcode(POC_IORLW, popGetLit(0));
2051 emitpcode(POC_MOVLW, popGetLit(0));
2055 if ( AOP_TYPE(oper) != AOP_ACC) {
2056 emitpcode(POC_MOVFW,popGet(AOP(oper),0));
2061 while (offset < size) {
2062 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
2064 /* Z is set iff (oper == 0) */
2068 /*-----------------------------------------------------------------*/
2069 /* genNot - generate code for ! operation */
2070 /*-----------------------------------------------------------------*/
2071 static void genNot (iCode *ic)
2078 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2079 /* assign asmOps to operand & result */
2080 aopOp (IC_LEFT(ic),ic,FALSE);
2081 aopOp (IC_RESULT(ic),ic,TRUE);
2083 DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2084 /* if in bit space then a special case */
2085 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2086 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2087 emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
2088 emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
2090 emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
2091 emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
2092 emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
2097 size = AOP_SIZE(IC_LEFT(ic));
2098 mov2w (AOP(IC_LEFT(ic)),0);
2101 if (op_isLitLike (IC_LEFT(ic)))
2102 emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
2104 emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
2106 emitpcode(POC_MOVLW, popGetLit (0));
2108 emitpcode(POC_MOVLW, popGetLit (1));
2109 movwf(AOP(IC_RESULT(ic)), 0);
2111 for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
2113 emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
2118 /* release the aops */
2119 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2120 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2124 /*-----------------------------------------------------------------*/
2125 /* genCpl - generate code for complement */
2126 /*-----------------------------------------------------------------*/
2127 static void genCpl (iCode *ic)
2129 operand *left, *result;
2134 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2135 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2136 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2138 /* if both are in bit space then
2140 if (AOP_TYPE(result) == AOP_CRY &&
2141 AOP_TYPE(left) == AOP_CRY ) {
2143 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir);
2144 pic14_emitcode("cpl","c");
2145 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir);
2149 size = AOP_SIZE(result);
2150 if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
2153 if(AOP_TYPE(left) == AOP_ACC)
2154 emitpcode(POC_XORLW, popGetLit(0xff));
2156 emitpcode(POC_COMFW,popGet(AOP(left),offset));
2158 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
2161 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2165 /* release the aops */
2166 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2167 freeAsmop(result,NULL,ic,TRUE);
2170 /*-----------------------------------------------------------------*/
2171 /* genUminusFloat - unary minus for floating points */
2172 /*-----------------------------------------------------------------*/
2173 static void genUminusFloat(operand *op,operand *result)
2175 int size ,offset =0 ;
2180 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2181 /* for this we just need to flip the
2182 first it then copy the rest in place */
2183 size = AOP_SIZE(op) - 1;
2184 l = aopGet(AOP(op),3,FALSE,FALSE);
2188 pic14_emitcode("cpl","acc.7");
2189 aopPut(AOP(result),"a",3);
2193 aopGet(AOP(op),offset,FALSE,FALSE),
2199 /*-----------------------------------------------------------------*/
2200 /* genUminus - unary minus code generation */
2201 /*-----------------------------------------------------------------*/
2202 static void genUminus (iCode *ic)
2205 sym_link *optype, *rtype;
2209 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2211 aopOp(IC_LEFT(ic),ic,FALSE);
2212 aopOp(IC_RESULT(ic),ic,TRUE);
2214 /* if both in bit space then special
2216 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2217 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2219 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0));
2220 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2221 emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0));
2226 optype = operandType(IC_LEFT(ic));
2227 rtype = operandType(IC_RESULT(ic));
2229 /* if float then do float stuff */
2230 if (IS_FLOAT(optype)) {
2231 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2235 /* otherwise subtract from zero by taking the 2's complement */
2236 size = AOP_SIZE(IC_LEFT(ic));
2238 for(i=0; i<size; i++) {
2239 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2240 emitpcode(POC_COMF, popGet(AOP(IC_LEFT(ic)),i));
2242 emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2243 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2247 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0));
2248 for(i=1; i<size; i++) {
2250 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),i));
2254 /* release the aops */
2255 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2256 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2259 /*-----------------------------------------------------------------*/
2260 /* saveRegisters - will look for a call and save the registers */
2261 /*-----------------------------------------------------------------*/
2262 static void saveRegisters(iCode *lic)
2271 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2273 for (ic = lic ; ic ; ic = ic->next)
2274 if (ic->op == CALL || ic->op == PCALL)
2278 fprintf(stderr,"found parameter push with no function call\n");
2282 /* if the registers have been saved already then
2284 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2287 /* find the registers in use at this time
2288 and push them away to safety */
2289 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2293 if (options.useXstack) {
2294 if (bitVectBitValue(rsave,R0_IDX))
2295 pic14_emitcode("mov","b,r0");
2296 pic14_emitcode("mov","r0,%s",spname);
2297 for (i = 0 ; i < pic14_nRegs ; i++) {
2298 if (bitVectBitValue(rsave,i)) {
2300 pic14_emitcode("mov","a,b");
2302 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2303 pic14_emitcode("movx","@r0,a");
2304 pic14_emitcode("inc","r0");
2307 pic14_emitcode("mov","%s,r0",spname);
2308 if (bitVectBitValue(rsave,R0_IDX))
2309 pic14_emitcode("mov","r0,b");
2311 //for (i = 0 ; i < pic14_nRegs ; i++) {
2312 // if (bitVectBitValue(rsave,i))
2313 // pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2316 dtype = operandType(IC_LEFT(ic));
2317 if (currFunc && dtype &&
2318 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2319 IFFUNC_ISISR(currFunc->type) &&
2322 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2325 /*-----------------------------------------------------------------*/
2326 /* unsaveRegisters - pop the pushed registers */
2327 /*-----------------------------------------------------------------*/
2328 static void unsaveRegisters (iCode *ic)
2335 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2336 /* find the registers in use at this time
2337 and push them away to safety */
2338 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2341 if (options.useXstack) {
2342 pic14_emitcode("mov","r0,%s",spname);
2343 for (i = pic14_nRegs ; i >= 0 ; i--) {
2344 if (bitVectBitValue(rsave,i)) {
2345 pic14_emitcode("dec","r0");
2346 pic14_emitcode("movx","a,@r0");
2348 pic14_emitcode("mov","b,a");
2350 pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2354 pic14_emitcode("mov","%s,r0",spname);
2355 if (bitVectBitValue(rsave,R0_IDX))
2356 pic14_emitcode("mov","r0,b");
2358 //for (i = pic14_nRegs ; i >= 0 ; i--) {
2359 // if (bitVectBitValue(rsave,i))
2360 // pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2366 /*-----------------------------------------------------------------*/
2368 /*-----------------------------------------------------------------*/
2369 static void pushSide(operand * oper, int size)
2373 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2375 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2376 if (AOP_TYPE(oper) != AOP_REG &&
2377 AOP_TYPE(oper) != AOP_DIR &&
2379 pic14_emitcode("mov","a,%s",l);
2380 pic14_emitcode("push","acc");
2382 pic14_emitcode("push","%s",l);
2387 /*-----------------------------------------------------------------*/
2388 /* assignResultValue - */
2389 /*-----------------------------------------------------------------*/
2390 static void assignResultValue(operand * oper)
2392 int size = AOP_SIZE(oper);
2397 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2399 DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2401 /* assign MSB first (passed via WREG) */
2403 get_returnvalue (oper, size, offset + GpsuedoStkPtr);
2409 /*-----------------------------------------------------------------*/
2410 /* genIpush - genrate code for pushing this gets a little complex */
2411 /*-----------------------------------------------------------------*/
2412 static void genIpush (iCode *ic)
2416 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2418 int size, offset = 0 ;
2422 /* if this is not a parm push : ie. it is spill push
2423 and spill push is always done on the local stack */
2424 if (!ic->parmPush) {
2426 /* and the item is spilt then do nothing */
2427 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2430 aopOp(IC_LEFT(ic),ic,FALSE);
2431 size = AOP_SIZE(IC_LEFT(ic));
2432 /* push it on the stack */
2434 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2439 pic14_emitcode("push","%s",l);
2444 /* this is a paramter push: in this case we call
2445 the routine to find the call and save those
2446 registers that need to be saved */
2449 /* then do the push */
2450 aopOp(IC_LEFT(ic),ic,FALSE);
2453 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2454 size = AOP_SIZE(IC_LEFT(ic));
2457 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2458 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
2459 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2461 pic14_emitcode("mov","a,%s",l);
2462 pic14_emitcode("push","acc");
2464 pic14_emitcode("push","%s",l);
2467 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2471 /*-----------------------------------------------------------------*/
2472 /* genIpop - recover the registers: can happen only for spilling */
2473 /*-----------------------------------------------------------------*/
2474 static void genIpop (iCode *ic)
2478 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2479 assert (!"genIpop -- unimplemented");
2484 /* if the temp was not pushed then */
2485 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2488 aopOp(IC_LEFT(ic),ic,FALSE);
2489 size = AOP_SIZE(IC_LEFT(ic));
2492 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2495 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2499 /*-----------------------------------------------------------------*/
2500 /* unsaverbank - restores the resgister bank from stack */
2501 /*-----------------------------------------------------------------*/
2502 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2506 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2512 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2514 if (options.useXstack) {
2516 r = getFreePtr(ic,&aop,FALSE);
2519 pic14_emitcode("mov","%s,_spx",r->name);
2520 pic14_emitcode("movx","a,@%s",r->name);
2521 pic14_emitcode("mov","psw,a");
2522 pic14_emitcode("dec","%s",r->name);
2525 pic14_emitcode ("pop","psw");
2528 for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2529 if (options.useXstack) {
2530 pic14_emitcode("movx","a,@%s",r->name);
2531 //pic14_emitcode("mov","(%s+%d),a",
2532 // regspic14[i].base,8*bank+regspic14[i].offset);
2533 pic14_emitcode("dec","%s",r->name);
2536 pic14_emitcode("pop",""); //"(%s+%d)",
2537 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2540 if (options.useXstack) {
2542 pic14_emitcode("mov","_spx,%s",r->name);
2543 freeAsmop(NULL,aop,ic,TRUE);
2549 /*-----------------------------------------------------------------*/
2550 /* saverbank - saves an entire register bank on the stack */
2551 /*-----------------------------------------------------------------*/
2552 static void saverbank (int bank, iCode *ic, bool pushPsw)
2556 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2562 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2563 if (options.useXstack) {
2566 r = getFreePtr(ic,&aop,FALSE);
2567 pic14_emitcode("mov","%s,_spx",r->name);
2571 for (i = 0 ; i < pic14_nRegs ;i++) {
2572 if (options.useXstack) {
2573 pic14_emitcode("inc","%s",r->name);
2574 //pic14_emitcode("mov","a,(%s+%d)",
2575 // regspic14[i].base,8*bank+regspic14[i].offset);
2576 pic14_emitcode("movx","@%s,a",r->name);
2578 pic14_emitcode("push","");// "(%s+%d)",
2579 //regspic14[i].base,8*bank+regspic14[i].offset);
2583 if (options.useXstack) {
2584 pic14_emitcode("mov","a,psw");
2585 pic14_emitcode("movx","@%s,a",r->name);
2586 pic14_emitcode("inc","%s",r->name);
2587 pic14_emitcode("mov","_spx,%s",r->name);
2588 freeAsmop (NULL,aop,ic,TRUE);
2591 pic14_emitcode("push","psw");
2593 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2599 /*-----------------------------------------------------------------*/
2600 /* genCall - generates a call statement */
2601 /*-----------------------------------------------------------------*/
2602 static void genCall (iCode *ic)
2611 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2613 /* if caller saves & we have not saved then */
2617 /* if we are calling a function that is not using
2618 the same register bank then we need to save the
2619 destination registers on the stack */
2620 dtype = operandType(IC_LEFT(ic));
2621 if (currFunc && dtype &&
2622 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2623 IFFUNC_ISISR(currFunc->type) &&
2626 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2628 /* if send set is not empty the assign */
2631 /* For the Pic port, there is no data stack.
2632 * So parameters passed to functions are stored
2633 * in registers. (The pCode optimizer will get
2634 * rid of most of these :).
2636 int psuedoStkPtr=-1;
2637 int firstTimeThruLoop = 1;
2639 _G.sendSet = reverseSet(_G.sendSet);
2641 /* First figure how many parameters are getting passed */
2642 for (sic = setFirstItem(_G.sendSet) ; sic ;
2643 sic = setNextItem(_G.sendSet)) {
2645 aopOp(IC_LEFT(sic),sic,FALSE);
2646 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2647 freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2650 for (sic = setFirstItem(_G.sendSet) ; sic ;
2651 sic = setNextItem(_G.sendSet)) {
2652 int size, offset = 0;
2654 aopOp(IC_LEFT(sic),sic,FALSE);
2655 size = AOP_SIZE(IC_LEFT(sic));
2658 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2659 AopType(AOP_TYPE(IC_LEFT(sic))));
2661 if(!firstTimeThruLoop) {
2662 /* If this is not the first time we've been through the loop
2663 * then we need to save the parameter in a temporary
2664 * register. The last byte of the last parameter is
2666 emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2669 firstTimeThruLoop=0;
2671 mov2w_op (IC_LEFT(sic), offset);
2674 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2679 sym = OP_SYMBOL(IC_LEFT(ic));
2680 name = sym->rname[0] ? sym->rname : sym->name;
2681 isExtern = IS_EXTERN(sym->etype);
2683 emitpcode(POC_PAGESEL,popGetWithString(name,1)); /* Extern functions maybe on another page - must call pagesel */
2685 emitpcode(POC_CALL,popGetWithString(name,isExtern));
2687 emitpcode(POC_PAGESEL,popGetWithString("$",0)); /* May have returned from another page - must call pagesel to restore PCLATH before next goto or call instruction */
2690 /* if we need assign a result value */
2691 if ((IS_ITEMP(IC_RESULT(ic)) &&
2692 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2693 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2694 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2697 aopOp(IC_RESULT(ic),ic,FALSE);
2700 assignResultValue(IC_RESULT(ic));
2702 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2703 AopType(AOP_TYPE(IC_RESULT(ic))));
2705 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2708 /* if register bank was saved then pop them */
2710 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2712 /* if we hade saved some registers then unsave them */
2713 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2714 unsaveRegisters (ic);
2719 /*-----------------------------------------------------------------*/
2720 /* genPcall - generates a call by pointer statement */
2721 /*-----------------------------------------------------------------*/
2722 static void genPcall (iCode *ic)
2725 symbol *albl = newiTempLabel(NULL);
2726 symbol *blbl = newiTempLabel(NULL);
2733 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2734 /* if caller saves & we have not saved then */
2738 /* if we are calling a function that is not using
2739 the same register bank then we need to save the
2740 destination registers on the stack */
2741 dtype = operandType(IC_LEFT(ic));
2742 if (currFunc && dtype &&
2743 IFFUNC_ISISR(currFunc->type) &&
2744 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2745 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2748 aopOp(left,ic,FALSE);
2749 DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2751 poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2753 pushSide(IC_LEFT(ic), FPTRSIZE);
2755 /* if send set is not empty, assign parameters */
2758 DEBUGpic14_emitcode ("; ***","%s %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2759 /* no way to pass args - W always gets used to make the call */
2761 /* first idea - factor out a common helper function and call it.
2762 But don't know how to get it generated only once in its own block
2764 if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2767 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2768 DEBUGpic14_emitcode ("; ***","%s %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2769 buffer = Safe_calloc(1,strlen(rname)+16);
2770 sprintf(buffer, "%s_goto_helper", rname);
2771 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2775 emitpcode(POC_CALL,popGetLabel(albl->key));
2776 pcop = popGetLabel(blbl->key);
2777 emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
2778 emitpcode(POC_GOTO,pcop);
2779 emitpLabel(albl->key);
2781 emitpcode(poc,popGetAddr(AOP(left),1,0));
2782 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2783 emitpcode(poc,popGetAddr(AOP(left),0,0));
2784 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2786 emitpLabel(blbl->key);
2788 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2790 /* if we need to assign a result value */
2791 if ((IS_ITEMP(IC_RESULT(ic)) &&
2792 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2793 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2794 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2797 aopOp(IC_RESULT(ic),ic,FALSE);
2802 assignResultValue(IC_RESULT(ic));
2804 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2807 /* if register bank was saved then unsave them */
2808 if (currFunc && dtype &&
2809 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2810 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2812 /* if we hade saved some registers then
2815 unsaveRegisters (ic);
2819 /*-----------------------------------------------------------------*/
2820 /* resultRemat - result is rematerializable */
2821 /*-----------------------------------------------------------------*/
2822 static int resultRemat (iCode *ic)
2824 // DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2827 if (SKIP_IC(ic) || ic->op == IFX)
2830 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2831 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2832 if (sym->remat && !POINTER_SET(ic))
2839 #if defined(__BORLANDC__) || defined(_MSC_VER)
2840 #define STRCASECMP stricmp
2842 #define STRCASECMP strcasecmp
2846 /*-----------------------------------------------------------------*/
2847 /* inExcludeList - return 1 if the string is in exclude Reg list */
2848 /*-----------------------------------------------------------------*/
2849 static bool inExcludeList(char *s)
2851 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2854 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2855 if (options.excludeRegs[i] &&
2856 STRCASECMP(options.excludeRegs[i],"none") == 0)
2859 for ( i = 0 ; options.excludeRegs[i]; i++) {
2860 if (options.excludeRegs[i] &&
2861 STRCASECMP(s,options.excludeRegs[i]) == 0)
2868 /*-----------------------------------------------------------------*/
2869 /* genFunction - generated code for function entry */
2870 /*-----------------------------------------------------------------*/
2871 static void genFunction (iCode *ic)
2878 DEBUGpic14_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2880 labelOffset += (max_key+4);
2884 /* create the function header */
2885 pic14_emitcode(";","-----------------------------------------");
2886 pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2887 pic14_emitcode(";","-----------------------------------------");
2889 /* prevent this symbol from being emitted as 'extern' */
2890 pic14_stringInSet(sym->rname, &pic14_localFunctions, 1);
2892 pic14_emitcode("","%s:",sym->rname);
2893 addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2895 ftype = operandType(IC_LEFT(ic));
2897 /* if critical function then turn interrupts off */
2898 if (IFFUNC_ISCRITICAL(ftype))
2899 pic14_emitcode("clr","ea");
2901 /* here we need to generate the equates for the
2902 register bank if required */
2904 if (FUNC_REGBANK(ftype) != rbank) {
2907 rbank = FUNC_REGBANK(ftype);
2908 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2909 if (strcmp(regspic14[i].base,"0") == 0)
2910 pic14_emitcode("","%s = 0x%02x",
2912 8*rbank+regspic14[i].offset);
2914 pic14_emitcode ("","%s = %s + 0x%02x",
2917 8*rbank+regspic14[i].offset);
2922 /* if this is an interrupt service routine */
2923 if (IFFUNC_ISISR(sym->type)) {
2924 /* already done in pic14createInterruptVect() - delete me
2925 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2926 emitpcodeNULLop(POC_NOP);
2927 emitpcodeNULLop(POC_NOP);
2928 emitpcodeNULLop(POC_NOP);
2930 emitpcode(POC_MOVWF, popCopyReg(&pc_wsave));
2931 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2932 emitpcode(POC_CLRF, popCopyReg(&pc_status));
2933 emitpcode(POC_MOVWF, popCopyReg(&pc_ssave));
2934 emitpcode(POC_MOVFW, popCopyReg(&pc_pclath));
2935 emitpcode(POC_MOVWF, popCopyReg(&pc_psave));
2936 emitpcode(POC_CLRF, popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2938 pBlockConvert2ISR(pb);
2939 pic14_hasInterrupt = 1;
2941 if (!inExcludeList("acc"))
2942 pic14_emitcode ("push","acc");
2943 if (!inExcludeList("b"))
2944 pic14_emitcode ("push","b");
2945 if (!inExcludeList("dpl"))
2946 pic14_emitcode ("push","dpl");
2947 if (!inExcludeList("dph"))
2948 pic14_emitcode ("push","dph");
2949 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2951 pic14_emitcode ("push", "dpx");
2952 /* Make sure we're using standard DPTR */
2953 pic14_emitcode ("push", "dps");
2954 pic14_emitcode ("mov", "dps, #0x00");
2955 if (options.stack10bit)
2957 /* This ISR could conceivably use DPTR2. Better save it. */
2958 pic14_emitcode ("push", "dpl1");
2959 pic14_emitcode ("push", "dph1");
2960 pic14_emitcode ("push", "dpx1");
2963 /* if this isr has no bank i.e. is going to
2964 run with bank 0 , then we need to save more
2966 if (!FUNC_REGBANK(sym->type)) {
2968 /* if this function does not call any other
2969 function then we can be economical and
2970 save only those registers that are used */
2971 if (! IFFUNC_HASFCALL(sym->type)) {
2974 /* if any registers used */
2975 if (sym->regsUsed) {
2976 /* save the registers used */
2977 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2978 if (bitVectBitValue(sym->regsUsed,i) ||
2979 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2980 pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);
2985 /* this function has a function call cannot
2986 determines register usage so we will have the
2988 saverbank(0,ic,FALSE);
2993 /* if callee-save to be used for this function
2994 then save the registers being used in this function */
2995 if (IFFUNC_CALLEESAVES(sym->type)) {
2998 /* if any registers used */
2999 if (sym->regsUsed) {
3000 /* save the registers used */
3001 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3002 if (bitVectBitValue(sym->regsUsed,i) ||
3003 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
3004 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
3012 /* set the register bank to the desired value */
3013 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
3014 pic14_emitcode("push","psw");
3015 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);
3018 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3020 if (options.useXstack) {
3021 pic14_emitcode("mov","r0,%s",spname);
3022 pic14_emitcode("mov","a,_bp");
3023 pic14_emitcode("movx","@r0,a");
3024 pic14_emitcode("inc","%s",spname);
3028 /* set up the stack */
3029 pic14_emitcode ("push","_bp"); /* save the callers stack */
3031 pic14_emitcode ("mov","_bp,%s",spname);
3034 /* adjust the stack for the function */
3039 werror(W_STACK_OVERFLOW,sym->name);
3041 if (i > 3 && sym->recvSize < 4) {
3043 pic14_emitcode ("mov","a,sp");
3044 pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3045 pic14_emitcode ("mov","sp,a");
3050 pic14_emitcode("inc","sp");
3055 pic14_emitcode ("mov","a,_spx");
3056 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3057 pic14_emitcode ("mov","_spx,a");
3062 /*-----------------------------------------------------------------*/
3063 /* genEndFunction - generates epilogue for functions */
3064 /*-----------------------------------------------------------------*/
3065 static void genEndFunction (iCode *ic)
3067 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3071 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3073 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3075 pic14_emitcode ("mov","%s,_bp",spname);
3078 /* if use external stack but some variables were
3079 added to the local stack then decrement the
3081 if (options.useXstack && sym->stack) {
3082 pic14_emitcode("mov","a,sp");
3083 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3084 pic14_emitcode("mov","sp,a");
3088 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3089 if (options.useXstack) {
3090 pic14_emitcode("mov","r0,%s",spname);
3091 pic14_emitcode("movx","a,@r0");
3092 pic14_emitcode("mov","_bp,a");
3093 pic14_emitcode("dec","%s",spname);
3097 pic14_emitcode ("pop","_bp");
3101 /* restore the register bank */
3102 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3103 pic14_emitcode ("pop","psw");
3105 if (IFFUNC_ISISR(sym->type)) {
3107 /* now we need to restore the registers */
3108 /* if this isr has no bank i.e. is going to
3109 run with bank 0 , then we need to save more
3111 if (!FUNC_REGBANK(sym->type)) {
3113 /* if this function does not call any other
3114 function then we can be economical and
3115 save only those registers that are used */
3116 if (! IFFUNC_HASFCALL(sym->type)) {
3119 /* if any registers used */
3120 if (sym->regsUsed) {
3121 /* save the registers used */
3122 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3123 if (bitVectBitValue(sym->regsUsed,i) ||
3124 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3125 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3130 /* this function has a function call cannot
3131 determines register usage so we will have the
3133 unsaverbank(0,ic,FALSE);
3137 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3139 if (options.stack10bit)
3141 pic14_emitcode ("pop", "dpx1");
3142 pic14_emitcode ("pop", "dph1");
3143 pic14_emitcode ("pop", "dpl1");
3145 pic14_emitcode ("pop", "dps");
3146 pic14_emitcode ("pop", "dpx");
3148 if (!inExcludeList("dph"))
3149 pic14_emitcode ("pop","dph");
3150 if (!inExcludeList("dpl"))
3151 pic14_emitcode ("pop","dpl");
3152 if (!inExcludeList("b"))
3153 pic14_emitcode ("pop","b");
3154 if (!inExcludeList("acc"))
3155 pic14_emitcode ("pop","acc");
3157 if (IFFUNC_ISCRITICAL(sym->type))
3158 pic14_emitcode("setb","ea");
3161 /* if debug then send end of function */
3162 /* if (options.debug && currFunc) { */
3164 debugFile->writeEndFunction (currFunc, ic, 1);
3167 pic14_emitcode ("reti","");
3168 emitpcode(POC_MOVFW, popCopyReg(&pc_psave));
3169 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
3170 emitpcode(POC_CLRF, popCopyReg(&pc_status));
3171 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3172 emitpcode(POC_MOVWF, popCopyReg(&pc_status));
3173 emitpcode(POC_SWAPF, popCopyReg(&pc_wsave));
3174 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3175 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3176 emitpcodeNULLop(POC_RETFIE);
3179 if (IFFUNC_ISCRITICAL(sym->type))
3180 pic14_emitcode("setb","ea");
3182 if (IFFUNC_CALLEESAVES(sym->type)) {
3185 /* if any registers used */
3186 if (sym->regsUsed) {
3187 /* save the registers used */
3188 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3189 if (bitVectBitValue(sym->regsUsed,i) ||
3190 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3191 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3197 /* if debug then send end of function */
3199 debugFile->writeEndFunction (currFunc, ic, 1);
3202 pic14_emitcode ("return","");
3203 emitpcodeNULLop(POC_RETURN);
3205 /* Mark the end of a function */
3206 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3211 /*-----------------------------------------------------------------*/
3212 /* genRet - generate code for return statement */
3213 /*-----------------------------------------------------------------*/
3214 static void genRet (iCode *ic)
3216 int size,offset = 0;
3220 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3221 /* if we have no return value then
3222 just generate the "ret" */
3226 /* we have something to return then
3227 move the return value into place */
3228 aopOp(IC_LEFT(ic),ic,FALSE);
3229 size = AOP_SIZE(IC_LEFT(ic));
3231 for (offset = 0; offset < size; offset++)
3233 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
3236 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3239 /* generate a jump to the return label
3240 if the next is not the return statement */
3241 if (!(ic->next && ic->next->op == LABEL &&
3242 IC_LABEL(ic->next) == returnLabel)) {
3244 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3249 /*-----------------------------------------------------------------*/
3250 /* genLabel - generates a label */
3251 /*-----------------------------------------------------------------*/
3252 static void genLabel (iCode *ic)
3256 /* special case never generate */
3257 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3258 if (IC_LABEL(ic) == entryLabel)
3261 emitpLabel(IC_LABEL(ic)->key);
3262 pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3265 /*-----------------------------------------------------------------*/
3266 /* genGoto - generates a goto */
3267 /*-----------------------------------------------------------------*/
3269 static void genGoto (iCode *ic)
3273 emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3274 pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3278 /*-----------------------------------------------------------------*/
3279 /* genMultbits :- multiplication of bits */
3280 /*-----------------------------------------------------------------*/
3281 static void genMultbits (operand *left,
3286 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3288 if(!pic14_sameRegs(AOP(result),AOP(right)))
3289 emitpcode(POC_BSF, popGet(AOP(result),0));
3291 emitpcode(POC_BTFSC,popGet(AOP(right),0));
3292 emitpcode(POC_BTFSS,popGet(AOP(left),0));
3293 emitpcode(POC_BCF, popGet(AOP(result),0));
3298 /*-----------------------------------------------------------------*/
3299 /* genMultOneByte : 8 bit multiplication & division */
3300 /*-----------------------------------------------------------------*/
3301 static void genMultOneByte (operand *left,
3305 char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
3313 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3314 DEBUGpic14_AopType(__LINE__,left,right,result);
3315 DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3317 /* (if two literals, the value is computed before) */
3318 /* if one literal, literal on the right */
3319 if (AOP_TYPE(left) == AOP_LIT){
3325 assert (AOP_SIZE(left) == AOP_SIZE(right));
3327 size = min(AOP_SIZE(result),AOP_SIZE(left));
3328 offset = Gstack_base_addr - (2*size - 1);
3330 /* pass right operand as argument */
3331 for (i=0; i < size; i++)
3333 mov2w (AOP(right), i);
3334 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3337 /* pass left operand as argument */
3338 for (i=0; i < size; i++)
3340 mov2w (AOP(left), i);
3341 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3343 assert (offset == Gstack_base_addr);
3345 /* call library routine */
3346 assert (size > 0 && size <= 4);
3347 call_libraryfunc (func[size]);
3350 movwf (AOP(result), size-1);
3351 for (i=0; i < size - 1; i++)
3353 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
3354 movwf (AOP(result), size - 2 - i);
3357 /* now (zero-/sign) extend the result to its size */
3358 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
3361 /*-----------------------------------------------------------------*/
3362 /* genMult - generates code for multiplication */
3363 /*-----------------------------------------------------------------*/
3364 static void genMult (iCode *ic)
3366 operand *left = IC_LEFT(ic);
3367 operand *right = IC_RIGHT(ic);
3368 operand *result= IC_RESULT(ic);
3372 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3373 /* assign the amsops */
3374 aopOp (left,ic,FALSE);
3375 aopOp (right,ic,FALSE);
3376 aopOp (result,ic,TRUE);
3378 DEBUGpic14_AopType(__LINE__,left,right,result);
3380 /* special cases first */
3382 if (AOP_TYPE(left) == AOP_CRY &&
3383 AOP_TYPE(right)== AOP_CRY) {
3384 genMultbits(left,right,result);
3388 /* if both are of size == 1 */
3389 if (AOP_SIZE(left) == 1 &&
3390 AOP_SIZE(right) == 1 ) {
3391 genMultOneByte(left,right,result);
3395 /* should have been converted to function call */
3399 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3400 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3401 freeAsmop(result,NULL,ic,TRUE);
3404 /*-----------------------------------------------------------------*/
3405 /* genDivbits :- division of bits */
3406 /*-----------------------------------------------------------------*/
3407 static void genDivbits (operand *left,
3416 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3417 /* the result must be bit */
3418 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3419 l = aopGet(AOP(left),0,FALSE,FALSE);
3423 pic14_emitcode("div","ab");
3424 pic14_emitcode("rrc","a");
3425 aopPut(AOP(result),"c",0);
3428 /*-----------------------------------------------------------------*/
3429 /* genDivOneByte : 8 bit division */
3430 /*-----------------------------------------------------------------*/
3431 static void genDivOneByte (operand *left,
3438 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3440 assert (AOP_SIZE(result) == 1);
3441 assert (AOP_SIZE(right) == 1);
3442 assert (AOP_SIZE(left) == 1);
3444 size = min(AOP_SIZE(result),AOP_SIZE(left));
3446 if (AOP_TYPE(right) == AOP_LIT)
3448 /* XXX: might add specialized code */
3451 if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3453 /* unsigned division */
3455 mov2w(AOP(right),0);
3456 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3458 call_libraryfunc("__divuchar");
3459 movwf(AOP(result),0);
3464 temp = popGetTempReg();
3465 lbl = newiTempLabel(NULL);
3467 /* XXX: improve this naive approach:
3468 [result] = [a] / [b]
3469 ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
3473 movwf temp // temp <-- left
3474 movf right,W // W <-- right
3478 subwf temp,F // temp <-- temp - W
3479 skipNC // subwf clears CARRY (i.e. sets BORROW) if temp < W
3481 decf result // we just subtract once too often
3484 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3485 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
3488 emitpcode(POC_MOVWF, temp);
3489 mov2w(AOP(right),0);
3490 emitpcode(POC_CLRF, popGet(AOP(result),0));
3492 emitpLabel(lbl->key);
3493 emitpcode(POC_INCF, popGet(AOP(result),0));
3494 emitpcode(POC_SUBWF, temp);
3496 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3497 emitpcode(POC_DECF, popGet(AOP(result),0));
3502 /* signed division */
3503 mov2w(AOP(right),0);
3504 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3506 call_libraryfunc("__divschar");
3507 movwf(AOP(result),0);
3510 /* now performed the signed/unsigned division -- extend result */
3511 addSign(result, 1, !SPEC_USIGN(operandType(result)));
3514 /*-----------------------------------------------------------------*/
3515 /* genDiv - generates code for division */
3516 /*-----------------------------------------------------------------*/
3517 static void genDiv (iCode *ic)
3519 operand *left = IC_LEFT(ic);
3520 operand *right = IC_RIGHT(ic);
3521 operand *result= IC_RESULT(ic);
3524 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3525 /* assign the amsops */
3526 aopOp (left,ic,FALSE);
3527 aopOp (right,ic,FALSE);
3528 aopOp (result,ic,TRUE);
3530 /* special cases first */
3532 if (AOP_TYPE(left) == AOP_CRY &&
3533 AOP_TYPE(right)== AOP_CRY) {
3534 genDivbits(left,right,result);
3538 /* if both are of size == 1 */
3539 if (AOP_SIZE(left) == 1 &&
3540 AOP_SIZE(right) == 1 ) {
3541 genDivOneByte(left,right,result);
3545 /* should have been converted to function call */
3548 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3549 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3550 freeAsmop(result,NULL,ic,TRUE);
3553 /*-----------------------------------------------------------------*/
3554 /* genModbits :- modulus of bits */
3555 /*-----------------------------------------------------------------*/
3556 static void genModbits (operand *left,
3564 /* the result must be bit */
3565 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3566 l = aopGet(AOP(left),0,FALSE,FALSE);
3570 pic14_emitcode("div","ab");
3571 pic14_emitcode("mov","a,b");
3572 pic14_emitcode("rrc","a");
3573 aopPut(AOP(result),"c",0);
3576 /*-----------------------------------------------------------------*/
3577 /* genModOneByte : 8 bit modulus */
3578 /*-----------------------------------------------------------------*/
3579 static void genModOneByte (operand *left,
3586 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3588 assert (AOP_SIZE(result) == 1);
3589 assert (AOP_SIZE(right) == 1);
3590 assert (AOP_SIZE(left) == 1);
3592 size = min(AOP_SIZE(result),AOP_SIZE(left));
3594 if (AOP_TYPE(right) == AOP_LIT)
3596 /* XXX: might add specialized code */
3599 if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3601 /* unsigned division */
3603 mov2w(AOP(right),0);
3604 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3606 call_libraryfunc("__moduchar");
3607 movwf(AOP(result),0);
3612 lbl = newiTempLabel(NULL);
3614 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3616 /* XXX: improve this naive approach:
3617 [result] = [a] % [b]
3618 ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3622 movwf result // result <-- left
3623 movf right,W // W <-- right
3625 subwf result,F // result <-- result - W
3626 skipNC // subwf clears CARRY (i.e. sets BORROW) if result < W
3628 addwf result, F // we just subtract once too often
3631 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3632 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3634 if (!pic14_sameRegs(AOP(left), AOP(result)))
3637 emitpcode(POC_MOVWF, popGet(AOP(result),0));
3639 mov2w(AOP(right),0);
3641 emitpLabel(lbl->key);
3642 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3644 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3645 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3650 /* signed division */
3651 mov2w(AOP(right),0);
3652 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3654 call_libraryfunc("__modschar");
3655 movwf(AOP(result),0);
3658 /* now we performed the signed/unsigned modulus -- extend result */
3659 addSign(result, 1, !SPEC_USIGN(operandType(result)));
3662 /*-----------------------------------------------------------------*/
3663 /* genMod - generates code for division */
3664 /*-----------------------------------------------------------------*/
3665 static void genMod (iCode *ic)
3667 operand *left = IC_LEFT(ic);
3668 operand *right = IC_RIGHT(ic);
3669 operand *result= IC_RESULT(ic);
3672 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3673 /* assign the amsops */
3674 aopOp (left,ic,FALSE);
3675 aopOp (right,ic,FALSE);
3676 aopOp (result,ic,TRUE);
3678 /* special cases first */
3680 if (AOP_TYPE(left) == AOP_CRY &&
3681 AOP_TYPE(right)== AOP_CRY) {
3682 genModbits(left,right,result);
3686 /* if both are of size == 1 */
3687 if (AOP_SIZE(left) == 1 &&
3688 AOP_SIZE(right) == 1 ) {
3689 genModOneByte(left,right,result);
3693 /* should have been converted to function call */
3697 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3698 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3699 freeAsmop(result,NULL,ic,TRUE);
3702 /*-----------------------------------------------------------------*/
3703 /* genIfxJump :- will create a jump depending on the ifx */
3704 /*-----------------------------------------------------------------*/
3706 note: May need to add parameter to indicate when a variable is in bit space.
3708 static void genIfxJump (iCode *ic, char *jval)
3712 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3713 /* if true label then we jump if condition
3715 if ( IC_TRUE(ic) ) {
3717 if(strcmp(jval,"a") == 0)
3719 else if (strcmp(jval,"c") == 0)
3722 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3723 emitpcode(POC_BTFSC, newpCodeOpBit(jval,-1,1));
3726 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3727 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3731 /* false label is present */
3732 if(strcmp(jval,"a") == 0)
3734 else if (strcmp(jval,"c") == 0)
3737 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3738 emitpcode(POC_BTFSS, newpCodeOpBit(jval,-1,1));
3741 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3742 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3747 /* mark the icode as generated */
3752 /*-----------------------------------------------------------------*/
3754 /*-----------------------------------------------------------------*/
3755 static void genSkip(iCode *ifx,int status_bit)
3761 if ( IC_TRUE(ifx) ) {
3762 switch(status_bit) {
3777 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3778 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3782 switch(status_bit) {
3796 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3797 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3804 /*-----------------------------------------------------------------*/
3806 /*-----------------------------------------------------------------*/
3807 static void genSkipc(resolvedIfx *rifx)
3818 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3819 emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3820 rifx->generated = 1;
3824 /*-----------------------------------------------------------------*/
3826 /*-----------------------------------------------------------------*/
3827 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3833 if( (rifx->condition ^ invert_condition) & 1)
3838 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3839 rifx->generated = 1;
3844 /*-----------------------------------------------------------------*/
3846 /*-----------------------------------------------------------------*/
3847 static void genSkipz(iCode *ifx, int condition)
3850 assert (ifx != NULL);
3858 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3860 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3863 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3865 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3871 /*-----------------------------------------------------------------*/
3873 /*-----------------------------------------------------------------*/
3874 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3881 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3883 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3886 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3887 rifx->generated = 1;
3892 /*-----------------------------------------------------------------*/
3893 /* genChkZeroes :- greater or less than comparison */
3894 /* For each byte in a literal that is zero, inclusive or the */
3895 /* the corresponding byte in the operand with W */
3896 /* returns true if any of the bytes are zero */
3897 /*-----------------------------------------------------------------*/
3898 static int genChkZeroes(operand *op, int lit, int size)
3905 i = (lit >> (size*8)) & 0xff;
3909 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3911 emitpcode(POC_IORFW, popGet(AOP(op),size));
3921 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3922 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
3923 #define DEBUGpc emitpComment
3925 /*-----------------------------------------------------------------*/
3926 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
3927 /* aop (if it's NOT a literal) or from lit (if */
3928 /* aop is a literal) */
3929 /*-----------------------------------------------------------------*/
3930 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3931 if (aop->type == AOP_LIT) {
3932 emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3934 emitpcode (POC_MOVFW, popGet (aop, offset));
3938 /* genCmp performs a left < right comparison, stores
3939 * the outcome in result (if != NULL) and generates
3940 * control flow code for the ifx (if != NULL).
3942 * This version leaves in sequences like
3943 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3944 * which should be optmized by the peephole
3945 * optimizer - RN 2005-01-01 */
3946 static void genCmp (operand *left,operand *right,
3947 operand *result, iCode *ifx, int sign)
3957 int invert_result = 0;
3961 assert (AOP_SIZE(left) == AOP_SIZE(right));
3962 assert (left && right);
3964 size = AOP_SIZE(right) - 1;
3965 mask = (0x100UL << (size*8)) - 1;
3966 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3971 resolveIfx (&rIfx, ifx);
3973 /**********************************************************************
3974 * handle bits - bit compares are promoted to int compares seemingly! *
3975 **********************************************************************/
3977 // THIS IS COMPLETELY UNTESTED!
3978 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3979 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3980 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3981 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3984 // 1 < {0,1} is false --> clear C by skipping the next instruction
3985 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3986 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3987 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3988 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3989 emitCLRC; // only skipped for left=0 && right=1
3991 goto correct_result_in_carry;
3995 /*************************************************
3996 * make sure that left is register (or the like) *
3997 *************************************************/
3998 if (!isAOP_REGlike(left)) {
3999 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4000 assert (isAOP_LIT(left));
4001 assert (isAOP_REGlike(right));
4002 // swap left and right
4003 // left < right <==> right > left <==> (right >= left + 1)
4004 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4006 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4007 // MAXVALUE < right? always false
4008 if (performedLt) emitCLRC; else emitSETC;
4009 goto correct_result_in_carry;
4012 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4013 // that's why we handled it above.
4020 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4021 } else if (isAOP_LIT(right)) {
4022 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4025 assert (isAOP_REGlike(left)); // left must be register or the like
4026 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4028 /*************************************************
4029 * special cases go here *
4030 *************************************************/
4032 if (isAOP_LIT(right)) {
4034 // unsigned comparison to a literal
4035 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4037 // unsigned left < 0? always false
4038 if (performedLt) emitCLRC; else emitSETC;
4039 goto correct_result_in_carry;
4042 // signed comparison to a literal
4043 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4044 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4045 // signed left < 0x80000000? always false
4046 if (performedLt) emitCLRC; else emitSETC;
4047 goto correct_result_in_carry;
4048 } else if (lit == 0) {
4049 // compare left < 0; set CARRY if SIGNBIT(left) is set
4050 if (performedLt) emitSETC; else emitCLRC;
4051 emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
4052 if (performedLt) emitCLRC; else emitSETC;
4053 goto correct_result_in_carry;
4056 } // right is literal
4058 /*************************************************
4059 * perform a general case comparison *
4060 * make sure we get CARRY==1 <==> left >= right *
4061 *************************************************/
4062 // compare most significant bytes
4063 //DEBUGpc ("comparing bytes at offset %d", size);
4065 // unsigned comparison
4066 pic14_mov2w_regOrLit (AOP(right), lit, size);
4067 emitpcode (POC_SUBFW, popGet (AOP(left), size));
4069 // signed comparison
4070 // (add 2^n to both operands then perform an unsigned comparison)
4071 if (isAOP_LIT(right)) {
4072 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4073 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4075 if (litbyte == 0x80) {
4076 // left >= 0x80 -- always true, but more bytes to come
4077 mov2w (AOP(left), size);
4078 emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
4081 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4082 mov2w (AOP(left), size);
4083 emitpcode (POC_ADDLW, popGetLit (0x80));
4084 emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4087 pCodeOp *pctemp = popGetTempReg();
4088 mov2w (AOP(left), size);
4089 emitpcode (POC_ADDLW, popGetLit (0x80));
4090 emitpcode (POC_MOVWF, pctemp);
4091 mov2w (AOP(right), size);
4092 emitpcode (POC_ADDLW, popGetLit (0x80));
4093 emitpcode (POC_SUBFW, pctemp);
4094 popReleaseTempReg(pctemp);
4098 // compare remaining bytes (treat as unsigned case from above)
4099 templbl = newiTempLabel ( NULL );
4102 //DEBUGpc ("comparing bytes at offset %d", offs);
4104 emitpcode (POC_GOTO, popGetLabel (templbl->key));
4105 pic14_mov2w_regOrLit (AOP(right), lit, offs);
4106 emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4108 emitpLabel (templbl->key);
4109 goto result_in_carry;
4113 /****************************************************
4114 * now CARRY contains the result of the comparison: *
4115 * SUBWF sets CARRY iff *
4116 * F-W >= 0 <==> F >= W <==> !(F < W) *
4117 * (F=left, W=right) *
4118 ****************************************************/
4122 // value will be used in the following genSkipc()
4123 rIfx.condition ^= 1;
4126 correct_result_in_carry:
4128 // assign result to variable (if neccessary)
4129 if (result && AOP_TYPE(result) != AOP_CRY) {
4130 //DEBUGpc ("assign result");
4131 size = AOP_SIZE(result);
4133 emitpcode (POC_CLRF, popGet (AOP(result), size));
4135 if (invert_result) {
4137 emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4139 emitpcode (POC_RLF, popGet (AOP(result), 0));
4143 // perform conditional jump
4145 //DEBUGpc ("generate control flow");
4153 /* OLD VERSION -- BUGGY, DO NOT USE */
4155 /*-----------------------------------------------------------------*/
4156 /* genCmp :- greater or less than comparison */
4157 /*-----------------------------------------------------------------*/
4158 static void genCmp (operand *left,operand *right,
4159 operand *result, iCode *ifx, int sign)
4161 int size; //, offset = 0 ;
4162 unsigned long lit = 0L,i = 0;
4163 resolvedIfx rFalseIfx;
4164 // resolvedIfx rTrueIfx;
4168 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4171 DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4172 DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4176 resolveIfx(&rFalseIfx,ifx);
4177 truelbl = newiTempLabel(NULL);
4178 size = max(AOP_SIZE(left),AOP_SIZE(right));
4180 DEBUGpic14_AopType(__LINE__,left,right,result);
4184 /* if literal is on the right then swap with left */
4185 if ((AOP_TYPE(right) == AOP_LIT)) {
4186 operand *tmp = right ;
4187 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4188 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4191 lit = (lit - 1) & mask;
4194 rFalseIfx.condition ^= 1;
4197 } else if ((AOP_TYPE(left) == AOP_LIT)) {
4198 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4202 //if(IC_TRUE(ifx) == NULL)
4203 /* if left & right are bit variables */
4204 if (AOP_TYPE(left) == AOP_CRY &&
4205 AOP_TYPE(right) == AOP_CRY ) {
4206 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4207 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4209 /* subtract right from left if at the
4210 end the carry flag is set then we know that
4211 left is greater than right */
4213 symbol *lbl = newiTempLabel(NULL);
4216 if(AOP_TYPE(right) == AOP_LIT) {
4218 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4220 DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4227 genSkipCond(&rFalseIfx,left,size-1,7);
4229 /* no need to compare to 0...*/
4230 /* NOTE: this is a de-generate compare that most certainly
4231 * creates some dead code. */
4232 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4234 if(ifx) ifx->generated = 1;
4241 //i = (lit >> (size*8)) & 0xff;
4242 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4244 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4246 i = ((0-lit) & 0xff);
4249 /* lit is 0x7f, all signed chars are less than
4250 * this except for 0x7f itself */
4251 emitpcode(POC_XORLW, popGetLit(0x7f));
4252 genSkipz2(&rFalseIfx,0);
4254 emitpcode(POC_ADDLW, popGetLit(0x80));
4255 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4256 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4261 genSkipz2(&rFalseIfx,1);
4263 emitpcode(POC_ADDLW, popGetLit(i));
4264 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4268 if(ifx) ifx->generated = 1;
4272 /* chars are out of the way. now do ints and longs */
4275 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4282 genSkipCond(&rFalseIfx,left,size,7);
4283 if(ifx) ifx->generated = 1;
4288 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4290 //rFalseIfx.condition ^= 1;
4291 //genSkipCond(&rFalseIfx,left,size,7);
4292 //rFalseIfx.condition ^= 1;
4294 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4295 if(rFalseIfx.condition)
4296 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4298 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4300 emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4301 emitpcode(POC_ADDFW, popGet(AOP(left),0));
4302 emitpcode(POC_MOVFW, popGet(AOP(left),1));
4305 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4307 if(rFalseIfx.condition) {
4309 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4315 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4316 emitpLabel(truelbl->key);
4317 if(ifx) ifx->generated = 1;
4324 if( (lit & 0xff) == 0) {
4325 /* lower byte is zero */
4326 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4327 i = ((lit >> 8) & 0xff) ^0x80;
4328 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4329 emitpcode(POC_ADDLW, popGetLit( 0x80));
4330 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4331 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4334 if(ifx) ifx->generated = 1;
4339 /* Special cases for signed longs */
4340 if( (lit & 0xffffff) == 0) {
4341 /* lower byte is zero */
4342 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4343 i = ((lit >> 8*3) & 0xff) ^0x80;
4344 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4345 emitpcode(POC_ADDLW, popGetLit( 0x80));
4346 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4347 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4350 if(ifx) ifx->generated = 1;
4358 if(lit & (0x80 << (size*8))) {
4359 /* lit is negative */
4360 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4362 //genSkipCond(&rFalseIfx,left,size,7);
4364 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4366 if(rFalseIfx.condition)
4367 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4369 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4373 /* lit is positive */
4374 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4375 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4376 if(rFalseIfx.condition)
4377 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4379 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4383 /* There are no more special cases, so perform a general compare */
4385 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4386 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4390 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4392 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4394 //rFalseIfx.condition ^= 1;
4395 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4397 emitpLabel(truelbl->key);
4399 if(ifx) ifx->generated = 1;
4406 /* sign is out of the way. So now do an unsigned compare */
4407 DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4410 /* General case - compare to an unsigned literal on the right.*/
4412 i = (lit >> (size*8)) & 0xff;
4413 emitpcode(POC_MOVLW, popGetLit(i));
4414 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4416 i = (lit >> (size*8)) & 0xff;
4419 emitpcode(POC_MOVLW, popGetLit(i));
4421 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4423 /* this byte of the lit is zero,
4424 *if it's not the last then OR in the variable */
4426 emitpcode(POC_IORFW, popGet(AOP(left),size));
4431 emitpLabel(lbl->key);
4432 //if(emitFinalCheck)
4433 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4435 emitpLabel(truelbl->key);
4437 if(ifx) ifx->generated = 1;
4444 if(AOP_TYPE(left) == AOP_LIT) {
4445 //symbol *lbl = newiTempLabel(NULL);
4447 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4450 DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4453 if((lit == 0) && (sign == 0)){
4456 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4458 emitpcode(POC_IORFW, popGet(AOP(right),--size));
4460 genSkipz2(&rFalseIfx,0);
4461 if(ifx) ifx->generated = 1;
4468 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4469 /* degenerate compare can never be true */
4470 if(rFalseIfx.condition == 0)
4471 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4473 if(ifx) ifx->generated = 1;
4478 /* signed comparisons to a literal byte */
4480 int lp1 = (lit+1) & 0xff;
4482 DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4485 rFalseIfx.condition ^= 1;
4486 genSkipCond(&rFalseIfx,right,0,7);
4489 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4490 emitpcode(POC_XORLW, popGetLit(0x7f));
4491 genSkipz2(&rFalseIfx,1);
4494 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4495 emitpcode(POC_ADDLW, popGetLit(0x80));
4496 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4497 rFalseIfx.condition ^= 1;
4498 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4501 if(ifx) ifx->generated = 1;
4503 /* unsigned comparisons to a literal byte */
4505 switch(lit & 0xff ) {
4507 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4508 genSkipz2(&rFalseIfx,0);
4509 if(ifx) ifx->generated = 1;
4512 genSkipCond(&rFalseIfx,right,0,7);
4513 if(ifx) ifx->generated = 1;
4517 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4518 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4519 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4520 rFalseIfx.condition ^= 1;
4521 if (AOP_TYPE(result) == AOP_CRY) {
4522 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4523 if(ifx) ifx->generated = 1;
4525 DEBUGpic14_emitcode ("; ***","%s %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4526 emitpcode(POC_CLRF, popGet(AOP(result),0));
4527 emitpcode(POC_RLF, popGet(AOP(result),0));
4528 emitpcode(POC_MOVLW, popGetLit(0x01));
4529 emitpcode(POC_XORWF, popGet(AOP(result),0));
4540 /* Size is greater than 1 */
4548 /* this means lit = 0xffffffff, or -1 */
4551 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4552 rFalseIfx.condition ^= 1;
4553 genSkipCond(&rFalseIfx,right,size,7);
4554 if(ifx) ifx->generated = 1;
4561 if(rFalseIfx.condition) {
4562 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4563 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4566 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4568 emitpcode(POC_IORFW, popGet(AOP(right),size));
4572 if(rFalseIfx.condition) {
4573 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4574 emitpLabel(truelbl->key);
4576 rFalseIfx.condition ^= 1;
4577 genSkipCond(&rFalseIfx,right,s,7);
4580 if(ifx) ifx->generated = 1;
4584 if((size == 1) && (0 == (lp1&0xff))) {
4585 /* lower byte of signed word is zero */
4586 DEBUGpic14_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
4587 i = ((lp1 >> 8) & 0xff) ^0x80;
4588 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4589 emitpcode(POC_ADDLW, popGetLit( 0x80));
4590 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4591 rFalseIfx.condition ^= 1;
4592 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4595 if(ifx) ifx->generated = 1;
4599 if(lit & (0x80 << (size*8))) {
4600 /* Lit is less than zero */
4601 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
4602 //rFalseIfx.condition ^= 1;
4603 //genSkipCond(&rFalseIfx,left,size,7);
4604 //rFalseIfx.condition ^= 1;
4605 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4606 //emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4608 if(rFalseIfx.condition)
4609 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4611 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4615 /* Lit is greater than or equal to zero */
4616 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
4617 //rFalseIfx.condition ^= 1;
4618 //genSkipCond(&rFalseIfx,right,size,7);
4619 //rFalseIfx.condition ^= 1;
4621 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4622 //emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4624 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4625 if(rFalseIfx.condition)
4626 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4628 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4633 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4634 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4638 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4640 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4642 rFalseIfx.condition ^= 1;
4643 //rFalseIfx.condition = 1;
4644 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4646 emitpLabel(truelbl->key);
4648 if(ifx) ifx->generated = 1;
4653 /* compare word or long to an unsigned literal on the right.*/
4658 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4661 break; /* handled above */
4664 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4666 emitpcode(POC_IORFW, popGet(AOP(right),size));
4667 genSkipz2(&rFalseIfx,0);
4671 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4673 emitpcode(POC_IORFW, popGet(AOP(right),size));
4676 if(rFalseIfx.condition)
4677 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4679 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4682 emitpcode(POC_MOVLW, popGetLit(lit+1));
4683 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4685 rFalseIfx.condition ^= 1;
4686 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4689 emitpLabel(truelbl->key);
4691 if(ifx) ifx->generated = 1;
4697 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4698 i = (lit >> (size*8)) & 0xff;
4700 emitpcode(POC_MOVLW, popGetLit(i));
4701 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4704 i = (lit >> (size*8)) & 0xff;
4707 emitpcode(POC_MOVLW, popGetLit(i));
4709 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4711 /* this byte of the lit is zero,
4712 *if it's not the last then OR in the variable */
4714 emitpcode(POC_IORFW, popGet(AOP(right),size));
4719 emitpLabel(lbl->key);
4721 rFalseIfx.condition ^= 1;
4722 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4726 emitpLabel(truelbl->key);
4727 if(ifx) ifx->generated = 1;
4731 /* Compare two variables */
4733 DEBUGpic14_emitcode(";sign","%d",sign);
4737 /* Sigh. thus sucks... */
4739 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4740 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4741 emitpcode(POC_MOVLW, popGetLit(0x80));
4742 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4743 emitpcode(POC_XORFW, popGet(AOP(right),size));
4744 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4746 /* Signed char comparison */
4747 /* Special thanks to Nikolai Golovchenko for this snippet */
4748 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4749 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4750 emitpcode(POC_RRFW, popGet(AOP(left),0)); /* could be any register */
4751 emitpcode(POC_XORFW, popGet(AOP(left),0));
4752 emitpcode(POC_XORFW, popGet(AOP(right),0));
4753 emitpcode(POC_ADDLW, popGetLit(0x80));
4755 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4756 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4758 if(ifx) ifx->generated = 1;
4764 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4765 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4769 /* The rest of the bytes of a multi-byte compare */
4773 emitpcode(POC_GOTO, popGetLabel(lbl->key));
4776 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4777 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4782 emitpLabel(lbl->key);
4784 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4785 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
4786 (AOP_TYPE(result) == AOP_REG)) {
4787 emitpcode(POC_CLRF, popGet(AOP(result),0));
4788 emitpcode(POC_RLF, popGet(AOP(result),0));
4790 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4792 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4793 if(ifx) ifx->generated = 1;
4800 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4801 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4802 pic14_outBitC(result);
4804 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4805 /* if the result is used in the next
4806 ifx conditional branch then generate
4807 code a little differently */
4809 genIfxJump (ifx,"c");
4811 pic14_outBitC(result);
4812 /* leave the result in acc */
4818 /*-----------------------------------------------------------------*/
4819 /* genCmpGt :- greater than comparison */
4820 /*-----------------------------------------------------------------*/
4821 static void genCmpGt (iCode *ic, iCode *ifx)
4823 operand *left, *right, *result;
4824 sym_link *letype , *retype;
4828 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4830 right= IC_RIGHT(ic);
4831 result = IC_RESULT(ic);
4833 letype = getSpec(operandType(left));
4834 retype =getSpec(operandType(right));
4835 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4836 /* assign the amsops */
4837 aopOp (left,ic,FALSE);
4838 aopOp (right,ic,FALSE);
4839 aopOp (result,ic,TRUE);
4841 genCmp(right, left, result, ifx, sign);
4843 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4844 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4845 freeAsmop(result,NULL,ic,TRUE);
4848 /*-----------------------------------------------------------------*/
4849 /* genCmpLt - less than comparisons */
4850 /*-----------------------------------------------------------------*/
4851 static void genCmpLt (iCode *ic, iCode *ifx)
4853 operand *left, *right, *result;
4854 sym_link *letype , *retype;
4858 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4860 right= IC_RIGHT(ic);
4861 result = IC_RESULT(ic);
4863 letype = getSpec(operandType(left));
4864 retype =getSpec(operandType(right));
4865 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4867 /* assign the amsops */
4868 aopOp (left,ic,FALSE);
4869 aopOp (right,ic,FALSE);
4870 aopOp (result,ic,TRUE);
4872 genCmp(left, right, result, ifx, sign);
4874 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4875 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4876 freeAsmop(result,NULL,ic,TRUE);
4880 /*-----------------------------------------------------------------*/
4881 /* genc16bit2lit - compare a 16 bit value to a literal */
4882 /*-----------------------------------------------------------------*/
4883 static void genc16bit2lit(operand *op, int lit, int offset)
4888 DEBUGpic14_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
4889 if( (lit&0xff) == 0)
4894 switch( BYTEofLONG(lit,i)) {
4896 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4899 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4902 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4905 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4906 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4911 switch( BYTEofLONG(lit,i)) {
4913 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4917 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4921 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4924 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4926 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4934 /*-----------------------------------------------------------------*/
4935 /* gencjneshort - compare and jump if not equal */
4936 /*-----------------------------------------------------------------*/
4937 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4939 int size = min(AOP_SIZE(left),AOP_SIZE(right));
4944 //unsigned long lit = 0L;
4946 if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4947 emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4950 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4951 DEBUGpic14_AopType(__LINE__,left,right,result);
4953 assert (!pic14_sameRegs (AOP(left), AOP(result)));
4954 assert (!pic14_sameRegs (AOP(right), AOP(result)));
4955 if (AOP_SIZE(result)) {
4956 for (offset = 0; offset < AOP_SIZE(result); offset++)
4957 emitpcode (POC_CLRF, popGet (AOP(result), offset));
4960 assert (AOP_SIZE(left) == AOP_SIZE(right));
4961 //resolveIfx(&rIfx,ifx);
4962 lbl = newiTempLabel (NULL);
4965 mov2w (AOP(right),size);
4966 emitpcode (POC_XORFW, popGet (AOP(left), size));
4970 emitpcode (POC_GOTO, popGetLabel (lbl->key));
4973 emitpLabel (lbl->key);
4974 if (AOP_SIZE(result)) {
4976 emitpcode (POC_INCF, popGet (AOP(result), 0));
4979 genSkipz (ifx, NULL != IC_TRUE(ifx));
4986 DEBUGpic14_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
4987 assert (!pic14_sameRegs (AOP(result), AOP(left)));
4988 assert (!pic14_sameRegs (AOP(result), AOP(right)));
4989 for (offset=0; offset < AOP_SIZE(result); offset++)
4991 emitpcode (POC_CLRF, popGet (AOP(result), offset));
4996 /* if the left side is a literal or
4997 if the right is in a pointer register and left
4999 if ((AOP_TYPE(left) == AOP_LIT) ||
5000 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5005 if(AOP_TYPE(right) == AOP_LIT)
5006 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5008 /* if the right side is a literal then anything goes */
5009 if (AOP_TYPE(right) == AOP_LIT &&
5010 AOP_TYPE(left) != AOP_DIR ) {
5013 genc16bit2lit(left, lit, 0);
5015 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5021 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5022 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5024 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5028 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5036 /* if the right side is in a register or in direct space or
5037 if the left is a pointer register & right is not */
5038 else if (AOP_TYPE(right) == AOP_REG ||
5039 AOP_TYPE(right) == AOP_DIR ||
5040 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5041 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5042 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5043 int lbl_key = lbl->key;
5046 DEBUGpic14_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
5047 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
5048 __FUNCTION__,__LINE__);
5052 /* switch(size) { */
5054 /* genc16bit2lit(left, lit, 0); */
5056 /* emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
5062 if((AOP_TYPE(left) == AOP_DIR) &&
5063 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5065 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5066 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5068 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5070 switch (lit & 0xff) {
5072 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5075 emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
5076 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5077 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5081 emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5082 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5083 //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5084 emitpcode(POC_GOTO,popGetLabel(lbl_key));
5088 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5089 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5094 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5097 if(AOP_TYPE(result) == AOP_CRY) {
5098 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5103 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5105 /* fix me. probably need to check result size too */
5106 //emitpcode(POC_CLRF,popGet(AOP(result),0));
5111 emitpcode(POC_GOTO,popGetLabel(lbl_key));
5121 } else if(AOP_TYPE(right) == AOP_REG &&
5122 AOP_TYPE(left) != AOP_DIR){
5126 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5127 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5128 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5133 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5138 /* right is a pointer reg need both a & b */
5141 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5143 pic14_emitcode("mov","b,%s",l);
5144 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5145 pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
5150 emitpcode(POC_INCF,popGet(AOP(result),0));
5152 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5154 emitpLabel(lbl->key);
5156 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5165 /*-----------------------------------------------------------------*/
5166 /* gencjne - compare and jump if not equal */
5167 /*-----------------------------------------------------------------*/
5168 static void gencjne(operand *left, operand *right, iCode *ifx)
5170 symbol *tlbl = newiTempLabel(NULL);
5172 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5173 gencjneshort(left, right, lbl);
5175 pic14_emitcode("mov","a,%s",one);
5176 pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5177 pic14_emitcode("","%05d_DS_:",lbl->key+100);
5178 pic14_emitcode("clr","a");
5179 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5181 emitpLabel(lbl->key);
5182 emitpLabel(tlbl->key);
5187 /*-----------------------------------------------------------------*/
5188 /* genCmpEq - generates code for equal to */
5189 /*-----------------------------------------------------------------*/
5190 static void genCmpEq (iCode *ic, iCode *ifx)
5192 operand *left, *right, *result;
5194 symbol *false_label;
5197 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5200 DEBUGpic14_emitcode ("; ifx is non-null","");
5202 DEBUGpic14_emitcode ("; ifx is null","");
5204 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5205 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5206 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5208 DEBUGpic14_AopType(__LINE__,left,right,result);
5210 /* if literal, move literal to right */
5211 if (op_isLitLike (IC_LEFT(ic))) {
5212 operand *tmp = right ;
5218 if (ifx && !IC_TRUE(ifx))
5220 assert (IC_FALSE(ifx));
5221 false_label = IC_FALSE(ifx);
5224 size = min(AOP_SIZE(left),AOP_SIZE(right));
5225 assert(!pic14_sameRegs(AOP(result),AOP(left)));
5226 assert(!pic14_sameRegs(AOP(result),AOP(right)));
5228 /* assume left != right */
5231 for (i=0; i < AOP_SIZE(result); i++)
5233 emitpcode(POC_CLRF, popGet(AOP(result),i));
5237 if (AOP_TYPE(right) == AOP_LIT)
5239 unsigned long lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
5241 size = AOP_SIZE(left);
5242 assert(!op_isLitLike(left));
5247 mov2w(AOP(left), 0);
5248 for (i=1; i < size; i++)
5249 emitpcode(POC_IORFW,popGet(AOP(left),i));
5250 /* now Z is set iff `left == right' */
5252 if (!false_label) false_label = newiTempLabel(NULL);
5253 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5257 for (i=0; i < size; i++)
5260 emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
5261 /* now Z is cleared if `left != right' */
5263 if (!false_label) false_label = newiTempLabel(NULL);
5264 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5271 /* right is no literal */
5274 for (i=0; i < size; i++)
5276 mov2w(AOP(right),i);
5277 emitpcode(POC_XORFW,popGet(AOP(left),i));
5278 /* now Z is cleared if `left != right' */
5280 if (!false_label) false_label = newiTempLabel(NULL);
5281 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5285 /* if we reach here, left == right */
5287 if (AOP_SIZE(result) > 0)
5289 emitpcode(POC_INCF, popGet(AOP(result),0));
5292 if (ifx && IC_TRUE(ifx))
5294 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5297 if (false_label && (!ifx || IC_TRUE(ifx)))
5298 emitpLabel(false_label->key);
5300 if (ifx) ifx->generated = 1;
5302 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5303 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5304 freeAsmop(result,NULL,ic,TRUE);
5307 /*-----------------------------------------------------------------*/
5308 /* ifxForOp - returns the icode containing the ifx for operand */
5309 /*-----------------------------------------------------------------*/
5310 static iCode *ifxForOp ( operand *op, iCode *ic )
5313 /* if true symbol then needs to be assigned */
5314 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5315 if (IS_TRUE_SYMOP(op))
5318 /* if this has register type condition and
5319 the next instruction is ifx with the same operand
5320 and live to of the operand is upto the ifx only then */
5322 ic->next->op == IFX &&
5323 IC_COND(ic->next)->key == op->key &&
5324 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5328 ic->next->op == IFX &&
5329 IC_COND(ic->next)->key == op->key) {
5330 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5334 DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5336 ic->next->op == IFX)
5337 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5340 ic->next->op == IFX &&
5341 IC_COND(ic->next)->key == op->key) {
5342 DEBUGpic14_emitcode ("; "," key is okay");
5343 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5344 OP_SYMBOL(op)->liveTo,
5351 /*-----------------------------------------------------------------*/
5352 /* genAndOp - for && operation */
5353 /*-----------------------------------------------------------------*/
5354 static void genAndOp (iCode *ic)
5356 operand *left,*right, *result;
5360 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5361 /* note here that && operations that are in an
5362 if statement are taken away by backPatchLabels
5363 only those used in arthmetic operations remain */
5364 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5365 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5366 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5368 DEBUGpic14_AopType(__LINE__,left,right,result);
5370 emitpcode(POC_MOVFW,popGet(AOP(left),0));
5371 emitpcode(POC_ANDFW,popGet(AOP(right),0));
5372 emitpcode(POC_MOVWF,popGet(AOP(result),0));
5374 /* if both are bit variables */
5375 /* if (AOP_TYPE(left) == AOP_CRY && */
5376 /* AOP_TYPE(right) == AOP_CRY ) { */
5377 /* pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5378 /* pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5379 /* pic14_outBitC(result); */
5381 /* tlbl = newiTempLabel(NULL); */
5382 /* pic14_toBoolean(left); */
5383 /* pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5384 /* pic14_toBoolean(right); */
5385 /* pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5386 /* pic14_outBitAcc(result); */
5389 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5390 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5391 freeAsmop(result,NULL,ic,TRUE);
5395 /*-----------------------------------------------------------------*/
5396 /* genOrOp - for || operation */
5397 /*-----------------------------------------------------------------*/
5400 modified this code, but it doesn't appear to ever get called
5403 static void genOrOp (iCode *ic)
5405 operand *left,*right, *result;
5409 /* note here that || operations that are in an
5410 if statement are taken away by backPatchLabels
5411 only those used in arthmetic operations remain */
5413 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5414 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5415 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5416 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5418 DEBUGpic14_AopType(__LINE__,left,right,result);
5420 for (i=0; i < AOP_SIZE(result); i++)
5422 emitpcode(POC_CLRF, popGet(AOP(result), i));
5425 tlbl = newiTempLabel(NULL);
5426 pic14_toBoolean(left);
5428 emitpcode(POC_GOTO, popGetLabel(tlbl->key));
5429 pic14_toBoolean(right);
5430 emitpLabel(tlbl->key);
5431 /* here Z is clear IFF `left || right' */
5433 emitpcode(POC_INCF, popGet(AOP(result), 0));
5435 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5436 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5437 freeAsmop(result,NULL,ic,TRUE);
5440 /*-----------------------------------------------------------------*/
5441 /* isLiteralBit - test if lit == 2^n */
5442 /*-----------------------------------------------------------------*/
5443 static int isLiteralBit(unsigned long lit)
5445 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5446 0x100L,0x200L,0x400L,0x800L,
5447 0x1000L,0x2000L,0x4000L,0x8000L,
5448 0x10000L,0x20000L,0x40000L,0x80000L,
5449 0x100000L,0x200000L,0x400000L,0x800000L,
5450 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5451 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5455 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5456 for(idx = 0; idx < 32; idx++)
5462 /*-----------------------------------------------------------------*/
5463 /* continueIfTrue - */
5464 /*-----------------------------------------------------------------*/
5465 static void continueIfTrue (iCode *ic)
5468 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5470 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5474 /*-----------------------------------------------------------------*/
5476 /*-----------------------------------------------------------------*/
5477 static void jumpIfTrue (iCode *ic)
5480 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5482 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5486 /*-----------------------------------------------------------------*/
5487 /* jmpTrueOrFalse - */
5488 /*-----------------------------------------------------------------*/
5489 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5492 // ugly but optimized by peephole
5493 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5495 symbol *nlbl = newiTempLabel(NULL);
5496 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5497 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5498 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5499 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5502 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5503 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5508 /*-----------------------------------------------------------------*/
5509 /* genAnd - code for and */
5510 /*-----------------------------------------------------------------*/
5511 static void genAnd (iCode *ic, iCode *ifx)
5513 operand *left, *right, *result;
5515 unsigned long lit = 0L;
5520 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5521 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5522 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5523 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5525 resolveIfx(&rIfx,ifx);
5527 /* if left is a literal & right is not then exchange them */
5528 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5529 AOP_NEEDSACC(left)) {
5530 operand *tmp = right ;
5535 /* if result = right then exchange them */
5536 if(pic14_sameRegs(AOP(result),AOP(right))){
5537 operand *tmp = right ;
5542 /* if right is bit then exchange them */
5543 if (AOP_TYPE(right) == AOP_CRY &&
5544 AOP_TYPE(left) != AOP_CRY){
5545 operand *tmp = right ;
5549 if(AOP_TYPE(right) == AOP_LIT)
5550 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5552 size = AOP_SIZE(result);
5554 DEBUGpic14_AopType(__LINE__,left,right,result);
5557 // result = bit & yy;
5558 if (AOP_TYPE(left) == AOP_CRY){
5559 // c = bit & literal;
5560 if(AOP_TYPE(right) == AOP_LIT){
5562 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5565 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5568 if(size && (AOP_TYPE(result) == AOP_CRY)){
5569 pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5572 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5576 pic14_emitcode("clr","c");
5579 if (AOP_TYPE(right) == AOP_CRY){
5581 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5582 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5585 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5587 pic14_emitcode("rrc","a");
5588 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5594 pic14_outBitC(result);
5596 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5597 genIfxJump(ifx, "c");
5601 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5602 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5603 if((AOP_TYPE(right) == AOP_LIT) &&
5604 (AOP_TYPE(result) == AOP_CRY) &&
5605 (AOP_TYPE(left) != AOP_CRY)){
5606 int posbit = isLiteralBit(lit);
5610 //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5613 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5618 while (posbit > 7) {
5622 emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5623 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5624 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5631 symbol *tlbl = newiTempLabel(NULL);
5632 int sizel = AOP_SIZE(left);
5634 pic14_emitcode("setb","c");
5636 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5637 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5639 if((posbit = isLiteralBit(bytelit)) != 0)
5640 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5642 if(bytelit != 0x0FFL)
5643 pic14_emitcode("anl","a,%s",
5644 aopGet(AOP(right),offset,FALSE,TRUE));
5645 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5650 // bit = left & literal
5652 pic14_emitcode("clr","c");
5653 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5655 // if(left & literal)
5658 jmpTrueOrFalse(ifx, tlbl);
5662 pic14_outBitC(result);
5666 /* if left is same as result */
5667 if(pic14_sameRegs(AOP(result),AOP(left))){
5669 for(;size--; offset++,lit>>=8) {
5670 if(AOP_TYPE(right) == AOP_LIT){
5671 switch(lit & 0xff) {
5673 /* and'ing with 0 has clears the result */
5674 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5677 /* and'ing with 0xff is a nop when the result and left are the same */
5682 int p = my_powof2( (~lit) & 0xff );
5684 /* only one bit is set in the literal, so use a bcf instruction */
5685 emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5688 if(know_W != (int)(lit&0xff))
5689 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5691 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5696 if (AOP_TYPE(left) == AOP_ACC) {
5697 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5699 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5700 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5707 // left & result in different registers
5708 if(AOP_TYPE(result) == AOP_CRY){
5710 // if(size), result in bit
5711 // if(!size && ifx), conditional oper: if(left & right)
5712 symbol *tlbl = newiTempLabel(NULL);
5713 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5715 pic14_emitcode("setb","c");
5717 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5718 pic14_emitcode("anl","a,%s",
5719 aopGet(AOP(left),offset,FALSE,FALSE));
5720 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5725 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5726 pic14_outBitC(result);
5728 jmpTrueOrFalse(ifx, tlbl);
5730 for(;(size--);offset++) {
5732 // result = left & right
5733 if(AOP_TYPE(right) == AOP_LIT){
5734 int t = (lit >> (offset*8)) & 0x0FFL;
5737 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5740 if(AOP_TYPE(left) != AOP_ACC) {
5741 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5743 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5746 if(AOP_TYPE(left) == AOP_ACC) {
5747 emitpcode(POC_ANDLW, popGetLit(t));
5749 emitpcode(POC_MOVLW, popGetLit(t));
5750 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5752 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5757 if (AOP_TYPE(left) == AOP_ACC) {
5758 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5760 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5761 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5763 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5769 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5770 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5771 freeAsmop(result,NULL,ic,TRUE);
5774 /*-----------------------------------------------------------------*/
5775 /* genOr - code for or */
5776 /*-----------------------------------------------------------------*/
5777 static void genOr (iCode *ic, iCode *ifx)
5779 operand *left, *right, *result;
5781 unsigned long lit = 0L;
5784 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5786 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5787 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5788 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5790 DEBUGpic14_AopType(__LINE__,left,right,result);
5792 /* if left is a literal & right is not then exchange them */
5793 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5794 AOP_NEEDSACC(left)) {
5795 operand *tmp = right ;
5800 /* if result = right then exchange them */
5801 if(pic14_sameRegs(AOP(result),AOP(right))){
5802 operand *tmp = right ;
5807 /* if right is bit then exchange them */
5808 if (AOP_TYPE(right) == AOP_CRY &&
5809 AOP_TYPE(left) != AOP_CRY){
5810 operand *tmp = right ;
5815 DEBUGpic14_AopType(__LINE__,left,right,result);
5817 if(AOP_TYPE(right) == AOP_LIT)
5818 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5820 size = AOP_SIZE(result);
5824 if (AOP_TYPE(left) == AOP_CRY){
5825 if(AOP_TYPE(right) == AOP_LIT){
5826 // c = bit & literal;
5828 // lit != 0 => result = 1
5829 if(AOP_TYPE(result) == AOP_CRY){
5831 emitpcode(POC_BSF, popGet(AOP(result),0));
5832 //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5833 // AOP(result)->aopu.aop_dir,
5834 // AOP(result)->aopu.aop_dir);
5836 continueIfTrue(ifx);
5840 // lit == 0 => result = left
5841 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5843 pic14_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5846 if (AOP_TYPE(right) == AOP_CRY){
5847 if(pic14_sameRegs(AOP(result),AOP(left))){
5849 emitpcode(POC_BCF, popGet(AOP(result),0));
5850 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5851 emitpcode(POC_BSF, popGet(AOP(result),0));
5853 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5854 AOP(result)->aopu.aop_dir,
5855 AOP(result)->aopu.aop_dir);
5856 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5857 AOP(right)->aopu.aop_dir,
5858 AOP(right)->aopu.aop_dir);
5859 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5860 AOP(result)->aopu.aop_dir,
5861 AOP(result)->aopu.aop_dir);
5863 if( AOP_TYPE(result) == AOP_ACC) {
5864 emitpcode(POC_MOVLW, popGetLit(0));
5865 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5866 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5867 emitpcode(POC_MOVLW, popGetLit(1));
5871 emitpcode(POC_BCF, popGet(AOP(result),0));
5872 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5873 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5874 emitpcode(POC_BSF, popGet(AOP(result),0));
5876 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5877 AOP(result)->aopu.aop_dir,
5878 AOP(result)->aopu.aop_dir);
5879 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5880 AOP(right)->aopu.aop_dir,
5881 AOP(right)->aopu.aop_dir);
5882 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5883 AOP(left)->aopu.aop_dir,
5884 AOP(left)->aopu.aop_dir);
5885 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5886 AOP(result)->aopu.aop_dir,
5887 AOP(result)->aopu.aop_dir);
5892 symbol *tlbl = newiTempLabel(NULL);
5893 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5896 emitpcode(POC_BCF, popGet(AOP(result),0));
5897 if( AOP_TYPE(right) == AOP_ACC) {
5898 emitpcode(POC_IORLW, popGetLit(0));
5900 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5901 emitpcode(POC_BSF, popGet(AOP(result),0));
5906 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5907 pic14_emitcode(";XXX setb","c");
5908 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5909 AOP(left)->aopu.aop_dir,tlbl->key+100);
5910 pic14_toBoolean(right);
5911 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5912 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5913 jmpTrueOrFalse(ifx, tlbl);
5917 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5924 pic14_outBitC(result);
5926 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5927 genIfxJump(ifx, "c");
5931 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5932 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5933 if((AOP_TYPE(right) == AOP_LIT) &&
5934 (AOP_TYPE(result) == AOP_CRY) &&
5935 (AOP_TYPE(left) != AOP_CRY)){
5937 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5940 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5942 continueIfTrue(ifx);
5945 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5946 // lit = 0, result = boolean(left)
5948 pic14_emitcode(";XXX setb","c");
5949 pic14_toBoolean(right);
5951 symbol *tlbl = newiTempLabel(NULL);
5952 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5954 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5956 genIfxJump (ifx,"a");
5960 pic14_outBitC(result);
5964 /* if left is same as result */
5965 if(pic14_sameRegs(AOP(result),AOP(left))){
5967 for(;size--; offset++,lit>>=8) {
5968 if(AOP_TYPE(right) == AOP_LIT){
5969 if((lit & 0xff) == 0)
5970 /* or'ing with 0 has no effect */
5973 int p = my_powof2(lit & 0xff);
5975 /* only one bit is set in the literal, so use a bsf instruction */
5977 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5979 if(know_W != (int)(lit & 0xff))
5980 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5981 know_W = lit & 0xff;
5982 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5987 if (AOP_TYPE(left) == AOP_ACC) {
5988 emitpcode(POC_IORFW, popGet(AOP(right),offset));
5989 pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5991 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
5992 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5994 pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5995 pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
6001 // left & result in different registers
6002 if(AOP_TYPE(result) == AOP_CRY){
6004 // if(size), result in bit
6005 // if(!size && ifx), conditional oper: if(left | right)
6006 symbol *tlbl = newiTempLabel(NULL);
6007 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6008 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6012 pic14_emitcode(";XXX setb","c");
6014 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6015 pic14_emitcode(";XXX orl","a,%s",
6016 aopGet(AOP(left),offset,FALSE,FALSE));
6017 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6022 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6023 pic14_outBitC(result);
6025 jmpTrueOrFalse(ifx, tlbl);
6026 } else for(;(size--);offset++){
6028 // result = left | right
6029 if(AOP_TYPE(right) == AOP_LIT){
6030 int t = (lit >> (offset*8)) & 0x0FFL;
6033 if (AOP_TYPE(left) != AOP_ACC) {
6034 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
6036 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6040 if (AOP_TYPE(left) == AOP_ACC) {
6041 emitpcode(POC_IORLW, popGetLit(t));
6043 emitpcode(POC_MOVLW, popGetLit(t));
6044 emitpcode(POC_IORFW, popGet(AOP(left),offset));
6046 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6051 // faster than result <- left, anl result,right
6052 // and better if result is SFR
6053 if (AOP_TYPE(left) == AOP_ACC) {
6054 emitpcode(POC_IORFW,popGet(AOP(right),offset));
6056 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6057 emitpcode(POC_IORFW,popGet(AOP(left),offset));
6059 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6064 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6065 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6066 freeAsmop(result,NULL,ic,TRUE);
6069 /*-----------------------------------------------------------------*/
6070 /* genXor - code for xclusive or */
6071 /*-----------------------------------------------------------------*/
6072 static void genXor (iCode *ic, iCode *ifx)
6074 operand *left, *right, *result;
6076 unsigned long lit = 0L;
6079 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6081 aopOp((left = IC_LEFT(ic)),ic,FALSE);
6082 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6083 aopOp((result=IC_RESULT(ic)),ic,TRUE);
6085 /* if left is a literal & right is not ||
6086 if left needs acc & right does not */
6087 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6088 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6089 operand *tmp = right ;
6094 /* if result = right then exchange them */
6095 if(pic14_sameRegs(AOP(result),AOP(right))){
6096 operand *tmp = right ;
6101 /* if right is bit then exchange them */
6102 if (AOP_TYPE(right) == AOP_CRY &&
6103 AOP_TYPE(left) != AOP_CRY){
6104 operand *tmp = right ;
6108 if(AOP_TYPE(right) == AOP_LIT)
6109 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6111 size = AOP_SIZE(result);
6115 if (AOP_TYPE(left) == AOP_CRY){
6116 if(AOP_TYPE(right) == AOP_LIT){
6117 // c = bit & literal;
6119 // lit>>1 != 0 => result = 1
6120 if(AOP_TYPE(result) == AOP_CRY){
6122 {emitpcode(POC_BSF, popGet(AOP(result),offset));
6123 pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6125 continueIfTrue(ifx);
6128 pic14_emitcode("setb","c");
6132 // lit == 0, result = left
6133 if(size && pic14_sameRegs(AOP(result),AOP(left)))
6135 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6137 // lit == 1, result = not(left)
6138 if(size && pic14_sameRegs(AOP(result),AOP(left))){
6139 emitpcode(POC_MOVLW, popGet(AOP(result),offset));
6140 emitpcode(POC_XORWF, popGet(AOP(result),offset));
6141 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6144 assert ( !"incomplete genXor" );
6145 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6146 pic14_emitcode("cpl","c");
6153 symbol *tlbl = newiTempLabel(NULL);
6154 if (AOP_TYPE(right) == AOP_CRY){
6156 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6159 int sizer = AOP_SIZE(right);
6161 // if val>>1 != 0, result = 1
6162 pic14_emitcode("setb","c");
6164 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6166 // test the msb of the lsb
6167 pic14_emitcode("anl","a,#0xfe");
6168 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6172 pic14_emitcode("rrc","a");
6174 pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6175 pic14_emitcode("cpl","c");
6176 pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6181 pic14_outBitC(result);
6183 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6184 genIfxJump(ifx, "c");
6188 if(pic14_sameRegs(AOP(result),AOP(left))){
6189 /* if left is same as result */
6190 for(;size--; offset++) {
6191 if(AOP_TYPE(right) == AOP_LIT){
6192 int t = (lit >> (offset*8)) & 0x0FFL;
6196 if (IS_AOP_PREG(left)) {
6197 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6198 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6199 aopPut(AOP(result),"a",offset);
6201 emitpcode(POC_MOVLW, popGetLit(t));
6202 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6203 pic14_emitcode("xrl","%s,%s",
6204 aopGet(AOP(left),offset,FALSE,TRUE),
6205 aopGet(AOP(right),offset,FALSE,FALSE));
6208 if (AOP_TYPE(left) == AOP_ACC)
6209 pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6211 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6212 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6214 if (IS_AOP_PREG(left)) {
6215 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6216 aopPut(AOP(result),"a",offset);
6218 pic14_emitcode("xrl","%s,a",
6219 aopGet(AOP(left),offset,FALSE,TRUE));
6225 // left & result in different registers
6226 if(AOP_TYPE(result) == AOP_CRY){
6228 // if(size), result in bit
6229 // if(!size && ifx), conditional oper: if(left ^ right)
6230 symbol *tlbl = newiTempLabel(NULL);
6231 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6233 pic14_emitcode("setb","c");
6235 if((AOP_TYPE(right) == AOP_LIT) &&
6236 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6237 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6239 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6240 pic14_emitcode("xrl","a,%s",
6241 aopGet(AOP(left),offset,FALSE,FALSE));
6243 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6248 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6249 pic14_outBitC(result);
6251 jmpTrueOrFalse(ifx, tlbl);
6252 } else for(;(size--);offset++){
6254 // result = left & right
6255 if(AOP_TYPE(right) == AOP_LIT){
6256 int t = (lit >> (offset*8)) & 0x0FFL;
6259 if (AOP_TYPE(left) != AOP_ACC) {
6260 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6262 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6263 pic14_emitcode("movf","%s,w",
6264 aopGet(AOP(left),offset,FALSE,FALSE));
6265 pic14_emitcode("movwf","%s",
6266 aopGet(AOP(result),offset,FALSE,FALSE));
6269 if (AOP_TYPE(left) == AOP_ACC) {
6270 emitpcode(POC_XORLW, popGetLit(t));
6272 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6274 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6277 if (AOP_TYPE(left) == AOP_ACC) {
6278 emitpcode(POC_XORLW, popGetLit(t));
6280 emitpcode(POC_MOVLW, popGetLit(t));
6281 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6283 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6284 pic14_emitcode("movlw","0x%x",t);
6285 pic14_emitcode("xorwf","%s,w",
6286 aopGet(AOP(left),offset,FALSE,FALSE));
6287 pic14_emitcode("movwf","%s",
6288 aopGet(AOP(result),offset,FALSE,FALSE));
6294 // faster than result <- left, anl result,right
6295 // and better if result is SFR
6296 if (AOP_TYPE(left) == AOP_ACC) {
6297 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6299 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6300 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6302 if ( AOP_TYPE(result) != AOP_ACC){
6303 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6309 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6310 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6311 freeAsmop(result,NULL,ic,TRUE);
6314 /*-----------------------------------------------------------------*/
6315 /* genInline - write the inline code out */
6316 /*-----------------------------------------------------------------*/
6317 static void genInline (iCode *ic)
6319 char *buffer, *bp, *bp1;
6322 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6324 _G.inLine += (!options.asmpeep);
6326 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6327 strcpy(buffer,IC_INLINE(ic));
6329 /* emit each line as a code */
6335 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6343 /* print label, use this special format with NULL directive
6344 * to denote that the argument should not be indented with tab */
6345 addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6352 if ((bp1 != bp) && *bp1)
6353 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6357 _G.inLine -= (!options.asmpeep);
6360 /*-----------------------------------------------------------------*/
6361 /* genRRC - rotate right with carry */
6362 /*-----------------------------------------------------------------*/
6363 static void genRRC (iCode *ic)
6365 operand *left , *result ;
6366 int size, offset = 0, same;
6369 /* rotate right with carry */
6371 result=IC_RESULT(ic);
6372 aopOp (left,ic,FALSE);
6373 aopOp (result,ic,FALSE);
6375 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6377 same = pic14_sameRegs(AOP(result),AOP(left));
6379 size = AOP_SIZE(result);
6381 /* get the lsb and put it into the carry */
6382 emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6389 emitpcode(POC_RRF, popGet(AOP(left),offset));
6391 emitpcode(POC_RRFW, popGet(AOP(left),offset));
6392 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6398 freeAsmop(left,NULL,ic,TRUE);
6399 freeAsmop(result,NULL,ic,TRUE);
6402 /*-----------------------------------------------------------------*/
6403 /* genRLC - generate code for rotate left with carry */
6404 /*-----------------------------------------------------------------*/
6405 static void genRLC (iCode *ic)
6407 operand *left , *result ;
6408 int size, offset = 0;
6412 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6413 /* rotate right with carry */
6415 result=IC_RESULT(ic);
6416 aopOp (left,ic,FALSE);
6417 aopOp (result,ic,FALSE);
6419 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6421 same = pic14_sameRegs(AOP(result),AOP(left));
6423 /* move it to the result */
6424 size = AOP_SIZE(result);
6426 /* get the msb and put it into the carry */
6427 emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6434 emitpcode(POC_RLF, popGet(AOP(left),offset));
6436 emitpcode(POC_RLFW, popGet(AOP(left),offset));
6437 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6444 freeAsmop(left,NULL,ic,TRUE);
6445 freeAsmop(result,NULL,ic,TRUE);
6448 /*-----------------------------------------------------------------*/
6449 /* genGetHbit - generates code get highest order bit */
6450 /*-----------------------------------------------------------------*/
6451 static void genGetHbit (iCode *ic)
6453 operand *left, *result;
6455 result=IC_RESULT(ic);
6456 aopOp (left,ic,FALSE);
6457 aopOp (result,ic,FALSE);
6460 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6461 /* get the highest order byte into a */
6462 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6463 if(AOP_TYPE(result) == AOP_CRY){
6464 pic14_emitcode("rlc","a");
6465 pic14_outBitC(result);
6468 pic14_emitcode("rl","a");
6469 pic14_emitcode("anl","a,#0x01");
6470 pic14_outAcc(result);
6474 freeAsmop(left,NULL,ic,TRUE);
6475 freeAsmop(result,NULL,ic,TRUE);
6478 /*-----------------------------------------------------------------*/
6479 /* AccLsh - shift left accumulator by known count */
6480 /* MARK: pic14 always rotates through CARRY! */
6481 /*-----------------------------------------------------------------*/
6482 static void AccLsh (pCodeOp *pcop,int shCount)
6485 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6486 shCount &= 0x0007; // shCount : 0..7
6493 emitpcode(POC_RLF,pcop);
6497 emitpcode(POC_RLF,pcop);
6498 emitpcode(POC_RLF,pcop);
6501 emitpcode(POC_RLF,pcop);
6502 emitpcode(POC_RLF,pcop);
6503 emitpcode(POC_RLF,pcop);
6506 emitpcode(POC_SWAPF,pcop);
6509 emitpcode(POC_SWAPF,pcop);
6510 emitpcode(POC_RLF,pcop);
6513 emitpcode(POC_SWAPF,pcop);
6514 emitpcode(POC_RLF,pcop);
6515 emitpcode(POC_RLF,pcop);
6518 emitpcode(POC_RRFW,pcop);
6519 emitpcode(POC_RRF,pcop);
6522 /* clear invalid bits */
6523 emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6524 emitpcode(POC_ANDWF, pcop);
6527 /*-----------------------------------------------------------------*/
6528 /* AccRsh - shift right accumulator by known count */
6529 /* MARK: pic14 always rotates through CARRY! */
6530 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6531 /* 1: mask out invalid bits (zero-extend) */
6532 /* 2: sign-extend result (pretty slow) */
6533 /*-----------------------------------------------------------------*/
6534 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6537 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6538 shCount &= 0x0007; // shCount : 0..7
6544 /* load sign if needed */
6545 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6546 else if (mask_mode == 1) emitCLRC;
6547 emitpcode(POC_RRF,pcop);
6551 /* load sign if needed */
6552 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6553 emitpcode(POC_RRF,pcop);
6554 /* load sign if needed */
6555 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6556 emitpcode(POC_RRF,pcop);
6557 if (mask_mode == 2) return;
6560 /* load sign if needed */
6561 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6562 emitpcode(POC_RRF,pcop);
6563 /* load sign if needed */
6564 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6565 emitpcode(POC_RRF,pcop);
6566 /* load sign if needed */
6567 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6568 emitpcode(POC_RRF,pcop);
6569 if (mask_mode == 2) return;
6572 emitpcode(POC_SWAPF,pcop);
6575 emitpcode(POC_SWAPF,pcop);
6576 emitpcode(POC_RRF,pcop);
6579 emitpcode(POC_SWAPF,pcop);
6580 emitpcode(POC_RRF,pcop);
6581 emitpcode(POC_RRF,pcop);
6587 emitpcode(POC_RLFW,pcop);
6588 emitpcode(POC_CLRF,pcop);
6590 emitpcode(POC_COMF,pcop);
6593 emitpcode(POC_RLFW,pcop);
6594 emitpcode(POC_RLF,pcop);
6601 /* leave invalid bits undefined */
6605 /* clear invalid bits -- zero-extend */
6606 emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6607 emitpcode(POC_ANDWF, pcop);
6609 if (mask_mode == 2) {
6611 emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6612 emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6613 emitpcode(POC_IORWF, pcop);
6618 /*-----------------------------------------------------------------*/
6619 /* AccSRsh - signed right shift accumulator by known count */
6620 /*-----------------------------------------------------------------*/
6621 static void AccSRsh (int shCount)
6624 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6627 pic14_emitcode("mov","c,acc.7");
6628 pic14_emitcode("rrc","a");
6629 } else if(shCount == 2){
6630 pic14_emitcode("mov","c,acc.7");
6631 pic14_emitcode("rrc","a");
6632 pic14_emitcode("mov","c,acc.7");
6633 pic14_emitcode("rrc","a");
6635 tlbl = newiTempLabel(NULL);
6636 /* rotate right accumulator */
6637 AccRol(8 - shCount);
6638 /* and kill the higher order bits */
6639 pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6640 pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6641 pic14_emitcode("orl","a,#0x%02x",
6642 (unsigned char)~SRMask[shCount]);
6643 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6648 /*-----------------------------------------------------------------*/
6649 /* shiftR1Left2Result - shift right one byte from left to result */
6650 /*-----------------------------------------------------------------*/
6651 static void shiftR1Left2ResultSigned (operand *left, int offl,
6652 operand *result, int offr,
6658 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6660 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6664 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6666 emitpcode(POC_RRF, popGet(AOP(result),offr));
6668 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6669 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6675 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6677 emitpcode(POC_RRF, popGet(AOP(result),offr));
6679 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6680 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6682 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6683 emitpcode(POC_RRF, popGet(AOP(result),offr));
6689 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6691 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6692 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6695 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6696 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6697 emitpcode(POC_ANDLW, popGetLit(0x1f));
6699 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6700 emitpcode(POC_IORLW, popGetLit(0xe0));
6702 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6706 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6707 emitpcode(POC_ANDLW, popGetLit(0x0f));
6708 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6709 emitpcode(POC_IORLW, popGetLit(0xf0));
6710 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6714 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6716 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6717 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6719 emitpcode(POC_RRFW, popGet(AOP(result),offr));
6720 emitpcode(POC_ANDLW, popGetLit(0x07));
6721 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6722 emitpcode(POC_IORLW, popGetLit(0xf8));
6723 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6728 emitpcode(POC_MOVLW, popGetLit(0x00));
6729 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6730 emitpcode(POC_MOVLW, popGetLit(0xfe));
6731 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6732 emitpcode(POC_IORLW, popGetLit(0x01));
6733 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6735 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6736 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6737 emitpcode(POC_DECF, popGet(AOP(result),offr));
6738 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6739 emitpcode(POC_BCF, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6745 emitpcode(POC_MOVLW, popGetLit(0x00));
6746 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6747 emitpcode(POC_MOVLW, popGetLit(0xff));
6748 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6750 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6751 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6752 emitpcode(POC_DECF, popGet(AOP(result),offr));
6760 /*-----------------------------------------------------------------*/
6761 /* shiftR1Left2Result - shift right one byte from left to result */
6762 /*-----------------------------------------------------------------*/
6763 static void shiftR1Left2Result (operand *left, int offl,
6764 operand *result, int offr,
6765 int shCount, int sign)
6770 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6772 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6774 /* Copy the msb into the carry if signed. */
6776 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6786 emitpcode(POC_RRF, popGet(AOP(result),offr));
6788 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6789 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6795 emitpcode(POC_RRF, popGet(AOP(result),offr));
6797 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6798 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6801 emitpcode(POC_RRF, popGet(AOP(result),offr));
6806 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6808 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6809 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6812 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6813 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6814 emitpcode(POC_ANDLW, popGetLit(0x1f));
6815 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6819 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6820 emitpcode(POC_ANDLW, popGetLit(0x0f));
6821 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6825 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6826 emitpcode(POC_ANDLW, popGetLit(0x0f));
6827 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6829 emitpcode(POC_RRF, popGet(AOP(result),offr));
6834 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6835 emitpcode(POC_ANDLW, popGetLit(0x80));
6836 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6837 emitpcode(POC_RLF, popGet(AOP(result),offr));
6838 emitpcode(POC_RLF, popGet(AOP(result),offr));
6843 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6844 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6845 emitpcode(POC_RLF, popGet(AOP(result),offr));
6854 /*-----------------------------------------------------------------*/
6855 /* shiftL1Left2Result - shift left one byte from left to result */
6856 /*-----------------------------------------------------------------*/
6857 static void shiftL1Left2Result (operand *left, int offl,
6858 operand *result, int offr, int shCount)
6864 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6866 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6867 DEBUGpic14_emitcode ("; ***","same = %d",same);
6868 // l = aopGet(AOP(left),offl,FALSE,FALSE);
6870 /* shift left accumulator */
6871 //AccLsh(shCount); // don't comment out just yet...
6872 // aopPut(AOP(result),"a",offr);
6876 /* Shift left 1 bit position */
6877 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6879 emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6881 emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6882 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6886 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6887 emitpcode(POC_ANDLW,popGetLit(0x7e));
6888 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6889 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6892 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6893 emitpcode(POC_ANDLW,popGetLit(0x3e));
6894 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6895 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6896 emitpcode(POC_RLF, popGet(AOP(result),offr));
6899 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6900 emitpcode(POC_ANDLW, popGetLit(0xf0));
6901 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6904 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6905 emitpcode(POC_ANDLW, popGetLit(0xf0));
6906 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6907 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6910 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6911 emitpcode(POC_ANDLW, popGetLit(0x30));
6912 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6913 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6914 emitpcode(POC_RLF, popGet(AOP(result),offr));
6917 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6918 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6919 emitpcode(POC_RRF, popGet(AOP(result),offr));
6923 DEBUGpic14_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6929 /*-----------------------------------------------------------------*/
6930 /* movLeft2Result - move byte from left to result */
6931 /*-----------------------------------------------------------------*/
6932 static void movLeft2Result (operand *left, int offl,
6933 operand *result, int offr)
6937 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6938 if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6939 l = aopGet(AOP(left),offl,FALSE,FALSE);
6941 if (*l == '@' && (IS_AOP_PREG(result))) {
6942 pic14_emitcode("mov","a,%s",l);
6943 aopPut(AOP(result),"a",offr);
6945 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6946 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6951 /*-----------------------------------------------------------------*/
6952 /* shiftLeft_Left2ResultLit - shift left by known count */
6953 /*-----------------------------------------------------------------*/
6955 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6957 int size, same, offr, i;
6959 size = AOP_SIZE(left);
6960 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6962 same = pic14_sameRegs (AOP(left), AOP(result));
6965 shCount = shCount & 0x07;
6971 case 0: /* takes 0 or 2N cycles (for offr==0) */
6972 if (!same || offr) {
6973 for (i=size-1; i >= 0; i--)
6974 movLeft2Result (left, i, result, offr + i);
6978 case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6980 shiftLeft_Left2ResultLit (left, result, 8 * offr);
6981 shiftLeft_Left2ResultLit (result, result, shCount);
6982 return; /* prevent clearing result again */
6985 for (i=0; i < size; i++) {
6986 if (same && !offr) {
6987 emitpcode (POC_RLF, popGet (AOP(left), i));
6989 emitpcode (POC_RLFW, popGet (AOP(left), i));
6990 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6996 case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
6997 /* works in-place/with offr as well */
6998 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
6999 emitpcode (POC_ANDLW, popGetLit (0xF0));
7000 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
7002 for (i = size - 2; i >= 0; i--)
7004 emitpcode (POC_SWAPFW, popGet (AOP(left), i));
7005 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7006 emitpcode (POC_ANDLW, popGetLit (0x0F));
7007 emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
7008 emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
7012 case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
7013 /* works in-place/with offr as well */
7014 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
7015 for (i = size-2; i >= 0; i--) {
7016 emitpcode (POC_RRFW, popGet (AOP(left), i));
7017 emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
7019 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7020 emitpcode (POC_RRF, popGet (AOP(result), offr));
7024 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
7025 shiftLeft_Left2ResultLit (result, result, 1);
7026 return; /* prevent clearing result again */
7032 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7036 /*-----------------------------------------------------------------*/
7037 /* shiftRight_Left2ResultLit - shift right by known count */
7038 /*-----------------------------------------------------------------*/
7040 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
7042 int size, same, offr, i;
7044 size = AOP_SIZE(left);
7045 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7047 same = pic14_sameRegs (AOP(left), AOP(result));
7050 shCount = shCount & 0x07;
7058 case 0: /* takes 0 or 2N cycles (for offr==0) */
7059 if (!same || offr) {
7060 for (i=0; i < size; i++)
7061 movLeft2Result (left, i + offr, result, i);
7065 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7066 emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7068 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7069 shiftRight_Left2ResultLit (result, result, shCount, sign);
7070 return; /* prevent sign-extending result again */
7074 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7077 for (i = size-1; i >= 0; i--) {
7078 if (same && !offr) {
7079 emitpcode (POC_RRF, popGet (AOP(left), i));
7081 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7082 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7088 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7089 /* works in-place/with offr as well */
7090 emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7091 emitpcode (POC_ANDLW, popGetLit (0x0F));
7092 emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7094 for (i = 1; i < size; i++)
7096 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7097 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7098 emitpcode (POC_ANDLW, popGetLit (0xF0));
7099 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7100 emitpcode (POC_XORWF, popGet (AOP(result), i));
7105 emitpcode (POC_MOVLW, popGetLit (0xF0));
7106 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7107 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7111 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7112 /* works in-place/with offr as well */
7113 emitpcode (POC_RLFW, popGet (AOP(left), offr));
7114 for (i = 0; i < size-1; i++) {
7115 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7116 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7118 emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7120 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7123 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7128 shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7129 shiftRight_Left2ResultLit (result, result, 1, sign);
7130 return; /* prevent sign extending result again */
7135 addSign (result, size, sign);
7139 /*-----------------------------------------------------------------*/
7140 /* shiftL2Left2Result - shift left two bytes from left to result */
7141 /*-----------------------------------------------------------------*/
7142 static void shiftL2Left2Result (operand *left, int offl,
7143 operand *result, int offr, int shCount)
7147 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7149 if(pic14_sameRegs(AOP(result), AOP(left))) {
7157 emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7158 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7159 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7163 emitpcode(POC_RLF, popGet(AOP(result),offr));
7164 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7170 emitpcode(POC_MOVLW, popGetLit(0x0f));
7171 emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7172 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7173 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7174 emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7175 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7176 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7178 emitpcode(POC_RLF, popGet(AOP(result),offr));
7179 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7183 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7184 emitpcode(POC_RRF, popGet(AOP(result),offr));
7185 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7186 emitpcode(POC_RRF, popGet(AOP(result),offr));
7187 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7188 emitpcode(POC_ANDLW,popGetLit(0xc0));
7189 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7190 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7191 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7192 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7195 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7196 emitpcode(POC_RRFW, popGet(AOP(result),offr));
7197 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7198 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7199 emitpcode(POC_RRF, popGet(AOP(result),offr));
7209 /* note, use a mov/add for the shift since the mov has a
7210 chance of getting optimized out */
7211 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7212 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7213 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7214 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7215 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7219 emitpcode(POC_RLF, popGet(AOP(result),offr));
7220 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7226 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7227 emitpcode(POC_ANDLW, popGetLit(0xF0));
7228 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7229 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7230 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7231 emitpcode(POC_ANDLW, popGetLit(0xF0));
7232 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7233 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7237 emitpcode(POC_RLF, popGet(AOP(result),offr));
7238 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7242 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7243 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7244 emitpcode(POC_RRFW, popGet(AOP(result),offl));
7245 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7247 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7248 emitpcode(POC_RRF, popGet(AOP(result),offr));
7249 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7250 emitpcode(POC_ANDLW,popGetLit(0xc0));
7251 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7252 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7253 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7254 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7257 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7258 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7259 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7260 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7261 emitpcode(POC_RRF, popGet(AOP(result),offr));
7267 /*-----------------------------------------------------------------*/
7268 /* shiftR2Left2Result - shift right two bytes from left to result */
7269 /*-----------------------------------------------------------------*/
7270 static void shiftR2Left2Result (operand *left, int offl,
7271 operand *result, int offr,
7272 int shCount, int sign)
7277 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7278 same = pic14_sameRegs(AOP(result), AOP(left));
7280 if(same && ((offl + MSB16) == offr)){
7282 /* don't crash result[offr] */
7283 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7284 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7287 movLeft2Result(left,offl, result, offr);
7288 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7291 /* a:x >> shCount (x = lsb(result))*/
7294 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7296 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7305 emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7310 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7311 emitpcode(POC_RRF,popGet(AOP(result),offr));
7313 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7314 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7315 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7316 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7321 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7324 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7325 emitpcode(POC_RRF,popGet(AOP(result),offr));
7332 emitpcode(POC_MOVLW, popGetLit(0xf0));
7333 emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7334 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7336 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7337 emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7338 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7339 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7341 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7342 emitpcode(POC_ANDLW, popGetLit(0x0f));
7343 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7345 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7346 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7347 emitpcode(POC_ANDLW, popGetLit(0xf0));
7348 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7349 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7353 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7354 emitpcode(POC_RRF, popGet(AOP(result),offr));
7358 emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7359 emitpcode(POC_BTFSC,
7360 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7361 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7369 emitpcode(POC_RLF, popGet(AOP(result),offr));
7370 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7372 emitpcode(POC_RLF, popGet(AOP(result),offr));
7373 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7374 emitpcode(POC_RLFW, popGet(AOP(result),offr));
7375 emitpcode(POC_ANDLW,popGetLit(0x03));
7377 emitpcode(POC_BTFSC,
7378 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7379 emitpcode(POC_IORLW,popGetLit(0xfc));
7381 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7382 emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7383 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7384 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7386 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7387 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7388 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7389 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7390 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7391 emitpcode(POC_RLF, popGet(AOP(result),offr));
7392 emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7393 emitpcode(POC_ANDLW,popGetLit(0x03));
7395 emitpcode(POC_BTFSC,
7396 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7397 emitpcode(POC_IORLW,popGetLit(0xfc));
7399 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7400 //emitpcode(POC_RLF, popGet(AOP(result),offr));
7407 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7408 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7409 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7410 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7413 emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7415 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7419 /*-----------------------------------------------------------------*/
7420 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7421 /*-----------------------------------------------------------------*/
7422 static void shiftLLeftOrResult (operand *left, int offl,
7423 operand *result, int offr, int shCount)
7426 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7428 /* shift left accumulator */
7429 AccLsh(left,offl,shCount);
7430 /* or with result */
7431 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7432 assert ( !"broken (modifies left, fails for left==result))" );
7435 /*-----------------------------------------------------------------*/
7436 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7437 /*-----------------------------------------------------------------*/
7438 static void shiftRLeftOrResult (operand *left, int offl,
7439 operand *result, int offr, int shCount)
7442 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7444 /* shift right accumulator */
7445 AccRsh(left,offl,shCount);
7446 /* or with result */
7447 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7448 assert ( !"broken (modifies left, fails for left==result))" );
7451 /*-----------------------------------------------------------------*/
7452 /* genlshOne - left shift a one byte quantity by known count */
7453 /*-----------------------------------------------------------------*/
7454 static void genlshOne (operand *result, operand *left, int shCount)
7457 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7458 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7461 /*-----------------------------------------------------------------*/
7462 /* genlshTwo - left shift two bytes by known amount != 0 */
7463 /*-----------------------------------------------------------------*/
7464 static void genlshTwo (operand *result,operand *left, int shCount)
7469 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7470 size = pic14_getDataSize(result);
7472 /* if shCount >= 8 */
7478 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7480 movLeft2Result(left, LSB, result, MSB16);
7482 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7485 /* 1 <= shCount <= 7 */
7488 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7490 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7494 /*-----------------------------------------------------------------*/
7495 /* shiftLLong - shift left one long from left to result */
7496 /* offl = LSB or MSB16 */
7497 /*-----------------------------------------------------------------*/
7498 static void shiftLLong (operand *left, operand *result, int offr )
7501 int size = AOP_SIZE(result);
7504 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7505 if(size >= LSB+offr){
7506 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7508 pic14_emitcode("add","a,acc");
7509 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7510 size >= MSB16+offr && offr != LSB )
7511 pic14_emitcode("xch","a,%s",
7512 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7514 aopPut(AOP(result),"a",LSB+offr);
7517 if(size >= MSB16+offr){
7518 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7519 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7522 pic14_emitcode("rlc","a");
7523 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7524 size >= MSB24+offr && offr != LSB)
7525 pic14_emitcode("xch","a,%s",
7526 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7528 aopPut(AOP(result),"a",MSB16+offr);
7531 if(size >= MSB24+offr){
7532 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7533 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7536 pic14_emitcode("rlc","a");
7537 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7538 size >= MSB32+offr && offr != LSB )
7539 pic14_emitcode("xch","a,%s",
7540 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7542 aopPut(AOP(result),"a",MSB24+offr);
7545 if(size > MSB32+offr){
7546 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7547 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7550 pic14_emitcode("rlc","a");
7551 aopPut(AOP(result),"a",MSB32+offr);
7554 aopPut(AOP(result),zero,LSB);
7557 /*-----------------------------------------------------------------*/
7558 /* genlshFour - shift four byte by a known amount != 0 */
7559 /*-----------------------------------------------------------------*/
7560 static void genlshFour (operand *result, operand *left, int shCount)
7565 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7566 size = AOP_SIZE(result);
7568 /* if shifting more that 3 bytes */
7569 if (shCount >= 24 ) {
7572 /* lowest order of left goes to the highest
7573 order of the destination */
7574 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7576 movLeft2Result(left, LSB, result, MSB32);
7577 aopPut(AOP(result),zero,LSB);
7578 aopPut(AOP(result),zero,MSB16);
7579 aopPut(AOP(result),zero,MSB32);
7583 /* more than two bytes */
7584 else if ( shCount >= 16 ) {
7585 /* lower order two bytes goes to higher order two bytes */
7587 /* if some more remaining */
7589 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7591 movLeft2Result(left, MSB16, result, MSB32);
7592 movLeft2Result(left, LSB, result, MSB24);
7594 aopPut(AOP(result),zero,MSB16);
7595 aopPut(AOP(result),zero,LSB);
7599 /* if more than 1 byte */
7600 else if ( shCount >= 8 ) {
7601 /* lower order three bytes goes to higher order three bytes */
7605 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7607 movLeft2Result(left, LSB, result, MSB16);
7609 else{ /* size = 4 */
7611 movLeft2Result(left, MSB24, result, MSB32);
7612 movLeft2Result(left, MSB16, result, MSB24);
7613 movLeft2Result(left, LSB, result, MSB16);
7614 aopPut(AOP(result),zero,LSB);
7616 else if(shCount == 1)
7617 shiftLLong(left, result, MSB16);
7619 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7620 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7621 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7622 aopPut(AOP(result),zero,LSB);
7627 /* 1 <= shCount <= 7 */
7628 else if(shCount <= 2){
7629 shiftLLong(left, result, LSB);
7631 shiftLLong(result, result, LSB);
7633 /* 3 <= shCount <= 7, optimize */
7635 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7636 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7637 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7643 /*-----------------------------------------------------------------*/
7644 /* genLeftShiftLiteral - left shifting by known count */
7645 /*-----------------------------------------------------------------*/
7646 static void genLeftShiftLiteral (operand *left,
7651 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7655 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7656 freeAsmop(right,NULL,ic,TRUE);
7658 aopOp(left,ic,FALSE);
7659 aopOp(result,ic,FALSE);
7661 size = getSize(operandType(result));
7664 pic14_emitcode("; shift left ","result %d, left %d",size,
7668 /* I suppose that the left size >= result size */
7671 movLeft2Result(left, size, result, size);
7675 else if(shCount >= (size * 8))
7677 aopPut(AOP(result),zero,size);
7681 genlshOne (result,left,shCount);
7686 genlshTwo (result,left,shCount);
7690 genlshFour (result,left,shCount);
7694 freeAsmop(left,NULL,ic,TRUE);
7695 freeAsmop(result,NULL,ic,TRUE);
7699 /*-----------------------------------------------------------------*
7700 * genMultiAsm - repeat assembly instruction for size of register.
7701 * if endian == 1, then the high byte (i.e base address + size of
7702 * register) is used first else the low byte is used first;
7703 *-----------------------------------------------------------------*/
7704 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7710 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7723 emitpcode(poc, popGet(AOP(reg),offset));
7730 /*-----------------------------------------------------------------*/
7731 /* genLeftShift - generates code for left shifting */
7732 /*-----------------------------------------------------------------*/
7733 static void genLeftShift (iCode *ic)
7735 operand *left,*right, *result;
7737 unsigned long lit = 0L;
7739 symbol *tlbl , *tlbl1;
7743 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7745 right = IC_RIGHT(ic);
7747 result = IC_RESULT(ic);
7749 aopOp(right,ic,FALSE);
7750 aopOp(left,ic,FALSE);
7751 aopOp(result,ic,FALSE);
7754 /* if the shift count is known then do it
7755 as efficiently as possible */
7756 if (AOP_TYPE(right) == AOP_LIT) {
7757 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7761 /* shift count is unknown then we have to form
7762 a loop get the loop count in B : Note: we take
7763 only the lower order byte since shifting
7764 more that 32 bits make no sense anyway, ( the
7765 largest size of an object can be only 32 bits ) */
7767 /* this code fails for RIGHT == RESULT */
7768 assert (!pic14_sameRegs (AOP(right), AOP(result)));
7770 /* now move the left to the result if they are not the
7772 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
7773 AOP_SIZE(result) > 1) {
7775 size = AOP_SIZE(result);
7778 l = aopGet(AOP(left),offset,FALSE,TRUE);
7779 if (*l == '@' && (IS_AOP_PREG(result))) {
7781 pic14_emitcode("mov","a,%s",l);
7782 aopPut(AOP(result),"a",offset);
7784 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
7785 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7786 //aopPut(AOP(result),l,offset);
7792 if(AOP_TYPE(left) == AOP_LIT)
7793 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7795 size = AOP_SIZE(result);
7797 /* if it is only one byte then */
7799 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7800 emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7801 emitpcode(POC_ANDLW, popGetLit(0xf0));
7802 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7803 emitpcode(POC_MOVFW, popGet(AOP(left),0));
7804 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7805 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7806 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7807 emitpcode(POC_RLFW, popGet(AOP(result),0));
7808 emitpcode(POC_ANDLW, popGetLit(0xfe));
7809 emitpcode(POC_ADDFW, popGet(AOP(result),0));
7810 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7811 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7814 tlbl = newiTempLabel(NULL);
7815 if (!pic14_sameRegs(AOP(left),AOP(result))) {
7816 mov2w (AOP(left), 0);
7817 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7820 emitpcode(POC_COMFW, popGet(AOP(right),0));
7821 emitpcode(POC_RRF, popGet(AOP(result),0));
7822 emitpLabel(tlbl->key);
7823 emitpcode(POC_RLF, popGet(AOP(result),0));
7824 emitpcode(POC_ADDLW, popGetLit(1));
7826 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7831 if (pic14_sameRegs(AOP(left),AOP(result))) {
7833 tlbl = newiTempLabel(NULL);
7834 emitpcode(POC_COMFW, popGet(AOP(right),0));
7835 genMultiAsm(POC_RRF, result, size,1);
7836 emitpLabel(tlbl->key);
7837 genMultiAsm(POC_RLF, result, size,0);
7838 emitpcode(POC_ADDLW, popGetLit(1));
7840 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7844 //tlbl = newiTempLabel(NULL);
7846 //tlbl1 = newiTempLabel(NULL);
7848 //reAdjustPreg(AOP(result));
7850 //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7851 //pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7852 //l = aopGet(AOP(result),offset,FALSE,FALSE);
7854 //pic14_emitcode("add","a,acc");
7855 //aopPut(AOP(result),"a",offset++);
7857 // l = aopGet(AOP(result),offset,FALSE,FALSE);
7859 // pic14_emitcode("rlc","a");
7860 // aopPut(AOP(result),"a",offset++);
7862 //reAdjustPreg(AOP(result));
7864 //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7865 //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7868 tlbl = newiTempLabel(NULL);
7869 tlbl1= newiTempLabel(NULL);
7871 size = AOP_SIZE(result);
7874 pctemp = popGetTempReg(); /* grab a temporary working register. */
7876 emitpcode(POC_MOVFW, popGet(AOP(right),0));
7878 /* offset should be 0, 1 or 3 */
7879 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7881 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
7883 emitpcode(POC_MOVWF, pctemp);
7886 emitpLabel(tlbl->key);
7889 emitpcode(POC_RLF, popGet(AOP(result),0));
7891 emitpcode(POC_RLF, popGet(AOP(result),offset++));
7893 emitpcode(POC_DECFSZ, pctemp);
7894 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7895 emitpLabel(tlbl1->key);
7897 popReleaseTempReg(pctemp);
7901 freeAsmop (right,NULL,ic,TRUE);
7902 freeAsmop(left,NULL,ic,TRUE);
7903 freeAsmop(result,NULL,ic,TRUE);
7908 /*-----------------------------------------------------------------*/
7909 /* genrshOne - right shift a one byte quantity by known count */
7910 /*-----------------------------------------------------------------*/
7911 static void genrshOne (operand *result, operand *left,
7912 int shCount, int sign)
7915 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7916 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7919 /*-----------------------------------------------------------------*/
7920 /* genrshTwo - right shift two bytes by known amount != 0 */
7921 /*-----------------------------------------------------------------*/
7922 static void genrshTwo (operand *result,operand *left,
7923 int shCount, int sign)
7926 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7927 /* if shCount >= 8 */
7931 shiftR1Left2Result(left, MSB16, result, LSB,
7934 movLeft2Result(left, MSB16, result, LSB);
7936 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7939 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7940 emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7944 /* 1 <= shCount <= 7 */
7946 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
7949 /*-----------------------------------------------------------------*/
7950 /* shiftRLong - shift right one long from left to result */
7951 /* offl = LSB or MSB16 */
7952 /*-----------------------------------------------------------------*/
7953 static void shiftRLong (operand *left, int offl,
7954 operand *result, int sign)
7959 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7961 size = AOP_SIZE(left);
7962 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7965 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7969 assert (offl >= 0 && offl < size);
7971 same = pic14_sameRegs (AOP(left), AOP(result));
7973 /* perform the shift */
7976 if (same && !offl) {
7977 emitpcode (POC_RRF, popGet (AOP(result), size));
7979 emitpcode (POC_RRFW, popGet (AOP(left), size));
7980 emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7984 addSign (result, AOP_SIZE(left) - offl, sign);
7987 /*-----------------------------------------------------------------*/
7988 /* genrshFour - shift four byte by a known amount != 0 */
7989 /*-----------------------------------------------------------------*/
7990 static void genrshFour (operand *result, operand *left,
7991 int shCount, int sign)
7994 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7995 /* if shifting more that 3 bytes */
7996 if(shCount >= 24 ) {
7999 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8001 movLeft2Result(left, MSB32, result, LSB);
8003 addSign(result, MSB16, sign);
8005 else if(shCount >= 16){
8008 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8010 movLeft2Result(left, MSB24, result, LSB);
8011 movLeft2Result(left, MSB32, result, MSB16);
8013 addSign(result, MSB24, sign);
8015 else if(shCount >= 8){
8018 shiftRLong(left, MSB16, result, sign);
8019 else if(shCount == 0){
8020 movLeft2Result(left, MSB16, result, LSB);
8021 movLeft2Result(left, MSB24, result, MSB16);
8022 movLeft2Result(left, MSB32, result, MSB24);
8023 addSign(result, MSB32, sign);
8026 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8027 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8028 /* the last shift is signed */
8029 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8030 addSign(result, MSB32, sign);
8033 else{ /* 1 <= shCount <= 7 */
8035 shiftRLong(left, LSB, result, sign);
8037 shiftRLong(result, LSB, result, sign);
8040 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8041 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8042 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8047 /*-----------------------------------------------------------------*/
8048 /* genRightShiftLiteral - right shifting by known count */
8049 /*-----------------------------------------------------------------*/
8050 static void genRightShiftLiteral (operand *left,
8056 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8060 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8061 freeAsmop(right,NULL,ic,TRUE);
8063 aopOp(left,ic,FALSE);
8064 aopOp(result,ic,FALSE);
8067 pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8071 lsize = pic14_getDataSize(left);
8072 res_size = pic14_getDataSize(result);
8073 /* test the LEFT size !!! */
8075 /* I suppose that the left size >= result size */
8078 movLeft2Result(left, res_size, result, res_size);
8081 else if(shCount >= (lsize * 8)){
8084 emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8086 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8087 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8092 emitpcode(POC_MOVLW, popGetLit(0));
8093 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8094 emitpcode(POC_MOVLW, popGetLit(0xff));
8096 emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8101 emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8108 genrshOne (result,left,shCount,sign);
8112 genrshTwo (result,left,shCount,sign);
8116 genrshFour (result,left,shCount,sign);
8124 freeAsmop(left,NULL,ic,TRUE);
8125 freeAsmop(result,NULL,ic,TRUE);
8130 /*-----------------------------------------------------------------*/
8131 /* genSignedRightShift - right shift of signed number */
8132 /*-----------------------------------------------------------------*/
8133 static void genSignedRightShift (iCode *ic)
8135 operand *right, *left, *result;
8138 symbol *tlbl, *tlbl1 ;
8141 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8143 /* we do it the hard way put the shift count in b
8144 and loop thru preserving the sign */
8146 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8148 right = IC_RIGHT(ic);
8150 result = IC_RESULT(ic);
8152 aopOp(right,ic,FALSE);
8153 aopOp(left,ic,FALSE);
8154 aopOp(result,ic,FALSE);
8157 if ( AOP_TYPE(right) == AOP_LIT) {
8158 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8159 //genRightShiftLiteral (left,right,result,ic,1);
8162 /* shift count is unknown then we have to form
8163 a loop get the loop count in B : Note: we take
8164 only the lower order byte since shifting
8165 more that 32 bits make no sense anyway, ( the
8166 largest size of an object can be only 32 bits ) */
8168 //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8169 //pic14_emitcode("inc","b");
8170 //freeAsmop (right,NULL,ic,TRUE);
8171 //aopOp(left,ic,FALSE);
8172 //aopOp(result,ic,FALSE);
8174 /* now move the left to the result if they are not the
8176 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
8177 AOP_SIZE(result) > 1) {
8179 size = AOP_SIZE(result);
8183 l = aopGet(AOP(left),offset,FALSE,TRUE);
8184 if (*l == '@' && IS_AOP_PREG(result)) {
8185 pic14_emitcode("mov","a,%s",l);
8186 aopPut(AOP(result),"a",offset);
8188 aopPut(AOP(result),l,offset);
8190 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8191 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8197 /* mov the highest order bit to OVR */
8198 tlbl = newiTempLabel(NULL);
8199 tlbl1= newiTempLabel(NULL);
8201 size = AOP_SIZE(result);
8204 pctemp = popGetTempReg(); /* grab a temporary working register. */
8206 emitpcode(POC_MOVFW, popGet(AOP(right),0));
8208 /* offset should be 0, 1 or 3 */
8209 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8211 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8213 emitpcode(POC_MOVWF, pctemp);
8216 emitpLabel(tlbl->key);
8218 emitpcode(POC_RLFW, popGet(AOP(result),offset));
8219 emitpcode(POC_RRF, popGet(AOP(result),offset));
8222 emitpcode(POC_RRF, popGet(AOP(result),--offset));
8225 emitpcode(POC_DECFSZ, pctemp);
8226 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8227 emitpLabel(tlbl1->key);
8229 popReleaseTempReg(pctemp);
8231 size = AOP_SIZE(result);
8233 pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8234 pic14_emitcode("rlc","a");
8235 pic14_emitcode("mov","ov,c");
8236 /* if it is only one byte then */
8238 l = aopGet(AOP(left),0,FALSE,FALSE);
8240 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8241 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8242 pic14_emitcode("mov","c,ov");
8243 pic14_emitcode("rrc","a");
8244 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8245 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8246 aopPut(AOP(result),"a",0);
8250 reAdjustPreg(AOP(result));
8251 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8252 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8253 pic14_emitcode("mov","c,ov");
8255 l = aopGet(AOP(result),offset,FALSE,FALSE);
8257 pic14_emitcode("rrc","a");
8258 aopPut(AOP(result),"a",offset--);
8260 reAdjustPreg(AOP(result));
8261 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8262 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8267 freeAsmop(left,NULL,ic,TRUE);
8268 freeAsmop(result,NULL,ic,TRUE);
8269 freeAsmop(right,NULL,ic,TRUE);
8273 /*-----------------------------------------------------------------*/
8274 /* loadSignToC - load the operand's sign bit into CARRY */
8275 /*-----------------------------------------------------------------*/
8277 static void loadSignToC (operand *op)
8280 assert (op && AOP(op) && AOP_SIZE(op));
8283 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8287 /*-----------------------------------------------------------------*/
8288 /* genRightShift - generate code for right shifting */
8289 /*-----------------------------------------------------------------*/
8290 static void genGenericShift (iCode *ic, int shiftRight)
8292 operand *right, *left, *result;
8295 symbol *tlbl, *tlbl1, *inverselbl;
8298 /* if signed then we do it the hard way preserve the
8299 sign bit moving it inwards */
8300 retype = getSpec(operandType(IC_RESULT(ic)));
8301 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8303 /* signed & unsigned types are treated the same : i.e. the
8304 signed is NOT propagated inwards : quoting from the
8305 ANSI - standard : "for E1 >> E2, is equivalent to division
8306 by 2**E2 if unsigned or if it has a non-negative value,
8307 otherwise the result is implementation defined ", MY definition
8308 is that the sign does not get propagated */
8310 right = IC_RIGHT(ic);
8312 result = IC_RESULT(ic);
8314 aopOp(right,ic,FALSE);
8315 aopOp(left,ic,FALSE);
8316 aopOp(result,ic,FALSE);
8318 /* if the shift count is known then do it
8319 as efficiently as possible */
8320 if (AOP_TYPE(right) == AOP_LIT) {
8321 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8325 shiftRight = !shiftRight;
8329 shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8331 shiftLeft_Left2ResultLit (left, result, lit);
8332 //genRightShiftLiteral (left,right,result,ic, 0);
8336 /* shift count is unknown then we have to form
8337 a loop get the loop count in B : Note: we take
8338 only the lower order byte since shifting
8339 more that 32 bits make no sense anyway, ( the
8340 largest size of an object can be only 32 bits ) */
8342 /* we must not overwrite the shift counter */
8343 assert (!pic14_sameRegs(AOP(right),AOP(result)));
8345 /* now move the left to the result if they are not the
8347 if (!pic14_sameRegs(AOP(left),AOP(result)))
8349 size = min(AOP_SIZE(result), AOP_SIZE(left));
8351 mov2w(AOP(left), size);
8352 movwf(AOP(result), size);
8354 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8357 tlbl = newiTempLabel(NULL);
8358 tlbl1= newiTempLabel(NULL);
8360 size = AOP_SIZE(result);
8362 mov2w(AOP(right),0);
8363 if (!SPEC_USIGN(operandType(right)))
8365 inverselbl = newiTempLabel(NULL);
8366 /* signed shift count -- invert shift direction for c<0 */
8367 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8368 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8370 emitpcode(POC_SUBLW, popGetLit(0)); /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8371 /* check for `a = b >> c' with `-c == 0' */
8373 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8374 emitpLabel(tlbl->key);
8375 /* propagate the sign bit inwards for SIGNED result */
8376 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8377 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8378 emitpcode(POC_ADDLW, popGetLit(1)); /* clears CARRY (unless W==0 afterwards) */
8380 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8382 if (!SPEC_USIGN(operandType(right)))
8384 symbol *inv_loop = newiTempLabel(NULL);
8386 shiftRight = !shiftRight; /* invert shift direction */
8388 /* we came here from the code above -- we are done */
8389 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8391 /* emit code for shifting N<0 steps, count is already in W */
8392 emitpLabel(inverselbl->key);
8393 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8394 emitpLabel(inv_loop->key);
8395 /* propagate the sign bit inwards for SIGNED result */
8396 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8397 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8398 emitpcode(POC_ADDLW, popGetLit(1));
8400 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8403 emitpLabel(tlbl1->key);
8405 freeAsmop(left,NULL,ic,TRUE);
8406 freeAsmop (right,NULL,ic,TRUE);
8407 freeAsmop(result,NULL,ic,TRUE);
8410 static void genRightShift (iCode *ic)
8412 genGenericShift(ic, 1);
8415 static void genLeftShift (iCode *ic)
8417 genGenericShift(ic, 0);
8420 /*-----------------------------------------------------------------*/
8421 /* SetIrp - Set IRP bit */
8422 /*-----------------------------------------------------------------*/
8423 void SetIrp(operand *result) {
8425 if (AOP_TYPE(result) == AOP_LIT) {
8426 unsigned lit = (unsigned)operandLitValue(result);
8432 if (PCOP(AOP(result))->type == PO_LITERAL) {
8433 int addrs = PCOL(AOP(result))->lit;
8439 emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8440 if(AOP_SIZE(result) > 1) {
8441 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8449 setup_fsr (operand *ptr)
8452 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8454 /* also setup-up IRP */
8458 /*-----------------------------------------------------------------*/
8459 /* emitPtrByteGet - emits code to get a byte into WREG from an */
8460 /* arbitrary pointer (__code, __data, generic) */
8461 /*-----------------------------------------------------------------*/
8463 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8470 if (!alreadyAddressed) setup_fsr (src);
8471 emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8475 assert( AOP_SIZE(src) == 2 );
8477 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8479 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8480 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
8481 call_libraryfunc ("__gptrget1");
8485 assert( AOP_SIZE(src) == 3 );
8487 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8489 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8491 call_libraryfunc ("__gptrget1");
8495 assert( !"unhandled pointer type" );
8500 /*-----------------------------------------------------------------*/
8501 /* emitPtrByteSet - emits code to set a byte from src through a */
8502 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR). */
8503 /*-----------------------------------------------------------------*/
8505 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8512 if (!alreadyAddressed) setup_fsr (dst);
8513 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8517 assert( !"trying to assign to __code pointer" );
8521 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8523 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8525 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8527 call_libraryfunc ("__gptrput1");
8531 assert( !"unhandled pointer type" );
8536 /*-----------------------------------------------------------------*/
8537 /* genUnpackBits - generates code for unpacking bits */
8538 /*-----------------------------------------------------------------*/
8539 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8541 int rsize; /* result size */
8542 sym_link *etype; /* bitfield type information */
8543 int blen; /* bitfield length */
8544 int bstr; /* bitfield starting bit within byte */
8547 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8548 etype = getSpec(operandType(result));
8549 rsize = getSize (operandType (result));
8550 blen = SPEC_BLEN (etype);
8551 bstr = SPEC_BSTR (etype);
8553 /* single bit field case */
8555 if (ifx) { /* that is for an if statement */
8558 resolveIfx(&rIfx,ifx);
8559 if (ptype == -1) /* direct */
8560 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8562 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8563 emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8564 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8568 assert (!pic14_sameRegs (AOP(result), AOP(left)));
8569 for (i=0; i < AOP_SIZE(result); i++)
8570 emitpcode (POC_CLRF, popGet (AOP(result), i));
8575 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8576 /* adjust result below */
8583 emitPtrByteGet (left, ptype, FALSE);
8584 emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8586 /* adjust result below */
8590 assert( !"unhandled pointer type" );
8593 /* move sign-/zero extended bit to result */
8594 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8595 emitpcode (POC_INCF, popGet (AOP(result), 0));
8597 emitpcode (POC_DECF, popGet (AOP(result), 0));
8599 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8603 else if (blen <= 8 && ((blen + bstr) <= 8))
8608 for (i=0; i < AOP_SIZE(result); i++)
8609 emitpcode (POC_CLRF, popGet (AOP(result), i));
8614 mov2w(AOP(left), 0);
8621 emitPtrByteGet (left, ptype, FALSE);
8625 assert( !"unhandled pointer type" );
8629 emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8630 movwf(AOP(result), 0);
8631 AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8633 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8635 /* signed bitfield */
8636 assert (bstr + blen > 0);
8637 emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8638 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8639 emitpcode(POC_IORWF, popGet(AOP(result),0));
8641 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8645 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8649 /*-----------------------------------------------------------------*/
8650 /* genDataPointerGet - generates code when ptr offset is known */
8651 /*-----------------------------------------------------------------*/
8652 static void genDataPointerGet (operand *left,
8656 int size , offset = 0;
8659 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8662 /* optimization - most of the time, left and result are the same
8663 * address, but different types. for the pic code, we could omit
8666 aopOp(result,ic,TRUE);
8668 if (pic14_sameRegs (AOP(left), AOP(result)))
8671 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8673 //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8675 size = AOP_SIZE(result);
8676 if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8680 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8681 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8685 freeAsmop(left,NULL,ic,TRUE);
8686 freeAsmop(result,NULL,ic,TRUE);
8690 /*-----------------------------------------------------------------*/
8691 /* genNearPointerGet - pic14_emitcode for near pointer fetch */
8692 /*-----------------------------------------------------------------*/
8693 static void genNearPointerGet (operand *left,
8698 sym_link *ltype = operandType(left);
8699 sym_link *rtype = operandType(result);
8700 sym_link *retype= getSpec(rtype); /* bitfield type information */
8704 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8707 aopOp(left,ic,FALSE);
8709 /* if left is rematerialisable and
8710 result is not bit variable type and
8711 the left is pointer to data space i.e
8712 lower 128 bytes of space */
8713 if (AOP_TYPE(left) == AOP_PCODE && //AOP_TYPE(left) == AOP_IMMD &&
8714 !IS_BITVAR(retype) &&
8715 PIC_IS_DATA_PTR(ltype)) {
8716 genDataPointerGet (left,result,ic);
8720 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8721 aopOp (result,ic,FALSE);
8723 /* Check if can access directly instead of via a pointer */
8724 if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8725 && AOP_SIZE(result) == 1)
8730 if (IS_BITFIELD(getSpec(operandType(result))))
8732 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8736 /* If the pointer value is not in a the FSR then need to put it in */
8737 /* Must set/reset IRP bit for use with FSR. */
8742 /* if bitfield then unpack the bits */
8744 /* we have can just get the values */
8745 int size = AOP_SIZE(result);
8748 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8752 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8754 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8755 if (AOP_TYPE(result) == AOP_LIT) {
8756 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8758 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8760 if (size && !direct)
8761 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8766 /* now some housekeeping stuff */
8768 /* we had to allocate for this iCode */
8769 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8770 freeAsmop(NULL,aop,ic,TRUE);
8772 /* we did not allocate which means left
8773 already in a pointer register, then
8774 if size > 0 && this could be used again
8775 we have to point it back to where it
8777 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8778 if (AOP_SIZE(result) > 1 &&
8779 !OP_SYMBOL(left)->remat &&
8780 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8782 int size = AOP_SIZE(result) - 1;
8784 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8790 freeAsmop(left,NULL,ic,TRUE);
8791 freeAsmop(result,NULL,ic,TRUE);
8796 /*-----------------------------------------------------------------*/
8797 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch */
8798 /*-----------------------------------------------------------------*/
8799 static void genPagedPointerGet (operand *left,
8806 sym_link *rtype, *retype;
8809 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8811 rtype = operandType(result);
8812 retype= getSpec(rtype);
8814 aopOp(left,ic,FALSE);
8816 /* if the value is already in a pointer register
8817 then don't need anything more */
8818 if (!AOP_INPREG(AOP(left))) {
8819 /* otherwise get a free pointer register */
8821 preg = getFreePtr(ic,&aop,FALSE);
8822 pic14_emitcode("mov","%s,%s",
8824 aopGet(AOP(left),0,FALSE,TRUE));
8825 rname = preg->name ;
8827 rname = aopGet(AOP(left),0,FALSE,FALSE);
8829 freeAsmop(left,NULL,ic,TRUE);
8830 aopOp (result,ic,FALSE);
8832 /* if bitfield then unpack the bits */
8833 if (IS_BITFIELD(retype))
8834 genUnpackBits (result,left,rname,PPOINTER,0);
8836 /* we have can just get the values */
8837 int size = AOP_SIZE(result);
8842 pic14_emitcode("movx","a,@%s",rname);
8843 aopPut(AOP(result),"a",offset);
8848 pic14_emitcode("inc","%s",rname);
8852 /* now some housekeeping stuff */
8854 /* we had to allocate for this iCode */
8855 freeAsmop(NULL,aop,ic,TRUE);
8857 /* we did not allocate which means left
8858 already in a pointer register, then
8859 if size > 0 && this could be used again
8860 we have to point it back to where it
8862 if (AOP_SIZE(result) > 1 &&
8863 !OP_SYMBOL(left)->remat &&
8864 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8866 int size = AOP_SIZE(result) - 1;
8868 pic14_emitcode("dec","%s",rname);
8873 freeAsmop(result,NULL,ic,TRUE);
8878 /*-----------------------------------------------------------------*/
8879 /* genFarPointerGet - gget value from far space */
8880 /*-----------------------------------------------------------------*/
8881 static void genFarPointerGet (operand *left,
8882 operand *result, iCode *ic)
8885 sym_link *retype = getSpec(operandType(result));
8888 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8890 aopOp(left,ic,FALSE);
8892 /* if the operand is already in dptr
8893 then we do nothing else we move the value to dptr */
8894 if (AOP_TYPE(left) != AOP_STR) {
8895 /* if this is remateriazable */
8896 if (AOP_TYPE(left) == AOP_IMMD)
8897 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8898 else { /* we need to get it byte by byte */
8899 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8900 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8901 if (options.model == MODEL_FLAT24)
8903 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8907 /* so dptr know contains the address */
8908 freeAsmop(left,NULL,ic,TRUE);
8909 aopOp(result,ic,FALSE);
8911 /* if bit then unpack */
8912 if (IS_BITFIELD(retype))
8913 genUnpackBits(result,left,"dptr",FPOINTER,0);
8915 size = AOP_SIZE(result);
8919 pic14_emitcode("movx","a,@dptr");
8920 aopPut(AOP(result),"a",offset++);
8922 pic14_emitcode("inc","dptr");
8926 freeAsmop(result,NULL,ic,TRUE);
8931 /*-----------------------------------------------------------------*/
8932 /* genCodePointerGet - get value from code space */
8933 /*-----------------------------------------------------------------*/
8934 static void genCodePointerGet (operand *left,
8935 operand *result, iCode *ic)
8938 sym_link *retype = getSpec(operandType(result));
8940 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8942 aopOp(left,ic,FALSE);
8944 /* if the operand is already in dptr
8945 then we do nothing else we move the value to dptr */
8946 if (AOP_TYPE(left) != AOP_STR) {
8947 /* if this is remateriazable */
8948 if (AOP_TYPE(left) == AOP_IMMD)
8949 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8950 else { /* we need to get it byte by byte */
8951 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8952 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8953 if (options.model == MODEL_FLAT24)
8955 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8959 /* so dptr know contains the address */
8960 freeAsmop(left,NULL,ic,TRUE);
8961 aopOp(result,ic,FALSE);
8963 /* if bit then unpack */
8964 if (IS_BITFIELD(retype))
8965 genUnpackBits(result,left,"dptr",CPOINTER,0);
8967 size = AOP_SIZE(result);
8971 pic14_emitcode("clr","a");
8972 pic14_emitcode("movc","a,@a+dptr");
8973 aopPut(AOP(result),"a",offset++);
8975 pic14_emitcode("inc","dptr");
8979 freeAsmop(result,NULL,ic,TRUE);
8982 /*-----------------------------------------------------------------*/
8983 /* genGenPointerGet - gget value from generic pointer space */
8984 /*-----------------------------------------------------------------*/
8985 static void genGenPointerGet (operand *left,
8986 operand *result, iCode *ic)
8989 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8990 aopOp(left,ic,FALSE);
8991 aopOp(result,ic,FALSE);
8994 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8996 if (IS_BITFIELD(getSpec(operandType(result))))
8998 genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
9003 /* emit call to __gptrget */
9004 char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
9005 int size = AOP_SIZE(result);
9008 assert (size > 0 && size <= 4);
9010 /* pass arguments */
9011 assert (AOP_SIZE(left) == 3);
9012 mov2w(AOP(left), 0);
9013 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9014 mov2w(AOP(left), 1);
9015 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9016 mov2w(AOP(left), 2);
9017 call_libraryfunc (func[size]);
9020 movwf (AOP(result), --size);
9022 emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
9023 movwf (AOP(result), size);
9027 freeAsmop(left,NULL,ic,TRUE);
9028 freeAsmop(result,NULL,ic,TRUE);
9032 /*-----------------------------------------------------------------*/
9033 /* genConstPointerGet - get value from const generic pointer space */
9034 /*-----------------------------------------------------------------*/
9035 static void genConstPointerGet (operand *left,
9036 operand *result, iCode *ic)
9038 //sym_link *retype = getSpec(operandType(result));
9040 symbol *albl, *blbl;//, *clbl;
9047 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9048 aopOp(left,ic,FALSE);
9049 aopOp(result,ic,FALSE);
9051 size = AOP_SIZE(result);
9053 DEBUGpic14_AopType(__LINE__,left,NULL,result);
9055 DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
9057 lit = op_isLitLike (left);
9058 poc = lit ? POC_MOVLW : POC_MOVFW;
9060 if (IS_BITFIELD(getSpec(operandType(result))))
9062 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
9067 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
9068 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
9069 assert (size > 0 && size <= 4);
9072 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9074 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9075 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
9076 call_libraryfunc (func[size]);
9078 movwf(AOP(result),size-1);
9079 for (i = 1; i < size; i++)
9081 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
9082 movwf(AOP(result),size - 1 - i);
9087 freeAsmop(left,NULL,ic,TRUE);
9088 freeAsmop(result,NULL,ic,TRUE);
9091 /*-----------------------------------------------------------------*/
9092 /* genPointerGet - generate code for pointer get */
9093 /*-----------------------------------------------------------------*/
9094 static void genPointerGet (iCode *ic)
9096 operand *left, *result ;
9097 sym_link *type, *etype;
9101 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9104 result = IC_RESULT(ic) ;
9106 /* depending on the type of pointer we need to
9107 move it to the correct pointer register */
9108 type = operandType(left);
9109 etype = getSpec(type);
9111 if (IS_PTR_CONST(type))
9112 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9114 /* if left is of type of pointer then it is simple */
9115 if (IS_PTR(type) && !IS_FUNC(type->next))
9116 p_type = DCL_TYPE(type);
9118 /* we have to go by the storage class */
9119 p_type = PTR_TYPE(SPEC_OCLS(etype));
9121 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9123 if (SPEC_OCLS(etype)->codesp ) {
9124 DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9125 //p_type = CPOINTER ;
9128 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9129 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9130 /*p_type = FPOINTER ;*/
9132 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9133 DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9134 /* p_type = PPOINTER; */
9136 if (SPEC_OCLS(etype) == idata )
9137 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9138 /* p_type = IPOINTER; */
9140 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9141 /* p_type = POINTER ; */
9144 /* now that we have the pointer type we assign
9145 the pointer values */
9151 genNearPointerGet (left,result,ic);
9155 genPagedPointerGet(left,result,ic);
9159 genFarPointerGet (left,result,ic);
9163 genConstPointerGet (left,result,ic);
9167 genGenPointerGet (left,result,ic);
9170 assert ( !"unhandled pointer type" );
9176 /*-----------------------------------------------------------------*/
9177 /* genPackBits - generates code for packed bit storage */
9178 /*-----------------------------------------------------------------*/
9179 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9181 int blen; /* bitfield length */
9182 int bstr; /* bitfield starting bit within byte */
9183 int litval; /* source literal value (if AOP_LIT) */
9184 unsigned char mask; /* bitmask within current byte */
9187 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9189 blen = SPEC_BLEN (etype);
9190 bstr = SPEC_BSTR (etype);
9192 /* If the bitfield length is less than a byte and does not cross byte boundaries */
9193 if ((blen <= 8) && ((bstr + blen) <= 8))
9195 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9196 (unsigned char) (0xFF >> (8 - bstr)));
9198 if (AOP_TYPE (right) == AOP_LIT)
9200 /* Case with a bitfield length <8 and literal source */
9201 int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9208 if (AOP(result)->type == AOP_PCODE)
9209 pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9211 pcop = popGet(AOP(result),0);
9212 emitpcode(lit?POC_BSF:POC_BCF,pcop);
9218 emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9222 assert( !"trying to assign to bitfield via pointer to __code space" );
9226 emitPtrByteGet(result, p_type, FALSE);
9228 emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9230 emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9232 emitPtrByteSet(result, p_type, TRUE);
9236 assert( !"unhandled pointer type" );
9238 } // switch (p_type)
9241 litval = lit << bstr;
9242 litval &= (~mask) & 0x00ff;
9247 mov2w (AOP(result), 0);
9248 if ((litval|mask) != 0x00ff)
9249 emitpcode(POC_ANDLW, popGetLit (mask));
9251 emitpcode(POC_IORLW, popGetLit (litval));
9252 movwf (AOP(result), 0);
9258 emitPtrByteGet(result, p_type, FALSE);
9259 if ((litval|mask) != 0x00ff)
9260 emitpcode(POC_ANDLW, popGetLit (mask));
9262 emitpcode(POC_IORLW, popGetLit (litval));
9263 emitPtrByteSet(result, p_type, TRUE);
9267 assert( !"trying to assign to bitfield via pointer to __code space" );
9271 assert( !"unhandled pointer type" );
9278 /* right is no literal */
9283 /* Note more efficient code, of pre clearing bit then only setting it if required,
9284 * can only be done if it is known that the result is not a SFR */
9285 emitpcode(POC_RRFW,popGet(AOP(right),0));
9287 emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9289 emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9295 emitPtrByteGet (result, p_type, FALSE);
9296 emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9297 emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9298 emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9299 emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9300 emitPtrByteSet (result, p_type, TRUE);
9304 assert( !"trying to assign to bitfield via pointer to __code space" );
9308 assert( !"unhandled pointer type" );
9313 /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9314 pCodeOp *temp = popGetTempReg ();
9316 mov2w (AOP(right), 0);
9318 emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9320 emitpcode(POC_MOVWF, temp);
9322 AccLsh (temp, bstr);
9328 mov2w (AOP(result), 0);
9329 emitpcode(POC_ANDLW, popGetLit (mask));
9330 emitpcode(POC_IORFW, temp);
9331 movwf (AOP(result), 0);
9337 emitPtrByteGet (result, p_type, FALSE);
9338 emitpcode(POC_ANDLW, popGetLit (mask));
9339 emitpcode(POC_IORFW, temp);
9340 emitPtrByteSet (result, p_type, TRUE);
9344 assert( !"trying to assign to bitfield via pointer to __code space" );
9348 assert( !"unhandled pointer type" );
9352 popReleaseTempReg (temp);
9354 } // if (AOP(right)->type != AOP_LIT)
9356 } // if (blen <= 8 && ((blen + bstr) <= 8))
9358 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9361 /*-----------------------------------------------------------------*/
9362 /* genDataPointerSet - remat pointer to data space */
9363 /*-----------------------------------------------------------------*/
9364 static void genDataPointerSet(operand *right,
9368 int size, offset = 0 ;
9372 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9373 aopOp(right,ic,FALSE);
9374 aopOp(result,ic,FALSE);
9376 assert (IS_SYMOP(result));
9377 assert (IS_PTR(OP_SYM_TYPE(result)));
9379 size = AOP_SIZE(right);
9380 ressize = getSize(OP_SYM_ETYPE(result));
9381 if (size > ressize) size = ressize;
9382 //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9384 //assert( !"what's going on here?" );
9387 if ( AOP_TYPE(result) == AOP_PCODE) {
9388 fprintf(stderr,"genDataPointerSet %s, %d\n",
9389 AOP(result)->aopu.pcop->name,
9390 PCOI(AOP(result)->aopu.pcop)->offset);
9394 // tsd, was l+1 - the underline `_' prefix was being stripped
9396 emitpComment ("%s:%u: size=%d/%d, offset=%i", __FILE__,__LINE__, size, ressize, offset);
9398 if (AOP_TYPE(right) == AOP_LIT) {
9399 unsigned int lit = pic14aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
9400 //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9402 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9403 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9405 emitpcode(POC_CLRF, popGet(AOP(result), offset));
9408 //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9409 emitpcode(POC_MOVFW, popGet(AOP(right), offset));
9410 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9416 freeAsmop(right,NULL,ic,TRUE);
9417 freeAsmop(result,NULL,ic,TRUE);
9420 /*-----------------------------------------------------------------*/
9421 /* genNearPointerSet - pic14_emitcode for near pointer put */
9422 /*-----------------------------------------------------------------*/
9423 static void genNearPointerSet (operand *right,
9428 sym_link *ptype = operandType(result);
9429 sym_link *retype = getSpec(operandType(right));
9430 sym_link *letype = getSpec(ptype);
9435 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9436 aopOp(result,ic,FALSE);
9439 /* if the result is rematerializable &
9440 in data space & not a bit variable */
9441 //if (AOP_TYPE(result) == AOP_IMMD &&
9442 if (AOP_TYPE(result) == AOP_PCODE &&
9443 PIC_IS_DATA_PTR(ptype) &&
9444 !IS_BITVAR (retype) &&
9445 !IS_BITVAR (letype)) {
9446 genDataPointerSet (right,result,ic);
9447 freeAsmop(result,NULL,ic,TRUE);
9452 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9453 aopOp(right,ic,FALSE);
9454 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9456 /* Check if can access directly instead of via a pointer */
9457 if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9461 if (IS_BITFIELD (letype))
9463 genPackBits (letype, result, right, direct?-1:POINTER);
9467 /* If the pointer value is not in a the FSR then need to put it in */
9468 /* Must set/reset IRP bit for use with FSR. */
9469 /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9474 /* we have can just get the values */
9475 int size = AOP_SIZE(right);
9478 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9480 char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9482 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9484 if (AOP_TYPE(right) == AOP_LIT) {
9485 emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9487 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9490 emitpcode(POC_MOVWF,popGet(AOP(result),0));
9492 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9494 if (size && !direct)
9495 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9500 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9501 /* now some housekeeping stuff */
9503 /* we had to allocate for this iCode */
9504 freeAsmop(NULL,aop,ic,TRUE);
9506 /* we did not allocate which means left
9507 already in a pointer register, then
9508 if size > 0 && this could be used again
9509 we have to point it back to where it
9511 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9512 if (AOP_SIZE(right) > 1 &&
9513 !OP_SYMBOL(result)->remat &&
9514 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9516 int size = AOP_SIZE(right) - 1;
9518 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9522 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9525 freeAsmop(right,NULL,ic,TRUE);
9526 freeAsmop(result,NULL,ic,TRUE);
9530 /*-----------------------------------------------------------------*/
9531 /* genPagedPointerSet - pic14_emitcode for Paged pointer put */
9532 /*-----------------------------------------------------------------*/
9533 static void genPagedPointerSet (operand *right,
9543 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9545 retype= getSpec(operandType(right));
9547 aopOp(result,ic,FALSE);
9549 /* if the value is already in a pointer register
9550 then don't need anything more */
9551 if (!AOP_INPREG(AOP(result))) {
9552 /* otherwise get a free pointer register */
9554 preg = getFreePtr(ic,&aop,FALSE);
9555 pic14_emitcode("mov","%s,%s",
9557 aopGet(AOP(result),0,FALSE,TRUE));
9558 rname = preg->name ;
9560 rname = aopGet(AOP(result),0,FALSE,FALSE);
9562 freeAsmop(result,NULL,ic,TRUE);
9563 aopOp (right,ic,FALSE);
9565 /* if bitfield then unpack the bits */
9566 if (IS_BITFIELD(retype))
9567 genPackBits (retype,result,right,rname,PPOINTER);
9569 /* we have can just get the values */
9570 int size = AOP_SIZE(right);
9574 l = aopGet(AOP(right),offset,FALSE,TRUE);
9577 pic14_emitcode("movx","@%s,a",rname);
9580 pic14_emitcode("inc","%s",rname);
9586 /* now some housekeeping stuff */
9588 /* we had to allocate for this iCode */
9589 freeAsmop(NULL,aop,ic,TRUE);
9591 /* we did not allocate which means left
9592 already in a pointer register, then
9593 if size > 0 && this could be used again
9594 we have to point it back to where it
9596 if (AOP_SIZE(right) > 1 &&
9597 !OP_SYMBOL(result)->remat &&
9598 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9600 int size = AOP_SIZE(right) - 1;
9602 pic14_emitcode("dec","%s",rname);
9607 freeAsmop(right,NULL,ic,TRUE);
9612 /*-----------------------------------------------------------------*/
9613 /* genFarPointerSet - set value from far space */
9614 /*-----------------------------------------------------------------*/
9615 static void genFarPointerSet (operand *right,
9616 operand *result, iCode *ic)
9619 sym_link *retype = getSpec(operandType(right));
9622 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9623 aopOp(result,ic,FALSE);
9625 /* if the operand is already in dptr
9626 then we do nothing else we move the value to dptr */
9627 if (AOP_TYPE(result) != AOP_STR) {
9628 /* if this is remateriazable */
9629 if (AOP_TYPE(result) == AOP_IMMD)
9630 pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9631 else { /* we need to get it byte by byte */
9632 pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9633 pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9634 if (options.model == MODEL_FLAT24)
9636 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9640 /* so dptr know contains the address */
9641 freeAsmop(result,NULL,ic,TRUE);
9642 aopOp(right,ic,FALSE);
9644 /* if bit then unpack */
9645 if (IS_BITFIELD(retype))
9646 genPackBits(retype,result,right,"dptr",FPOINTER);
9648 size = AOP_SIZE(right);
9652 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9654 pic14_emitcode("movx","@dptr,a");
9656 pic14_emitcode("inc","dptr");
9660 freeAsmop(right,NULL,ic,TRUE);
9664 /*-----------------------------------------------------------------*/
9665 /* genGenPointerSet - set value from generic pointer space */
9666 /*-----------------------------------------------------------------*/
9667 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9669 sym_link *retype = getSpec(operandType(result));
9672 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9673 aopOp(right,ic,FALSE);
9674 aopOp(result,ic,FALSE);
9677 DEBUGpic14_AopType(__LINE__,right,NULL,result);
9679 if (IS_BITFIELD(retype))
9681 genPackBits (retype, result, right, GPOINTER);
9686 /* emit call to __gptrput */
9687 char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9688 int size = AOP_SIZE(right);
9691 assert (size == getSize(OP_SYM_ETYPE(result)));
9692 assert (size > 0 && size <= 4);
9694 /* pass arguments */
9695 /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9701 mov2w_op (right, off);
9702 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9707 assert (AOP_SIZE(result) == 3);
9708 mov2w(AOP(result), 0);
9709 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9710 mov2w(AOP(result), 1);
9711 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9712 mov2w(AOP(result), 2);
9713 call_libraryfunc (func[size]);
9716 freeAsmop(right,NULL,ic,TRUE);
9717 freeAsmop(result,NULL,ic,TRUE);
9720 /*-----------------------------------------------------------------*/
9721 /* genPointerSet - stores the value into a pointer location */
9722 /*-----------------------------------------------------------------*/
9723 static void genPointerSet (iCode *ic)
9725 operand *right, *result ;
9726 sym_link *type, *etype;
9730 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9732 right = IC_RIGHT(ic);
9733 result = IC_RESULT(ic) ;
9735 /* depending on the type of pointer we need to
9736 move it to the correct pointer register */
9737 type = operandType(result);
9738 etype = getSpec(type);
9739 /* if left is of type of pointer then it is simple */
9740 if (IS_PTR(type) && !IS_FUNC(type->next)) {
9741 p_type = DCL_TYPE(type);
9744 /* we have to go by the storage class */
9745 p_type = PTR_TYPE(SPEC_OCLS(etype));
9747 /* if (SPEC_OCLS(etype)->codesp ) { */
9748 /* p_type = CPOINTER ; */
9751 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9752 /* p_type = FPOINTER ; */
9754 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9755 /* p_type = PPOINTER ; */
9757 /* if (SPEC_OCLS(etype) == idata ) */
9758 /* p_type = IPOINTER ; */
9760 /* p_type = POINTER ; */
9763 /* now that we have the pointer type we assign
9764 the pointer values */
9770 genNearPointerSet (right,result,ic);
9774 genPagedPointerSet (right,result,ic);
9778 genFarPointerSet (right,result,ic);
9782 genGenPointerSet (right,result,ic);
9786 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9787 "genPointerSet: illegal pointer type");
9791 /*-----------------------------------------------------------------*/
9792 /* genIfx - generate code for Ifx statement */
9793 /*-----------------------------------------------------------------*/
9794 static void genIfx (iCode *ic, iCode *popIc)
9796 operand *cond = IC_COND(ic);
9800 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9802 aopOp(cond,ic,FALSE);
9804 /* get the value into acc */
9805 if (AOP_TYPE(cond) != AOP_CRY)
9806 pic14_toBoolean(cond);
9810 /* if there was something to be popped then do it */
9816 /* This assumes that CARRY is set iff cond is true */
9819 assert (!IC_FALSE(ic));
9820 emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
9822 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9824 assert (IC_FALSE(ic));
9825 emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
9827 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9831 static int hasWarned = 0;
9834 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
9841 /* now Z is set iff !cond */
9844 assert (!IC_FALSE(ic));
9846 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9849 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9855 /* the result is now in the accumulator */
9856 freeAsmop(cond,NULL,ic,TRUE);
9859 /*-----------------------------------------------------------------*/
9860 /* genAddrOf - generates code for address of */
9861 /*-----------------------------------------------------------------*/
9862 static void genAddrOf (iCode *ic)
9864 operand *right, *result, *left;
9868 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9871 //aopOp(IC_RESULT(ic),ic,FALSE);
9873 aopOp((left=IC_LEFT(ic)),ic,FALSE);
9874 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9875 aopOp((result=IC_RESULT(ic)),ic,TRUE);
9877 DEBUGpic14_AopType(__LINE__,left,right,result);
9878 assert (IS_SYMOP (left));
9880 /* sanity check: generic pointers to code space are not yet supported,
9881 * pionters to codespace must not be assigned addresses of __data values. */
9883 fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9884 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)));
9885 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)));
9886 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)));
9887 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)));
9890 if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9891 fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9892 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9893 OP_SYMBOL(left)->name);
9894 } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9895 fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9896 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9897 OP_SYMBOL(left)->name);
9900 size = AOP_SIZE(IC_RESULT(ic));
9901 if (IS_GENPTR(OP_SYM_TYPE(result))) {
9903 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9908 /* fixing bug #863624, reported from (errolv) */
9909 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9910 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9913 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9914 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9919 if (IS_GENPTR(OP_SYM_TYPE(result)))
9921 /* provide correct tag */
9922 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9923 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9924 movwf (AOP(result), 2);
9927 freeAsmop(left,NULL,ic,FALSE);
9928 freeAsmop(result,NULL,ic,TRUE);
9933 /*-----------------------------------------------------------------*/
9934 /* genFarFarAssign - assignment when both are in far space */
9935 /*-----------------------------------------------------------------*/
9936 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9938 int size = AOP_SIZE(right);
9941 /* first push the right side on to the stack */
9943 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9945 pic14_emitcode ("push","acc");
9948 freeAsmop(right,NULL,ic,FALSE);
9949 /* now assign DPTR to result */
9950 aopOp(result,ic,FALSE);
9951 size = AOP_SIZE(result);
9953 pic14_emitcode ("pop","acc");
9954 aopPut(AOP(result),"a",--offset);
9956 freeAsmop(result,NULL,ic,FALSE);
9961 /*-----------------------------------------------------------------*/
9962 /* genAssign - generate code for assignment */
9963 /*-----------------------------------------------------------------*/
9964 static void genAssign (iCode *ic)
9966 operand *result, *right;
9967 int size, offset,know_W;
9968 unsigned long lit = 0L;
9970 result = IC_RESULT(ic);
9971 right = IC_RIGHT(ic) ;
9974 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9976 /* if they are the same */
9977 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9980 aopOp(right,ic,FALSE);
9981 aopOp(result,ic,TRUE);
9983 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9985 /* if they are the same registers */
9986 if (pic14_sameRegs(AOP(right),AOP(result)))
9989 /* special case: assign from __code */
9990 if (!IS_ITEMP(right) /* --> iTemps never reside in __code */
9991 && IS_SYMOP (right) /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
9992 && !IS_FUNC(OP_SYM_TYPE(right)) /* --> we would want its address instead of the first instruction */
9993 && !IS_CODEPTR(OP_SYM_TYPE(right)) /* --> get symbols address instread */
9994 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
9996 emitpComment ("genAssign from CODESPACE");
9997 genConstPointerGet (right, result, ic);
10001 /* just for symmetry reasons... */
10002 if (!IS_ITEMP(result)
10003 && IS_SYMOP (result)
10004 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
10006 assert ( !"cannot write to CODESPACE" );
10009 /* if the result is a bit */
10010 if (AOP_TYPE(result) == AOP_CRY) {
10012 /* if the right size is a literal then
10013 we know what the value is */
10014 if (AOP_TYPE(right) == AOP_LIT) {
10016 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10017 popGet(AOP(result),0));
10019 if (((int) operandLitValue(right)))
10020 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10021 AOP(result)->aopu.aop_dir,
10022 AOP(result)->aopu.aop_dir);
10024 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10025 AOP(result)->aopu.aop_dir,
10026 AOP(result)->aopu.aop_dir);
10030 /* the right is also a bit variable */
10031 if (AOP_TYPE(right) == AOP_CRY) {
10032 emitpcode(POC_BCF, popGet(AOP(result),0));
10033 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10034 emitpcode(POC_BSF, popGet(AOP(result),0));
10036 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10037 AOP(result)->aopu.aop_dir,
10038 AOP(result)->aopu.aop_dir);
10039 pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
10040 AOP(right)->aopu.aop_dir,
10041 AOP(right)->aopu.aop_dir);
10042 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10043 AOP(result)->aopu.aop_dir,
10044 AOP(result)->aopu.aop_dir);
10048 /* we need to or */
10049 emitpcode(POC_BCF, popGet(AOP(result),0));
10050 pic14_toBoolean(right);
10052 emitpcode(POC_BSF, popGet(AOP(result),0));
10053 //aopPut(AOP(result),"a",0);
10057 /* bit variables done */
10059 size = AOP_SIZE(result);
10061 if(AOP_TYPE(right) == AOP_LIT)
10062 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10064 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
10065 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10066 if(aopIdx(AOP(result),0) == 4) {
10067 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10068 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10069 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10072 DEBUGpic14_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
10077 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10078 if(AOP_TYPE(right) == AOP_LIT) {
10080 if(know_W != (int)(lit&0xff))
10081 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10083 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10085 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10089 } else if (AOP_TYPE(right) == AOP_CRY) {
10090 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10092 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10093 emitpcode(POC_INCF, popGet(AOP(result),0));
10096 mov2w_op (right, offset);
10097 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10105 freeAsmop (right,NULL,ic,FALSE);
10106 freeAsmop (result,NULL,ic,TRUE);
10109 /*-----------------------------------------------------------------*/
10110 /* genJumpTab - genrates code for jump table */
10111 /*-----------------------------------------------------------------*/
10112 static void genJumpTab (iCode *ic)
10118 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10120 aopOp(IC_JTCOND(ic),ic,FALSE);
10121 /* get the condition into accumulator */
10122 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10124 /* multiply by three */
10125 pic14_emitcode("add","a,acc");
10126 pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10128 jtab = newiTempLabel(NULL);
10129 pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10130 pic14_emitcode("jmp","@a+dptr");
10131 pic14_emitcode("","%05d_DS_:",jtab->key+100);
10133 emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10134 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10135 emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10136 emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10138 emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10139 emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10140 emitpLabel(jtab->key);
10142 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10144 /* now generate the jump labels */
10145 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10146 jtab = setNextItem(IC_JTLABELS(ic))) {
10147 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10148 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10154 /*-----------------------------------------------------------------*/
10155 /* genMixedOperation - gen code for operators between mixed types */
10156 /*-----------------------------------------------------------------*/
10158 TSD - Written for the PIC port - but this unfortunately is buggy.
10159 This routine is good in that it is able to efficiently promote
10160 types to different (larger) sizes. Unfortunately, the temporary
10161 variables that are optimized out by this routine are sometimes
10162 used in other places. So until I know how to really parse the
10163 iCode tree, I'm going to not be using this routine :(.
10165 static int genMixedOperation (iCode *ic)
10169 operand *result = IC_RESULT(ic);
10170 sym_link *ctype = operandType(IC_LEFT(ic));
10171 operand *right = IC_RIGHT(ic);
10177 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10179 pic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10185 nextright = IC_RIGHT(nextic);
10186 nextleft = IC_LEFT(nextic);
10187 nextresult = IC_RESULT(nextic);
10189 aopOp(right,ic,FALSE);
10190 aopOp(result,ic,FALSE);
10191 aopOp(nextright, nextic, FALSE);
10192 aopOp(nextleft, nextic, FALSE);
10193 aopOp(nextresult, nextic, FALSE);
10195 if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10197 operand *t = right;
10201 pic14_emitcode(";remove right +","");
10203 } else if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10205 operand *t = right;
10209 pic14_emitcode(";remove left +","");
10213 big = AOP_SIZE(nextleft);
10214 small = AOP_SIZE(nextright);
10216 switch(nextic->op) {
10219 pic14_emitcode(";optimize a +","");
10220 /* if unsigned or not an integral type */
10221 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10222 pic14_emitcode(";add a bit to something","");
10225 pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10227 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10228 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10229 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10231 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10239 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10240 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10241 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10244 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10246 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10247 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10248 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10249 pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10250 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10253 pic14_emitcode("rlf","known_zero,w");
10260 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10261 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10262 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10264 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10274 freeAsmop(right,NULL,ic,TRUE);
10275 freeAsmop(result,NULL,ic,TRUE);
10276 freeAsmop(nextright,NULL,ic,TRUE);
10277 freeAsmop(nextleft,NULL,ic,TRUE);
10279 nextic->generated = 1;
10286 /*-----------------------------------------------------------------*/
10287 /* genCast - gen code for casting */
10288 /*-----------------------------------------------------------------*/
10289 static void genCast (iCode *ic)
10291 operand *result = IC_RESULT(ic);
10292 sym_link *restype = operandType(result);
10293 sym_link *rtype = operandType(IC_RIGHT(ic));
10294 operand *right = IC_RIGHT(ic);
10298 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10299 /* if they are equivalent then do nothing */
10300 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10303 aopOp(right,ic,FALSE) ;
10304 aopOp(result,ic,FALSE);
10306 DEBUGpic14_AopType(__LINE__,NULL,right,result);
10308 /* if the result is a bit */
10309 if (AOP_TYPE(result) == AOP_CRY) {
10310 assert(!"assigning to bit variables is not supported");
10313 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10315 size = AOP_SIZE(result);
10317 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10319 emitpcode(POC_CLRF, popGet(AOP(result),0));
10320 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10321 emitpcode(POC_INCF, popGet(AOP(result),0));
10324 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
10329 if (IS_PTR(restype))
10331 operand *result = IC_RESULT(ic);
10332 //operand *left = IC_LEFT(ic);
10333 operand *right = IC_RIGHT(ic);
10336 /* copy common part */
10337 int max, size = AOP_SIZE(result);
10338 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10339 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10341 /* warn if we discard generic opinter tag */
10342 if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10344 //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10350 mov2w_op (right, size);
10351 movwf (AOP(result), size);
10354 /* upcast into generic pointer type? */
10355 if (IS_GENPTR(restype)
10356 && (size < AOP_SIZE(result))
10357 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10359 //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10362 switch (DCL_TYPE(rtype))
10364 case POINTER: /* __data */
10365 case FPOINTER: /* __data */
10366 assert (AOP_SIZE(right) == 2);
10367 tag = GPTRTAG_DATA;
10370 case CPOINTER: /* __code */
10371 assert (AOP_SIZE(right) == 2);
10372 tag = GPTRTAG_CODE;
10375 case GPOINTER: /* unknown destination, __data or __code */
10376 /* assume __data space (address of immediate) */
10377 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10378 if (AOP(right)->code)
10379 tag = GPTRTAG_CODE;
10381 tag = GPTRTAG_DATA;
10385 assert (!"unhandled pointer type");
10388 /* convert other values into pointers to __data space */
10389 tag = GPTRTAG_DATA;
10392 assert (AOP_SIZE(result) == 3);
10394 emitpcode(POC_CLRF, popGet(AOP(result), 2));
10396 emitpcode(POC_MOVLW, popGetLit(tag));
10397 movwf(AOP(result), 2);
10400 addSign(result, max, 0);
10405 /* if they are the same size : or less */
10406 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10408 /* if they are in the same place */
10409 if (pic14_sameRegs(AOP(right),AOP(result)))
10412 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10413 if (IS_PTR_CONST(rtype))
10414 DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10415 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10416 DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10418 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10419 emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10420 emitpcode(POC_MOVWF, popGet(AOP(result),0));
10421 emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10422 emitpcode(POC_MOVWF, popGet(AOP(result),1));
10423 if(AOP_SIZE(result) <2)
10424 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10428 /* if they in different places then copy */
10429 size = AOP_SIZE(result);
10432 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10433 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10435 //aopPut(AOP(result),
10436 // aopGet(AOP(right),offset,FALSE,FALSE),
10445 /* so we now know that the size of destination is greater
10446 than the size of the source.
10447 Now, if the next iCode is an operator then we might be
10448 able to optimize the operation without performing a cast.
10450 if(0 && genMixedOperation(ic)) {
10451 /* XXX: cannot optimize: must copy regs! */
10455 /* we move to result for the size of source */
10456 size = AOP_SIZE(right);
10459 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10460 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10464 addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10467 freeAsmop(right,NULL,ic,TRUE);
10468 freeAsmop(result,NULL,ic,TRUE);
10472 /*-----------------------------------------------------------------*/
10473 /* genDjnz - generate decrement & jump if not zero instrucion */
10474 /*-----------------------------------------------------------------*/
10475 static int genDjnz (iCode *ic, iCode *ifx)
10477 symbol *lbl, *lbl1;
10479 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10484 /* if the if condition has a false label
10485 then we cannot save */
10489 /* if the minus is not of the form
10491 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10492 !IS_OP_LITERAL(IC_RIGHT(ic)))
10495 if (operandLitValue(IC_RIGHT(ic)) != 1)
10498 /* if the size of this greater than one then no
10500 if (getSize(operandType(IC_RESULT(ic))) > 1)
10503 /* otherwise we can save BIG */
10504 lbl = newiTempLabel(NULL);
10505 lbl1= newiTempLabel(NULL);
10507 aopOp(IC_RESULT(ic),ic,FALSE);
10509 if (IS_AOP_PREG(IC_RESULT(ic))) {
10510 pic14_emitcode("dec","%s",
10511 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10512 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10513 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10517 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10518 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10520 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10521 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10524 /* pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10525 /* pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10526 /* pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10527 /* pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10530 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10531 ifx->generated = 1;
10535 /*-----------------------------------------------------------------*/
10536 /* genReceive - generate code for a receive iCode */
10537 /*-----------------------------------------------------------------*/
10538 static void genReceive (iCode *ic)
10541 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10543 if (isOperandInFarSpace(IC_RESULT(ic)) &&
10544 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10545 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10547 int size = getSize(operandType(IC_RESULT(ic)));
10548 int offset = fReturnSizePic - size;
10550 pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10551 fReturn[fReturnSizePic - offset - 1] : "acc"));
10554 aopOp(IC_RESULT(ic),ic,FALSE);
10555 size = AOP_SIZE(IC_RESULT(ic));
10558 pic14_emitcode ("pop","acc");
10559 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10564 aopOp(IC_RESULT(ic),ic,FALSE);
10566 assignResultValue(IC_RESULT(ic));
10569 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10572 /*-----------------------------------------------------------------*/
10573 /* genDummyRead - generate code for dummy read of volatiles */
10574 /*-----------------------------------------------------------------*/
10576 genDummyRead (iCode * ic)
10579 pic14_emitcode ("; genDummyRead","");
10580 pic14_emitcode ("; not implemented","");
10585 /*-----------------------------------------------------------------*/
10586 /* genpic14Code - generate code for pic14 based controllers */
10587 /*-----------------------------------------------------------------*/
10589 * At this point, ralloc.c has gone through the iCode and attempted
10590 * to optimize in a way suitable for a PIC. Now we've got to generate
10591 * PIC instructions that correspond to the iCode.
10593 * Once the instructions are generated, we'll pass through both the
10594 * peep hole optimizer and the pCode optimizer.
10595 *-----------------------------------------------------------------*/
10597 void genpic14Code (iCode *lic)
10604 lineHead = lineCurr = NULL;
10606 pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10609 /* if debug information required */
10610 if (options.debug && currFunc) {
10612 debugFile->writeFunction (currFunc, lic);
10617 for (ic = lic ; ic ; ic = ic->next ) {
10619 //DEBUGpic14_emitcode(";ic","");
10620 //fprintf (stderr, "in ic loop\n");
10621 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10622 //ic->lineno, printCLine(ic->filename, ic->lineno));
10624 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10626 //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10627 cline = printCLine (ic->filename, ic->lineno);
10628 if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10629 addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10630 //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10633 if (options.iCodeInAsm) {
10634 emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10636 /* if the result is marked as
10637 spilt and rematerializable or code for
10638 this has already been generated then
10640 if (resultRemat(ic) || ic->generated )
10643 /* depending on the operation */
10662 /* IPOP happens only when trying to restore a
10663 spilt live range, if there is an ifx statement
10664 following this pop then the if statement might
10665 be using some of the registers being popped which
10666 would destory the contents of the register so
10667 we need to check for this condition and handle it */
10669 ic->next->op == IFX &&
10670 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10671 genIfx (ic->next,ic);
10689 genEndFunction (ic);
10709 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10726 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
10730 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10737 /* note these two are xlated by algebraic equivalence
10738 during parsing SDCC.y */
10739 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10740 "got '>=' or '<=' shouldn't have come here");
10744 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10756 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10760 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10764 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10788 genRightShift (ic);
10791 case GET_VALUE_AT_ADDRESS:
10796 if (POINTER_SET(ic))
10823 addSet(&_G.sendSet,ic);
10826 case DUMMY_READ_VOLATILE:
10831 fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10838 /* now we are ready to call the
10839 peep hole optimizer */
10840 if (!options.nopeep) {
10841 peepHole (&lineHead);
10843 /* now do the actual printing */
10844 printLine (lineHead,codeOutFile);
10847 DFPRINTF((stderr,"printing pBlock\n\n"));
10848 printpBlock(stdout,pb);
10854 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10855 * (meaning: representing its own address) or not (referencing its contents).
10856 * This can only be decided based on the operand's type. */
10858 aop_isLitLike (asmop *aop)
10861 if (aop->type == AOP_LIT) return 1;
10862 if (aop->type == AOP_IMMD) return 1;
10863 if ((aop->type == AOP_PCODE) &&
10864 ((aop->aopu.pcop->type == PO_LITERAL)))
10866 /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10867 * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10874 op_isLitLike (operand *op)
10877 if (aop_isLitLike (AOP(op))) return 1;
10878 if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10879 if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;