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 pic14_emitcode("","%s:",sym->rname);
2890 addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2892 ftype = operandType(IC_LEFT(ic));
2894 /* if critical function then turn interrupts off */
2895 if (IFFUNC_ISCRITICAL(ftype))
2896 pic14_emitcode("clr","ea");
2898 /* here we need to generate the equates for the
2899 register bank if required */
2901 if (FUNC_REGBANK(ftype) != rbank) {
2904 rbank = FUNC_REGBANK(ftype);
2905 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2906 if (strcmp(regspic14[i].base,"0") == 0)
2907 pic14_emitcode("","%s = 0x%02x",
2909 8*rbank+regspic14[i].offset);
2911 pic14_emitcode ("","%s = %s + 0x%02x",
2914 8*rbank+regspic14[i].offset);
2919 /* if this is an interrupt service routine */
2920 if (IFFUNC_ISISR(sym->type)) {
2921 /* already done in pic14createInterruptVect() - delete me
2922 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2923 emitpcodeNULLop(POC_NOP);
2924 emitpcodeNULLop(POC_NOP);
2925 emitpcodeNULLop(POC_NOP);
2927 emitpcode(POC_MOVWF, popCopyReg(&pc_wsave));
2928 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2929 emitpcode(POC_CLRF, popCopyReg(&pc_status));
2930 emitpcode(POC_MOVWF, popCopyReg(&pc_ssave));
2931 emitpcode(POC_MOVFW, popCopyReg(&pc_pclath));
2932 emitpcode(POC_MOVWF, popCopyReg(&pc_psave));
2933 emitpcode(POC_CLRF, popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2935 pBlockConvert2ISR(pb);
2936 pic14_hasInterrupt = 1;
2938 if (!inExcludeList("acc"))
2939 pic14_emitcode ("push","acc");
2940 if (!inExcludeList("b"))
2941 pic14_emitcode ("push","b");
2942 if (!inExcludeList("dpl"))
2943 pic14_emitcode ("push","dpl");
2944 if (!inExcludeList("dph"))
2945 pic14_emitcode ("push","dph");
2946 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2948 pic14_emitcode ("push", "dpx");
2949 /* Make sure we're using standard DPTR */
2950 pic14_emitcode ("push", "dps");
2951 pic14_emitcode ("mov", "dps, #0x00");
2952 if (options.stack10bit)
2954 /* This ISR could conceivably use DPTR2. Better save it. */
2955 pic14_emitcode ("push", "dpl1");
2956 pic14_emitcode ("push", "dph1");
2957 pic14_emitcode ("push", "dpx1");
2960 /* if this isr has no bank i.e. is going to
2961 run with bank 0 , then we need to save more
2963 if (!FUNC_REGBANK(sym->type)) {
2965 /* if this function does not call any other
2966 function then we can be economical and
2967 save only those registers that are used */
2968 if (! IFFUNC_HASFCALL(sym->type)) {
2971 /* if any registers used */
2972 if (sym->regsUsed) {
2973 /* save the registers used */
2974 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2975 if (bitVectBitValue(sym->regsUsed,i) ||
2976 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2977 pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);
2982 /* this function has a function call cannot
2983 determines register usage so we will have the
2985 saverbank(0,ic,FALSE);
2990 /* if callee-save to be used for this function
2991 then save the registers being used in this function */
2992 if (IFFUNC_CALLEESAVES(sym->type)) {
2995 /* if any registers used */
2996 if (sym->regsUsed) {
2997 /* save the registers used */
2998 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2999 if (bitVectBitValue(sym->regsUsed,i) ||
3000 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
3001 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
3009 /* set the register bank to the desired value */
3010 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
3011 pic14_emitcode("push","psw");
3012 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);
3015 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3017 if (options.useXstack) {
3018 pic14_emitcode("mov","r0,%s",spname);
3019 pic14_emitcode("mov","a,_bp");
3020 pic14_emitcode("movx","@r0,a");
3021 pic14_emitcode("inc","%s",spname);
3025 /* set up the stack */
3026 pic14_emitcode ("push","_bp"); /* save the callers stack */
3028 pic14_emitcode ("mov","_bp,%s",spname);
3031 /* adjust the stack for the function */
3036 werror(W_STACK_OVERFLOW,sym->name);
3038 if (i > 3 && sym->recvSize < 4) {
3040 pic14_emitcode ("mov","a,sp");
3041 pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3042 pic14_emitcode ("mov","sp,a");
3047 pic14_emitcode("inc","sp");
3052 pic14_emitcode ("mov","a,_spx");
3053 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3054 pic14_emitcode ("mov","_spx,a");
3059 /*-----------------------------------------------------------------*/
3060 /* genEndFunction - generates epilogue for functions */
3061 /*-----------------------------------------------------------------*/
3062 static void genEndFunction (iCode *ic)
3064 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3068 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3070 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3072 pic14_emitcode ("mov","%s,_bp",spname);
3075 /* if use external stack but some variables were
3076 added to the local stack then decrement the
3078 if (options.useXstack && sym->stack) {
3079 pic14_emitcode("mov","a,sp");
3080 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3081 pic14_emitcode("mov","sp,a");
3085 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3086 if (options.useXstack) {
3087 pic14_emitcode("mov","r0,%s",spname);
3088 pic14_emitcode("movx","a,@r0");
3089 pic14_emitcode("mov","_bp,a");
3090 pic14_emitcode("dec","%s",spname);
3094 pic14_emitcode ("pop","_bp");
3098 /* restore the register bank */
3099 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3100 pic14_emitcode ("pop","psw");
3102 if (IFFUNC_ISISR(sym->type)) {
3104 /* now we need to restore the registers */
3105 /* if this isr has no bank i.e. is going to
3106 run with bank 0 , then we need to save more
3108 if (!FUNC_REGBANK(sym->type)) {
3110 /* if this function does not call any other
3111 function then we can be economical and
3112 save only those registers that are used */
3113 if (! IFFUNC_HASFCALL(sym->type)) {
3116 /* if any registers used */
3117 if (sym->regsUsed) {
3118 /* save the registers used */
3119 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3120 if (bitVectBitValue(sym->regsUsed,i) ||
3121 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3122 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3127 /* this function has a function call cannot
3128 determines register usage so we will have the
3130 unsaverbank(0,ic,FALSE);
3134 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3136 if (options.stack10bit)
3138 pic14_emitcode ("pop", "dpx1");
3139 pic14_emitcode ("pop", "dph1");
3140 pic14_emitcode ("pop", "dpl1");
3142 pic14_emitcode ("pop", "dps");
3143 pic14_emitcode ("pop", "dpx");
3145 if (!inExcludeList("dph"))
3146 pic14_emitcode ("pop","dph");
3147 if (!inExcludeList("dpl"))
3148 pic14_emitcode ("pop","dpl");
3149 if (!inExcludeList("b"))
3150 pic14_emitcode ("pop","b");
3151 if (!inExcludeList("acc"))
3152 pic14_emitcode ("pop","acc");
3154 if (IFFUNC_ISCRITICAL(sym->type))
3155 pic14_emitcode("setb","ea");
3158 /* if debug then send end of function */
3159 /* if (options.debug && currFunc) { */
3161 debugFile->writeEndFunction (currFunc, ic, 1);
3164 pic14_emitcode ("reti","");
3165 emitpcode(POC_MOVFW, popCopyReg(&pc_psave));
3166 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
3167 emitpcode(POC_CLRF, popCopyReg(&pc_status));
3168 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3169 emitpcode(POC_MOVWF, popCopyReg(&pc_status));
3170 emitpcode(POC_SWAPF, popCopyReg(&pc_wsave));
3171 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3172 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3173 emitpcodeNULLop(POC_RETFIE);
3176 if (IFFUNC_ISCRITICAL(sym->type))
3177 pic14_emitcode("setb","ea");
3179 if (IFFUNC_CALLEESAVES(sym->type)) {
3182 /* if any registers used */
3183 if (sym->regsUsed) {
3184 /* save the registers used */
3185 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3186 if (bitVectBitValue(sym->regsUsed,i) ||
3187 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3188 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3194 /* if debug then send end of function */
3196 debugFile->writeEndFunction (currFunc, ic, 1);
3199 pic14_emitcode ("return","");
3200 emitpcodeNULLop(POC_RETURN);
3202 /* Mark the end of a function */
3203 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3208 /*-----------------------------------------------------------------*/
3209 /* genRet - generate code for return statement */
3210 /*-----------------------------------------------------------------*/
3211 static void genRet (iCode *ic)
3213 int size,offset = 0;
3217 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3218 /* if we have no return value then
3219 just generate the "ret" */
3223 /* we have something to return then
3224 move the return value into place */
3225 aopOp(IC_LEFT(ic),ic,FALSE);
3226 size = AOP_SIZE(IC_LEFT(ic));
3228 for (offset = 0; offset < size; offset++)
3230 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
3233 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3236 /* generate a jump to the return label
3237 if the next is not the return statement */
3238 if (!(ic->next && ic->next->op == LABEL &&
3239 IC_LABEL(ic->next) == returnLabel)) {
3241 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3246 /*-----------------------------------------------------------------*/
3247 /* genLabel - generates a label */
3248 /*-----------------------------------------------------------------*/
3249 static void genLabel (iCode *ic)
3253 /* special case never generate */
3254 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3255 if (IC_LABEL(ic) == entryLabel)
3258 emitpLabel(IC_LABEL(ic)->key);
3259 pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3262 /*-----------------------------------------------------------------*/
3263 /* genGoto - generates a goto */
3264 /*-----------------------------------------------------------------*/
3266 static void genGoto (iCode *ic)
3270 emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3271 pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3275 /*-----------------------------------------------------------------*/
3276 /* genMultbits :- multiplication of bits */
3277 /*-----------------------------------------------------------------*/
3278 static void genMultbits (operand *left,
3283 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3285 if(!pic14_sameRegs(AOP(result),AOP(right)))
3286 emitpcode(POC_BSF, popGet(AOP(result),0));
3288 emitpcode(POC_BTFSC,popGet(AOP(right),0));
3289 emitpcode(POC_BTFSS,popGet(AOP(left),0));
3290 emitpcode(POC_BCF, popGet(AOP(result),0));
3295 /*-----------------------------------------------------------------*/
3296 /* genMultOneByte : 8 bit multiplication & division */
3297 /*-----------------------------------------------------------------*/
3298 static void genMultOneByte (operand *left,
3302 char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
3310 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3311 DEBUGpic14_AopType(__LINE__,left,right,result);
3312 DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3314 /* (if two literals, the value is computed before) */
3315 /* if one literal, literal on the right */
3316 if (AOP_TYPE(left) == AOP_LIT){
3322 assert (AOP_SIZE(left) == AOP_SIZE(right));
3324 size = min(AOP_SIZE(result),AOP_SIZE(left));
3325 offset = Gstack_base_addr - (2*size - 1);
3327 /* pass right operand as argument */
3328 for (i=0; i < size; i++)
3330 mov2w (AOP(right), i);
3331 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3334 /* pass left operand as argument */
3335 for (i=0; i < size; i++)
3337 mov2w (AOP(left), i);
3338 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3340 assert (offset == Gstack_base_addr);
3342 /* call library routine */
3343 assert (size > 0 && size <= 4);
3344 call_libraryfunc (func[size]);
3347 movwf (AOP(result), size-1);
3348 for (i=0; i < size - 1; i++)
3350 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
3351 movwf (AOP(result), size - 2 - i);
3354 /* now (zero-/sign) extend the result to its size */
3355 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
3358 /*-----------------------------------------------------------------*/
3359 /* genMult - generates code for multiplication */
3360 /*-----------------------------------------------------------------*/
3361 static void genMult (iCode *ic)
3363 operand *left = IC_LEFT(ic);
3364 operand *right = IC_RIGHT(ic);
3365 operand *result= IC_RESULT(ic);
3369 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3370 /* assign the amsops */
3371 aopOp (left,ic,FALSE);
3372 aopOp (right,ic,FALSE);
3373 aopOp (result,ic,TRUE);
3375 DEBUGpic14_AopType(__LINE__,left,right,result);
3377 /* special cases first */
3379 if (AOP_TYPE(left) == AOP_CRY &&
3380 AOP_TYPE(right)== AOP_CRY) {
3381 genMultbits(left,right,result);
3385 /* if both are of size == 1 */
3386 if (AOP_SIZE(left) == 1 &&
3387 AOP_SIZE(right) == 1 ) {
3388 genMultOneByte(left,right,result);
3392 /* should have been converted to function call */
3396 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3397 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3398 freeAsmop(result,NULL,ic,TRUE);
3401 /*-----------------------------------------------------------------*/
3402 /* genDivbits :- division of bits */
3403 /*-----------------------------------------------------------------*/
3404 static void genDivbits (operand *left,
3413 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3414 /* the result must be bit */
3415 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3416 l = aopGet(AOP(left),0,FALSE,FALSE);
3420 pic14_emitcode("div","ab");
3421 pic14_emitcode("rrc","a");
3422 aopPut(AOP(result),"c",0);
3425 /*-----------------------------------------------------------------*/
3426 /* genDivOneByte : 8 bit division */
3427 /*-----------------------------------------------------------------*/
3428 static void genDivOneByte (operand *left,
3435 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3437 assert (AOP_SIZE(result) == 1);
3438 assert (AOP_SIZE(right) == 1);
3439 assert (AOP_SIZE(left) == 1);
3441 size = min(AOP_SIZE(result),AOP_SIZE(left));
3443 if (AOP_TYPE(right) == AOP_LIT)
3445 /* XXX: might add specialized code */
3448 if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3450 /* unsigned division */
3452 mov2w(AOP(right),0);
3453 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3455 call_libraryfunc("__divuchar");
3456 movwf(AOP(result),0);
3461 temp = popGetTempReg();
3462 lbl = newiTempLabel(NULL);
3464 /* XXX: improve this naive approach:
3465 [result] = [a] / [b]
3466 ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
3470 movwf temp // temp <-- left
3471 movf right,W // W <-- right
3475 subwf temp,F // temp <-- temp - W
3476 skipNC // subwf clears CARRY (i.e. sets BORROW) if temp < W
3478 decf result // we just subtract once too often
3481 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3482 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
3485 emitpcode(POC_MOVWF, temp);
3486 mov2w(AOP(right),0);
3487 emitpcode(POC_CLRF, popGet(AOP(result),0));
3489 emitpLabel(lbl->key);
3490 emitpcode(POC_INCF, popGet(AOP(result),0));
3491 emitpcode(POC_SUBWF, temp);
3493 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3494 emitpcode(POC_DECF, popGet(AOP(result),0));
3499 /* signed division */
3500 mov2w(AOP(right),0);
3501 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3503 call_libraryfunc("__divschar");
3504 movwf(AOP(result),0);
3507 /* now performed the signed/unsigned division -- extend result */
3508 addSign(result, 1, !SPEC_USIGN(operandType(result)));
3511 /*-----------------------------------------------------------------*/
3512 /* genDiv - generates code for division */
3513 /*-----------------------------------------------------------------*/
3514 static void genDiv (iCode *ic)
3516 operand *left = IC_LEFT(ic);
3517 operand *right = IC_RIGHT(ic);
3518 operand *result= IC_RESULT(ic);
3521 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3522 /* assign the amsops */
3523 aopOp (left,ic,FALSE);
3524 aopOp (right,ic,FALSE);
3525 aopOp (result,ic,TRUE);
3527 /* special cases first */
3529 if (AOP_TYPE(left) == AOP_CRY &&
3530 AOP_TYPE(right)== AOP_CRY) {
3531 genDivbits(left,right,result);
3535 /* if both are of size == 1 */
3536 if (AOP_SIZE(left) == 1 &&
3537 AOP_SIZE(right) == 1 ) {
3538 genDivOneByte(left,right,result);
3542 /* should have been converted to function call */
3545 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3546 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3547 freeAsmop(result,NULL,ic,TRUE);
3550 /*-----------------------------------------------------------------*/
3551 /* genModbits :- modulus of bits */
3552 /*-----------------------------------------------------------------*/
3553 static void genModbits (operand *left,
3561 /* the result must be bit */
3562 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3563 l = aopGet(AOP(left),0,FALSE,FALSE);
3567 pic14_emitcode("div","ab");
3568 pic14_emitcode("mov","a,b");
3569 pic14_emitcode("rrc","a");
3570 aopPut(AOP(result),"c",0);
3573 /*-----------------------------------------------------------------*/
3574 /* genModOneByte : 8 bit modulus */
3575 /*-----------------------------------------------------------------*/
3576 static void genModOneByte (operand *left,
3583 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3585 assert (AOP_SIZE(result) == 1);
3586 assert (AOP_SIZE(right) == 1);
3587 assert (AOP_SIZE(left) == 1);
3589 size = min(AOP_SIZE(result),AOP_SIZE(left));
3591 if (AOP_TYPE(right) == AOP_LIT)
3593 /* XXX: might add specialized code */
3596 if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3598 /* unsigned division */
3600 mov2w(AOP(right),0);
3601 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3603 call_libraryfunc("__moduchar");
3604 movwf(AOP(result),0);
3609 lbl = newiTempLabel(NULL);
3611 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3613 /* XXX: improve this naive approach:
3614 [result] = [a] % [b]
3615 ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3619 movwf result // result <-- left
3620 movf right,W // W <-- right
3622 subwf result,F // result <-- result - W
3623 skipNC // subwf clears CARRY (i.e. sets BORROW) if result < W
3625 addwf result, F // we just subtract once too often
3628 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3629 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3631 if (!pic14_sameRegs(AOP(left), AOP(result)))
3634 emitpcode(POC_MOVWF, popGet(AOP(result),0));
3636 mov2w(AOP(right),0);
3638 emitpLabel(lbl->key);
3639 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3641 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3642 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3647 /* signed division */
3648 mov2w(AOP(right),0);
3649 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3651 call_libraryfunc("__modschar");
3652 movwf(AOP(result),0);
3655 /* now we performed the signed/unsigned modulus -- extend result */
3656 addSign(result, 1, !SPEC_USIGN(operandType(result)));
3659 /*-----------------------------------------------------------------*/
3660 /* genMod - generates code for division */
3661 /*-----------------------------------------------------------------*/
3662 static void genMod (iCode *ic)
3664 operand *left = IC_LEFT(ic);
3665 operand *right = IC_RIGHT(ic);
3666 operand *result= IC_RESULT(ic);
3669 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3670 /* assign the amsops */
3671 aopOp (left,ic,FALSE);
3672 aopOp (right,ic,FALSE);
3673 aopOp (result,ic,TRUE);
3675 /* special cases first */
3677 if (AOP_TYPE(left) == AOP_CRY &&
3678 AOP_TYPE(right)== AOP_CRY) {
3679 genModbits(left,right,result);
3683 /* if both are of size == 1 */
3684 if (AOP_SIZE(left) == 1 &&
3685 AOP_SIZE(right) == 1 ) {
3686 genModOneByte(left,right,result);
3690 /* should have been converted to function call */
3694 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3695 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3696 freeAsmop(result,NULL,ic,TRUE);
3699 /*-----------------------------------------------------------------*/
3700 /* genIfxJump :- will create a jump depending on the ifx */
3701 /*-----------------------------------------------------------------*/
3703 note: May need to add parameter to indicate when a variable is in bit space.
3705 static void genIfxJump (iCode *ic, char *jval)
3709 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3710 /* if true label then we jump if condition
3712 if ( IC_TRUE(ic) ) {
3714 if(strcmp(jval,"a") == 0)
3716 else if (strcmp(jval,"c") == 0)
3719 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3720 emitpcode(POC_BTFSC, newpCodeOpBit(jval,-1,1));
3723 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3724 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3728 /* false label is present */
3729 if(strcmp(jval,"a") == 0)
3731 else if (strcmp(jval,"c") == 0)
3734 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3735 emitpcode(POC_BTFSS, newpCodeOpBit(jval,-1,1));
3738 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3739 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3744 /* mark the icode as generated */
3749 /*-----------------------------------------------------------------*/
3751 /*-----------------------------------------------------------------*/
3752 static void genSkip(iCode *ifx,int status_bit)
3758 if ( IC_TRUE(ifx) ) {
3759 switch(status_bit) {
3774 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3775 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3779 switch(status_bit) {
3793 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3794 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3801 /*-----------------------------------------------------------------*/
3803 /*-----------------------------------------------------------------*/
3804 static void genSkipc(resolvedIfx *rifx)
3815 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3816 emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3817 rifx->generated = 1;
3821 /*-----------------------------------------------------------------*/
3823 /*-----------------------------------------------------------------*/
3824 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3830 if( (rifx->condition ^ invert_condition) & 1)
3835 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3836 rifx->generated = 1;
3841 /*-----------------------------------------------------------------*/
3843 /*-----------------------------------------------------------------*/
3844 static void genSkipz(iCode *ifx, int condition)
3847 assert (ifx != NULL);
3855 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3857 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3860 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3862 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3868 /*-----------------------------------------------------------------*/
3870 /*-----------------------------------------------------------------*/
3871 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3878 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3880 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3883 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3884 rifx->generated = 1;
3889 /*-----------------------------------------------------------------*/
3890 /* genChkZeroes :- greater or less than comparison */
3891 /* For each byte in a literal that is zero, inclusive or the */
3892 /* the corresponding byte in the operand with W */
3893 /* returns true if any of the bytes are zero */
3894 /*-----------------------------------------------------------------*/
3895 static int genChkZeroes(operand *op, int lit, int size)
3902 i = (lit >> (size*8)) & 0xff;
3906 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3908 emitpcode(POC_IORFW, popGet(AOP(op),size));
3918 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3919 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
3920 #define DEBUGpc emitpComment
3922 /*-----------------------------------------------------------------*/
3923 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
3924 /* aop (if it's NOT a literal) or from lit (if */
3925 /* aop is a literal) */
3926 /*-----------------------------------------------------------------*/
3927 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3928 if (aop->type == AOP_LIT) {
3929 emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3931 emitpcode (POC_MOVFW, popGet (aop, offset));
3935 /* genCmp performs a left < right comparison, stores
3936 * the outcome in result (if != NULL) and generates
3937 * control flow code for the ifx (if != NULL).
3939 * This version leaves in sequences like
3940 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3941 * which should be optmized by the peephole
3942 * optimizer - RN 2005-01-01 */
3943 static void genCmp (operand *left,operand *right,
3944 operand *result, iCode *ifx, int sign)
3954 int invert_result = 0;
3958 assert (AOP_SIZE(left) == AOP_SIZE(right));
3959 assert (left && right);
3961 size = AOP_SIZE(right) - 1;
3962 mask = (0x100UL << (size*8)) - 1;
3963 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3968 resolveIfx (&rIfx, ifx);
3970 /**********************************************************************
3971 * handle bits - bit compares are promoted to int compares seemingly! *
3972 **********************************************************************/
3974 // THIS IS COMPLETELY UNTESTED!
3975 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3976 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3977 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3978 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3981 // 1 < {0,1} is false --> clear C by skipping the next instruction
3982 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3983 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3984 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3985 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3986 emitCLRC; // only skipped for left=0 && right=1
3988 goto correct_result_in_carry;
3992 /*************************************************
3993 * make sure that left is register (or the like) *
3994 *************************************************/
3995 if (!isAOP_REGlike(left)) {
3996 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
3997 assert (isAOP_LIT(left));
3998 assert (isAOP_REGlike(right));
3999 // swap left and right
4000 // left < right <==> right > left <==> (right >= left + 1)
4001 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4003 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4004 // MAXVALUE < right? always false
4005 if (performedLt) emitCLRC; else emitSETC;
4006 goto correct_result_in_carry;
4009 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4010 // that's why we handled it above.
4017 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4018 } else if (isAOP_LIT(right)) {
4019 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4022 assert (isAOP_REGlike(left)); // left must be register or the like
4023 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4025 /*************************************************
4026 * special cases go here *
4027 *************************************************/
4029 if (isAOP_LIT(right)) {
4031 // unsigned comparison to a literal
4032 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4034 // unsigned left < 0? always false
4035 if (performedLt) emitCLRC; else emitSETC;
4036 goto correct_result_in_carry;
4039 // signed comparison to a literal
4040 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4041 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4042 // signed left < 0x80000000? always false
4043 if (performedLt) emitCLRC; else emitSETC;
4044 goto correct_result_in_carry;
4045 } else if (lit == 0) {
4046 // compare left < 0; set CARRY if SIGNBIT(left) is set
4047 if (performedLt) emitSETC; else emitCLRC;
4048 emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
4049 if (performedLt) emitCLRC; else emitSETC;
4050 goto correct_result_in_carry;
4053 } // right is literal
4055 /*************************************************
4056 * perform a general case comparison *
4057 * make sure we get CARRY==1 <==> left >= right *
4058 *************************************************/
4059 // compare most significant bytes
4060 //DEBUGpc ("comparing bytes at offset %d", size);
4062 // unsigned comparison
4063 pic14_mov2w_regOrLit (AOP(right), lit, size);
4064 emitpcode (POC_SUBFW, popGet (AOP(left), size));
4066 // signed comparison
4067 // (add 2^n to both operands then perform an unsigned comparison)
4068 if (isAOP_LIT(right)) {
4069 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4070 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4072 if (litbyte == 0x80) {
4073 // left >= 0x80 -- always true, but more bytes to come
4074 mov2w (AOP(left), size);
4075 emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
4078 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4079 mov2w (AOP(left), size);
4080 emitpcode (POC_ADDLW, popGetLit (0x80));
4081 emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4084 pCodeOp *pctemp = popGetTempReg();
4085 mov2w (AOP(left), size);
4086 emitpcode (POC_ADDLW, popGetLit (0x80));
4087 emitpcode (POC_MOVWF, pctemp);
4088 mov2w (AOP(right), size);
4089 emitpcode (POC_ADDLW, popGetLit (0x80));
4090 emitpcode (POC_SUBFW, pctemp);
4091 popReleaseTempReg(pctemp);
4095 // compare remaining bytes (treat as unsigned case from above)
4096 templbl = newiTempLabel ( NULL );
4099 //DEBUGpc ("comparing bytes at offset %d", offs);
4101 emitpcode (POC_GOTO, popGetLabel (templbl->key));
4102 pic14_mov2w_regOrLit (AOP(right), lit, offs);
4103 emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4105 emitpLabel (templbl->key);
4106 goto result_in_carry;
4110 /****************************************************
4111 * now CARRY contains the result of the comparison: *
4112 * SUBWF sets CARRY iff *
4113 * F-W >= 0 <==> F >= W <==> !(F < W) *
4114 * (F=left, W=right) *
4115 ****************************************************/
4119 // value will be used in the following genSkipc()
4120 rIfx.condition ^= 1;
4123 correct_result_in_carry:
4125 // assign result to variable (if neccessary)
4126 if (result && AOP_TYPE(result) != AOP_CRY) {
4127 //DEBUGpc ("assign result");
4128 size = AOP_SIZE(result);
4130 emitpcode (POC_CLRF, popGet (AOP(result), size));
4132 if (invert_result) {
4134 emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4136 emitpcode (POC_RLF, popGet (AOP(result), 0));
4140 // perform conditional jump
4142 //DEBUGpc ("generate control flow");
4150 /* OLD VERSION -- BUGGY, DO NOT USE */
4152 /*-----------------------------------------------------------------*/
4153 /* genCmp :- greater or less than comparison */
4154 /*-----------------------------------------------------------------*/
4155 static void genCmp (operand *left,operand *right,
4156 operand *result, iCode *ifx, int sign)
4158 int size; //, offset = 0 ;
4159 unsigned long lit = 0L,i = 0;
4160 resolvedIfx rFalseIfx;
4161 // resolvedIfx rTrueIfx;
4165 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4168 DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4169 DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4173 resolveIfx(&rFalseIfx,ifx);
4174 truelbl = newiTempLabel(NULL);
4175 size = max(AOP_SIZE(left),AOP_SIZE(right));
4177 DEBUGpic14_AopType(__LINE__,left,right,result);
4181 /* if literal is on the right then swap with left */
4182 if ((AOP_TYPE(right) == AOP_LIT)) {
4183 operand *tmp = right ;
4184 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4185 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4188 lit = (lit - 1) & mask;
4191 rFalseIfx.condition ^= 1;
4194 } else if ((AOP_TYPE(left) == AOP_LIT)) {
4195 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4199 //if(IC_TRUE(ifx) == NULL)
4200 /* if left & right are bit variables */
4201 if (AOP_TYPE(left) == AOP_CRY &&
4202 AOP_TYPE(right) == AOP_CRY ) {
4203 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4204 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4206 /* subtract right from left if at the
4207 end the carry flag is set then we know that
4208 left is greater than right */
4210 symbol *lbl = newiTempLabel(NULL);
4213 if(AOP_TYPE(right) == AOP_LIT) {
4215 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4217 DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4224 genSkipCond(&rFalseIfx,left,size-1,7);
4226 /* no need to compare to 0...*/
4227 /* NOTE: this is a de-generate compare that most certainly
4228 * creates some dead code. */
4229 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4231 if(ifx) ifx->generated = 1;
4238 //i = (lit >> (size*8)) & 0xff;
4239 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4241 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4243 i = ((0-lit) & 0xff);
4246 /* lit is 0x7f, all signed chars are less than
4247 * this except for 0x7f itself */
4248 emitpcode(POC_XORLW, popGetLit(0x7f));
4249 genSkipz2(&rFalseIfx,0);
4251 emitpcode(POC_ADDLW, popGetLit(0x80));
4252 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4253 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4258 genSkipz2(&rFalseIfx,1);
4260 emitpcode(POC_ADDLW, popGetLit(i));
4261 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4265 if(ifx) ifx->generated = 1;
4269 /* chars are out of the way. now do ints and longs */
4272 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4279 genSkipCond(&rFalseIfx,left,size,7);
4280 if(ifx) ifx->generated = 1;
4285 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4287 //rFalseIfx.condition ^= 1;
4288 //genSkipCond(&rFalseIfx,left,size,7);
4289 //rFalseIfx.condition ^= 1;
4291 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4292 if(rFalseIfx.condition)
4293 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4295 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4297 emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4298 emitpcode(POC_ADDFW, popGet(AOP(left),0));
4299 emitpcode(POC_MOVFW, popGet(AOP(left),1));
4302 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4304 if(rFalseIfx.condition) {
4306 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4312 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4313 emitpLabel(truelbl->key);
4314 if(ifx) ifx->generated = 1;
4321 if( (lit & 0xff) == 0) {
4322 /* lower byte is zero */
4323 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4324 i = ((lit >> 8) & 0xff) ^0x80;
4325 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4326 emitpcode(POC_ADDLW, popGetLit( 0x80));
4327 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4328 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4331 if(ifx) ifx->generated = 1;
4336 /* Special cases for signed longs */
4337 if( (lit & 0xffffff) == 0) {
4338 /* lower byte is zero */
4339 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4340 i = ((lit >> 8*3) & 0xff) ^0x80;
4341 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4342 emitpcode(POC_ADDLW, popGetLit( 0x80));
4343 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4344 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4347 if(ifx) ifx->generated = 1;
4355 if(lit & (0x80 << (size*8))) {
4356 /* lit is negative */
4357 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4359 //genSkipCond(&rFalseIfx,left,size,7);
4361 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4363 if(rFalseIfx.condition)
4364 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4366 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4370 /* lit is positive */
4371 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4372 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4373 if(rFalseIfx.condition)
4374 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4376 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4380 /* There are no more special cases, so perform a general compare */
4382 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4383 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4387 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4389 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4391 //rFalseIfx.condition ^= 1;
4392 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4394 emitpLabel(truelbl->key);
4396 if(ifx) ifx->generated = 1;
4403 /* sign is out of the way. So now do an unsigned compare */
4404 DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4407 /* General case - compare to an unsigned literal on the right.*/
4409 i = (lit >> (size*8)) & 0xff;
4410 emitpcode(POC_MOVLW, popGetLit(i));
4411 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4413 i = (lit >> (size*8)) & 0xff;
4416 emitpcode(POC_MOVLW, popGetLit(i));
4418 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4420 /* this byte of the lit is zero,
4421 *if it's not the last then OR in the variable */
4423 emitpcode(POC_IORFW, popGet(AOP(left),size));
4428 emitpLabel(lbl->key);
4429 //if(emitFinalCheck)
4430 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4432 emitpLabel(truelbl->key);
4434 if(ifx) ifx->generated = 1;
4441 if(AOP_TYPE(left) == AOP_LIT) {
4442 //symbol *lbl = newiTempLabel(NULL);
4444 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4447 DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4450 if((lit == 0) && (sign == 0)){
4453 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4455 emitpcode(POC_IORFW, popGet(AOP(right),--size));
4457 genSkipz2(&rFalseIfx,0);
4458 if(ifx) ifx->generated = 1;
4465 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4466 /* degenerate compare can never be true */
4467 if(rFalseIfx.condition == 0)
4468 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4470 if(ifx) ifx->generated = 1;
4475 /* signed comparisons to a literal byte */
4477 int lp1 = (lit+1) & 0xff;
4479 DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4482 rFalseIfx.condition ^= 1;
4483 genSkipCond(&rFalseIfx,right,0,7);
4486 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4487 emitpcode(POC_XORLW, popGetLit(0x7f));
4488 genSkipz2(&rFalseIfx,1);
4491 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4492 emitpcode(POC_ADDLW, popGetLit(0x80));
4493 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4494 rFalseIfx.condition ^= 1;
4495 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4498 if(ifx) ifx->generated = 1;
4500 /* unsigned comparisons to a literal byte */
4502 switch(lit & 0xff ) {
4504 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4505 genSkipz2(&rFalseIfx,0);
4506 if(ifx) ifx->generated = 1;
4509 genSkipCond(&rFalseIfx,right,0,7);
4510 if(ifx) ifx->generated = 1;
4514 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4515 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4516 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4517 rFalseIfx.condition ^= 1;
4518 if (AOP_TYPE(result) == AOP_CRY) {
4519 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4520 if(ifx) ifx->generated = 1;
4522 DEBUGpic14_emitcode ("; ***","%s %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4523 emitpcode(POC_CLRF, popGet(AOP(result),0));
4524 emitpcode(POC_RLF, popGet(AOP(result),0));
4525 emitpcode(POC_MOVLW, popGetLit(0x01));
4526 emitpcode(POC_XORWF, popGet(AOP(result),0));
4537 /* Size is greater than 1 */
4545 /* this means lit = 0xffffffff, or -1 */
4548 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4549 rFalseIfx.condition ^= 1;
4550 genSkipCond(&rFalseIfx,right,size,7);
4551 if(ifx) ifx->generated = 1;
4558 if(rFalseIfx.condition) {
4559 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4560 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4563 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4565 emitpcode(POC_IORFW, popGet(AOP(right),size));
4569 if(rFalseIfx.condition) {
4570 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4571 emitpLabel(truelbl->key);
4573 rFalseIfx.condition ^= 1;
4574 genSkipCond(&rFalseIfx,right,s,7);
4577 if(ifx) ifx->generated = 1;
4581 if((size == 1) && (0 == (lp1&0xff))) {
4582 /* lower byte of signed word is zero */
4583 DEBUGpic14_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
4584 i = ((lp1 >> 8) & 0xff) ^0x80;
4585 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4586 emitpcode(POC_ADDLW, popGetLit( 0x80));
4587 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4588 rFalseIfx.condition ^= 1;
4589 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4592 if(ifx) ifx->generated = 1;
4596 if(lit & (0x80 << (size*8))) {
4597 /* Lit is less than zero */
4598 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
4599 //rFalseIfx.condition ^= 1;
4600 //genSkipCond(&rFalseIfx,left,size,7);
4601 //rFalseIfx.condition ^= 1;
4602 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4603 //emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4605 if(rFalseIfx.condition)
4606 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4608 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4612 /* Lit is greater than or equal to zero */
4613 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
4614 //rFalseIfx.condition ^= 1;
4615 //genSkipCond(&rFalseIfx,right,size,7);
4616 //rFalseIfx.condition ^= 1;
4618 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4619 //emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4621 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4622 if(rFalseIfx.condition)
4623 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4625 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4630 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4631 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4635 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4637 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4639 rFalseIfx.condition ^= 1;
4640 //rFalseIfx.condition = 1;
4641 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4643 emitpLabel(truelbl->key);
4645 if(ifx) ifx->generated = 1;
4650 /* compare word or long to an unsigned literal on the right.*/
4655 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4658 break; /* handled above */
4661 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4663 emitpcode(POC_IORFW, popGet(AOP(right),size));
4664 genSkipz2(&rFalseIfx,0);
4668 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4670 emitpcode(POC_IORFW, popGet(AOP(right),size));
4673 if(rFalseIfx.condition)
4674 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4676 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4679 emitpcode(POC_MOVLW, popGetLit(lit+1));
4680 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4682 rFalseIfx.condition ^= 1;
4683 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4686 emitpLabel(truelbl->key);
4688 if(ifx) ifx->generated = 1;
4694 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4695 i = (lit >> (size*8)) & 0xff;
4697 emitpcode(POC_MOVLW, popGetLit(i));
4698 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4701 i = (lit >> (size*8)) & 0xff;
4704 emitpcode(POC_MOVLW, popGetLit(i));
4706 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4708 /* this byte of the lit is zero,
4709 *if it's not the last then OR in the variable */
4711 emitpcode(POC_IORFW, popGet(AOP(right),size));
4716 emitpLabel(lbl->key);
4718 rFalseIfx.condition ^= 1;
4719 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4723 emitpLabel(truelbl->key);
4724 if(ifx) ifx->generated = 1;
4728 /* Compare two variables */
4730 DEBUGpic14_emitcode(";sign","%d",sign);
4734 /* Sigh. thus sucks... */
4736 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4737 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4738 emitpcode(POC_MOVLW, popGetLit(0x80));
4739 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4740 emitpcode(POC_XORFW, popGet(AOP(right),size));
4741 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4743 /* Signed char comparison */
4744 /* Special thanks to Nikolai Golovchenko for this snippet */
4745 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4746 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4747 emitpcode(POC_RRFW, popGet(AOP(left),0)); /* could be any register */
4748 emitpcode(POC_XORFW, popGet(AOP(left),0));
4749 emitpcode(POC_XORFW, popGet(AOP(right),0));
4750 emitpcode(POC_ADDLW, popGetLit(0x80));
4752 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4753 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4755 if(ifx) ifx->generated = 1;
4761 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4762 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4766 /* The rest of the bytes of a multi-byte compare */
4770 emitpcode(POC_GOTO, popGetLabel(lbl->key));
4773 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4774 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4779 emitpLabel(lbl->key);
4781 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4782 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
4783 (AOP_TYPE(result) == AOP_REG)) {
4784 emitpcode(POC_CLRF, popGet(AOP(result),0));
4785 emitpcode(POC_RLF, popGet(AOP(result),0));
4787 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4789 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4790 if(ifx) ifx->generated = 1;
4797 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4798 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4799 pic14_outBitC(result);
4801 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4802 /* if the result is used in the next
4803 ifx conditional branch then generate
4804 code a little differently */
4806 genIfxJump (ifx,"c");
4808 pic14_outBitC(result);
4809 /* leave the result in acc */
4815 /*-----------------------------------------------------------------*/
4816 /* genCmpGt :- greater than comparison */
4817 /*-----------------------------------------------------------------*/
4818 static void genCmpGt (iCode *ic, iCode *ifx)
4820 operand *left, *right, *result;
4821 sym_link *letype , *retype;
4825 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4827 right= IC_RIGHT(ic);
4828 result = IC_RESULT(ic);
4830 letype = getSpec(operandType(left));
4831 retype =getSpec(operandType(right));
4832 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4833 /* assign the amsops */
4834 aopOp (left,ic,FALSE);
4835 aopOp (right,ic,FALSE);
4836 aopOp (result,ic,TRUE);
4838 genCmp(right, left, result, ifx, sign);
4840 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4841 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4842 freeAsmop(result,NULL,ic,TRUE);
4845 /*-----------------------------------------------------------------*/
4846 /* genCmpLt - less than comparisons */
4847 /*-----------------------------------------------------------------*/
4848 static void genCmpLt (iCode *ic, iCode *ifx)
4850 operand *left, *right, *result;
4851 sym_link *letype , *retype;
4855 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4857 right= IC_RIGHT(ic);
4858 result = IC_RESULT(ic);
4860 letype = getSpec(operandType(left));
4861 retype =getSpec(operandType(right));
4862 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4864 /* assign the amsops */
4865 aopOp (left,ic,FALSE);
4866 aopOp (right,ic,FALSE);
4867 aopOp (result,ic,TRUE);
4869 genCmp(left, right, result, ifx, sign);
4871 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4872 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4873 freeAsmop(result,NULL,ic,TRUE);
4877 /*-----------------------------------------------------------------*/
4878 /* genc16bit2lit - compare a 16 bit value to a literal */
4879 /*-----------------------------------------------------------------*/
4880 static void genc16bit2lit(operand *op, int lit, int offset)
4885 DEBUGpic14_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
4886 if( (lit&0xff) == 0)
4891 switch( BYTEofLONG(lit,i)) {
4893 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4896 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4899 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4902 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4903 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4908 switch( BYTEofLONG(lit,i)) {
4910 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4914 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4918 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4921 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4923 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4931 /*-----------------------------------------------------------------*/
4932 /* gencjneshort - compare and jump if not equal */
4933 /*-----------------------------------------------------------------*/
4934 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4936 int size = min(AOP_SIZE(left),AOP_SIZE(right));
4941 //unsigned long lit = 0L;
4943 if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4944 emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4947 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4948 DEBUGpic14_AopType(__LINE__,left,right,result);
4950 assert (!pic14_sameRegs (AOP(left), AOP(result)));
4951 assert (!pic14_sameRegs (AOP(right), AOP(result)));
4952 if (AOP_SIZE(result)) {
4953 for (offset = 0; offset < AOP_SIZE(result); offset++)
4954 emitpcode (POC_CLRF, popGet (AOP(result), offset));
4957 assert (AOP_SIZE(left) == AOP_SIZE(right));
4958 //resolveIfx(&rIfx,ifx);
4959 lbl = newiTempLabel (NULL);
4962 mov2w (AOP(right),size);
4963 emitpcode (POC_XORFW, popGet (AOP(left), size));
4967 emitpcode (POC_GOTO, popGetLabel (lbl->key));
4970 emitpLabel (lbl->key);
4971 if (AOP_SIZE(result)) {
4973 emitpcode (POC_INCF, popGet (AOP(result), 0));
4976 genSkipz (ifx, NULL != IC_TRUE(ifx));
4983 DEBUGpic14_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
4984 assert (!pic14_sameRegs (AOP(result), AOP(left)));
4985 assert (!pic14_sameRegs (AOP(result), AOP(right)));
4986 for (offset=0; offset < AOP_SIZE(result); offset++)
4988 emitpcode (POC_CLRF, popGet (AOP(result), offset));
4993 /* if the left side is a literal or
4994 if the right is in a pointer register and left
4996 if ((AOP_TYPE(left) == AOP_LIT) ||
4997 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5002 if(AOP_TYPE(right) == AOP_LIT)
5003 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5005 /* if the right side is a literal then anything goes */
5006 if (AOP_TYPE(right) == AOP_LIT &&
5007 AOP_TYPE(left) != AOP_DIR ) {
5010 genc16bit2lit(left, lit, 0);
5012 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5018 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5019 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5021 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5025 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5033 /* if the right side is in a register or in direct space or
5034 if the left is a pointer register & right is not */
5035 else if (AOP_TYPE(right) == AOP_REG ||
5036 AOP_TYPE(right) == AOP_DIR ||
5037 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5038 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5039 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5040 int lbl_key = lbl->key;
5043 DEBUGpic14_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
5044 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
5045 __FUNCTION__,__LINE__);
5049 /* switch(size) { */
5051 /* genc16bit2lit(left, lit, 0); */
5053 /* emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
5059 if((AOP_TYPE(left) == AOP_DIR) &&
5060 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5062 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5063 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5065 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5067 switch (lit & 0xff) {
5069 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5072 emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
5073 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5074 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5078 emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5079 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5080 //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5081 emitpcode(POC_GOTO,popGetLabel(lbl_key));
5085 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5086 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5091 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5094 if(AOP_TYPE(result) == AOP_CRY) {
5095 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5100 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5102 /* fix me. probably need to check result size too */
5103 //emitpcode(POC_CLRF,popGet(AOP(result),0));
5108 emitpcode(POC_GOTO,popGetLabel(lbl_key));
5118 } else if(AOP_TYPE(right) == AOP_REG &&
5119 AOP_TYPE(left) != AOP_DIR){
5123 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5124 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5125 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5130 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5135 /* right is a pointer reg need both a & b */
5138 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5140 pic14_emitcode("mov","b,%s",l);
5141 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5142 pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
5147 emitpcode(POC_INCF,popGet(AOP(result),0));
5149 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5151 emitpLabel(lbl->key);
5153 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5162 /*-----------------------------------------------------------------*/
5163 /* gencjne - compare and jump if not equal */
5164 /*-----------------------------------------------------------------*/
5165 static void gencjne(operand *left, operand *right, iCode *ifx)
5167 symbol *tlbl = newiTempLabel(NULL);
5169 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5170 gencjneshort(left, right, lbl);
5172 pic14_emitcode("mov","a,%s",one);
5173 pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5174 pic14_emitcode("","%05d_DS_:",lbl->key+100);
5175 pic14_emitcode("clr","a");
5176 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5178 emitpLabel(lbl->key);
5179 emitpLabel(tlbl->key);
5184 /*-----------------------------------------------------------------*/
5185 /* genCmpEq - generates code for equal to */
5186 /*-----------------------------------------------------------------*/
5187 static void genCmpEq (iCode *ic, iCode *ifx)
5189 operand *left, *right, *result;
5191 symbol *false_label;
5194 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5197 DEBUGpic14_emitcode ("; ifx is non-null","");
5199 DEBUGpic14_emitcode ("; ifx is null","");
5201 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5202 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5203 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5205 DEBUGpic14_AopType(__LINE__,left,right,result);
5207 /* if literal, move literal to right */
5208 if (op_isLitLike (IC_LEFT(ic))) {
5209 operand *tmp = right ;
5215 if (ifx && !IC_TRUE(ifx))
5217 assert (IC_FALSE(ifx));
5218 false_label = IC_FALSE(ifx);
5221 size = min(AOP_SIZE(left),AOP_SIZE(right));
5222 assert(!pic14_sameRegs(AOP(result),AOP(left)));
5223 assert(!pic14_sameRegs(AOP(result),AOP(right)));
5225 /* assume left != right */
5228 for (i=0; i < AOP_SIZE(result); i++)
5230 emitpcode(POC_CLRF, popGet(AOP(result),i));
5234 if (AOP_TYPE(right) == AOP_LIT)
5236 unsigned long lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
5238 size = AOP_SIZE(left);
5239 assert(!op_isLitLike(left));
5244 mov2w(AOP(left), 0);
5245 for (i=1; i < size; i++)
5246 emitpcode(POC_IORFW,popGet(AOP(left),i));
5247 /* now Z is set iff `left == right' */
5249 if (!false_label) false_label = newiTempLabel(NULL);
5250 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5254 for (i=0; i < size; i++)
5257 emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
5258 /* now Z is cleared if `left != right' */
5260 if (!false_label) false_label = newiTempLabel(NULL);
5261 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5268 /* right is no literal */
5271 for (i=0; i < size; i++)
5273 mov2w(AOP(right),i);
5274 emitpcode(POC_XORFW,popGet(AOP(left),i));
5275 /* now Z is cleared if `left != right' */
5277 if (!false_label) false_label = newiTempLabel(NULL);
5278 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5282 /* if we reach here, left == right */
5284 if (AOP_SIZE(result) > 0)
5286 emitpcode(POC_INCF, popGet(AOP(result),0));
5289 if (ifx && IC_TRUE(ifx))
5291 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5294 if (false_label && (!ifx || IC_TRUE(ifx)))
5295 emitpLabel(false_label->key);
5297 if (ifx) ifx->generated = 1;
5299 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5300 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5301 freeAsmop(result,NULL,ic,TRUE);
5304 /*-----------------------------------------------------------------*/
5305 /* ifxForOp - returns the icode containing the ifx for operand */
5306 /*-----------------------------------------------------------------*/
5307 static iCode *ifxForOp ( operand *op, iCode *ic )
5310 /* if true symbol then needs to be assigned */
5311 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5312 if (IS_TRUE_SYMOP(op))
5315 /* if this has register type condition and
5316 the next instruction is ifx with the same operand
5317 and live to of the operand is upto the ifx only then */
5319 ic->next->op == IFX &&
5320 IC_COND(ic->next)->key == op->key &&
5321 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5325 ic->next->op == IFX &&
5326 IC_COND(ic->next)->key == op->key) {
5327 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5331 DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5333 ic->next->op == IFX)
5334 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5337 ic->next->op == IFX &&
5338 IC_COND(ic->next)->key == op->key) {
5339 DEBUGpic14_emitcode ("; "," key is okay");
5340 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5341 OP_SYMBOL(op)->liveTo,
5348 /*-----------------------------------------------------------------*/
5349 /* genAndOp - for && operation */
5350 /*-----------------------------------------------------------------*/
5351 static void genAndOp (iCode *ic)
5353 operand *left,*right, *result;
5357 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5358 /* note here that && operations that are in an
5359 if statement are taken away by backPatchLabels
5360 only those used in arthmetic operations remain */
5361 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5362 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5363 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5365 DEBUGpic14_AopType(__LINE__,left,right,result);
5367 emitpcode(POC_MOVFW,popGet(AOP(left),0));
5368 emitpcode(POC_ANDFW,popGet(AOP(right),0));
5369 emitpcode(POC_MOVWF,popGet(AOP(result),0));
5371 /* if both are bit variables */
5372 /* if (AOP_TYPE(left) == AOP_CRY && */
5373 /* AOP_TYPE(right) == AOP_CRY ) { */
5374 /* pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5375 /* pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5376 /* pic14_outBitC(result); */
5378 /* tlbl = newiTempLabel(NULL); */
5379 /* pic14_toBoolean(left); */
5380 /* pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5381 /* pic14_toBoolean(right); */
5382 /* pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5383 /* pic14_outBitAcc(result); */
5386 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5387 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5388 freeAsmop(result,NULL,ic,TRUE);
5392 /*-----------------------------------------------------------------*/
5393 /* genOrOp - for || operation */
5394 /*-----------------------------------------------------------------*/
5397 modified this code, but it doesn't appear to ever get called
5400 static void genOrOp (iCode *ic)
5402 operand *left,*right, *result;
5406 /* note here that || operations that are in an
5407 if statement are taken away by backPatchLabels
5408 only those used in arthmetic operations remain */
5410 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5411 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5412 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5413 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5415 DEBUGpic14_AopType(__LINE__,left,right,result);
5417 for (i=0; i < AOP_SIZE(result); i++)
5419 emitpcode(POC_CLRF, popGet(AOP(result), i));
5422 tlbl = newiTempLabel(NULL);
5423 pic14_toBoolean(left);
5425 emitpcode(POC_GOTO, popGetLabel(tlbl->key));
5426 pic14_toBoolean(right);
5427 emitpLabel(tlbl->key);
5428 /* here Z is clear IFF `left || right' */
5430 emitpcode(POC_INCF, popGet(AOP(result), 0));
5432 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5433 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5434 freeAsmop(result,NULL,ic,TRUE);
5437 /*-----------------------------------------------------------------*/
5438 /* isLiteralBit - test if lit == 2^n */
5439 /*-----------------------------------------------------------------*/
5440 static int isLiteralBit(unsigned long lit)
5442 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5443 0x100L,0x200L,0x400L,0x800L,
5444 0x1000L,0x2000L,0x4000L,0x8000L,
5445 0x10000L,0x20000L,0x40000L,0x80000L,
5446 0x100000L,0x200000L,0x400000L,0x800000L,
5447 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5448 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5452 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5453 for(idx = 0; idx < 32; idx++)
5459 /*-----------------------------------------------------------------*/
5460 /* continueIfTrue - */
5461 /*-----------------------------------------------------------------*/
5462 static void continueIfTrue (iCode *ic)
5465 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5467 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5471 /*-----------------------------------------------------------------*/
5473 /*-----------------------------------------------------------------*/
5474 static void jumpIfTrue (iCode *ic)
5477 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5479 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5483 /*-----------------------------------------------------------------*/
5484 /* jmpTrueOrFalse - */
5485 /*-----------------------------------------------------------------*/
5486 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5489 // ugly but optimized by peephole
5490 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5492 symbol *nlbl = newiTempLabel(NULL);
5493 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5494 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5495 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5496 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5499 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5500 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5505 /*-----------------------------------------------------------------*/
5506 /* genAnd - code for and */
5507 /*-----------------------------------------------------------------*/
5508 static void genAnd (iCode *ic, iCode *ifx)
5510 operand *left, *right, *result;
5512 unsigned long lit = 0L;
5517 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5518 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5519 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5520 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5522 resolveIfx(&rIfx,ifx);
5524 /* if left is a literal & right is not then exchange them */
5525 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5526 AOP_NEEDSACC(left)) {
5527 operand *tmp = right ;
5532 /* if result = right then exchange them */
5533 if(pic14_sameRegs(AOP(result),AOP(right))){
5534 operand *tmp = right ;
5539 /* if right is bit then exchange them */
5540 if (AOP_TYPE(right) == AOP_CRY &&
5541 AOP_TYPE(left) != AOP_CRY){
5542 operand *tmp = right ;
5546 if(AOP_TYPE(right) == AOP_LIT)
5547 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5549 size = AOP_SIZE(result);
5551 DEBUGpic14_AopType(__LINE__,left,right,result);
5554 // result = bit & yy;
5555 if (AOP_TYPE(left) == AOP_CRY){
5556 // c = bit & literal;
5557 if(AOP_TYPE(right) == AOP_LIT){
5559 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5562 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5565 if(size && (AOP_TYPE(result) == AOP_CRY)){
5566 pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5569 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5573 pic14_emitcode("clr","c");
5576 if (AOP_TYPE(right) == AOP_CRY){
5578 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5579 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5582 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5584 pic14_emitcode("rrc","a");
5585 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5591 pic14_outBitC(result);
5593 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5594 genIfxJump(ifx, "c");
5598 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5599 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5600 if((AOP_TYPE(right) == AOP_LIT) &&
5601 (AOP_TYPE(result) == AOP_CRY) &&
5602 (AOP_TYPE(left) != AOP_CRY)){
5603 int posbit = isLiteralBit(lit);
5607 //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5610 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5615 while (posbit > 7) {
5619 emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5620 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5621 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5628 symbol *tlbl = newiTempLabel(NULL);
5629 int sizel = AOP_SIZE(left);
5631 pic14_emitcode("setb","c");
5633 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5634 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5636 if((posbit = isLiteralBit(bytelit)) != 0)
5637 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5639 if(bytelit != 0x0FFL)
5640 pic14_emitcode("anl","a,%s",
5641 aopGet(AOP(right),offset,FALSE,TRUE));
5642 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5647 // bit = left & literal
5649 pic14_emitcode("clr","c");
5650 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5652 // if(left & literal)
5655 jmpTrueOrFalse(ifx, tlbl);
5659 pic14_outBitC(result);
5663 /* if left is same as result */
5664 if(pic14_sameRegs(AOP(result),AOP(left))){
5666 for(;size--; offset++,lit>>=8) {
5667 if(AOP_TYPE(right) == AOP_LIT){
5668 switch(lit & 0xff) {
5670 /* and'ing with 0 has clears the result */
5671 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5674 /* and'ing with 0xff is a nop when the result and left are the same */
5679 int p = my_powof2( (~lit) & 0xff );
5681 /* only one bit is set in the literal, so use a bcf instruction */
5682 emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5685 if(know_W != (int)(lit&0xff))
5686 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5688 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5693 if (AOP_TYPE(left) == AOP_ACC) {
5694 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5696 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5697 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5704 // left & result in different registers
5705 if(AOP_TYPE(result) == AOP_CRY){
5707 // if(size), result in bit
5708 // if(!size && ifx), conditional oper: if(left & right)
5709 symbol *tlbl = newiTempLabel(NULL);
5710 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5712 pic14_emitcode("setb","c");
5714 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5715 pic14_emitcode("anl","a,%s",
5716 aopGet(AOP(left),offset,FALSE,FALSE));
5717 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5722 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5723 pic14_outBitC(result);
5725 jmpTrueOrFalse(ifx, tlbl);
5727 for(;(size--);offset++) {
5729 // result = left & right
5730 if(AOP_TYPE(right) == AOP_LIT){
5731 int t = (lit >> (offset*8)) & 0x0FFL;
5734 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5737 if(AOP_TYPE(left) != AOP_ACC) {
5738 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5740 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5743 if(AOP_TYPE(left) == AOP_ACC) {
5744 emitpcode(POC_ANDLW, popGetLit(t));
5746 emitpcode(POC_MOVLW, popGetLit(t));
5747 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5749 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5754 if (AOP_TYPE(left) == AOP_ACC) {
5755 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5757 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5758 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5760 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5766 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5767 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5768 freeAsmop(result,NULL,ic,TRUE);
5771 /*-----------------------------------------------------------------*/
5772 /* genOr - code for or */
5773 /*-----------------------------------------------------------------*/
5774 static void genOr (iCode *ic, iCode *ifx)
5776 operand *left, *right, *result;
5778 unsigned long lit = 0L;
5781 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5783 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5784 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5785 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5787 DEBUGpic14_AopType(__LINE__,left,right,result);
5789 /* if left is a literal & right is not then exchange them */
5790 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5791 AOP_NEEDSACC(left)) {
5792 operand *tmp = right ;
5797 /* if result = right then exchange them */
5798 if(pic14_sameRegs(AOP(result),AOP(right))){
5799 operand *tmp = right ;
5804 /* if right is bit then exchange them */
5805 if (AOP_TYPE(right) == AOP_CRY &&
5806 AOP_TYPE(left) != AOP_CRY){
5807 operand *tmp = right ;
5812 DEBUGpic14_AopType(__LINE__,left,right,result);
5814 if(AOP_TYPE(right) == AOP_LIT)
5815 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5817 size = AOP_SIZE(result);
5821 if (AOP_TYPE(left) == AOP_CRY){
5822 if(AOP_TYPE(right) == AOP_LIT){
5823 // c = bit & literal;
5825 // lit != 0 => result = 1
5826 if(AOP_TYPE(result) == AOP_CRY){
5828 emitpcode(POC_BSF, popGet(AOP(result),0));
5829 //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5830 // AOP(result)->aopu.aop_dir,
5831 // AOP(result)->aopu.aop_dir);
5833 continueIfTrue(ifx);
5837 // lit == 0 => result = left
5838 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5840 pic14_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5843 if (AOP_TYPE(right) == AOP_CRY){
5844 if(pic14_sameRegs(AOP(result),AOP(left))){
5846 emitpcode(POC_BCF, popGet(AOP(result),0));
5847 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5848 emitpcode(POC_BSF, popGet(AOP(result),0));
5850 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5851 AOP(result)->aopu.aop_dir,
5852 AOP(result)->aopu.aop_dir);
5853 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5854 AOP(right)->aopu.aop_dir,
5855 AOP(right)->aopu.aop_dir);
5856 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5857 AOP(result)->aopu.aop_dir,
5858 AOP(result)->aopu.aop_dir);
5860 if( AOP_TYPE(result) == AOP_ACC) {
5861 emitpcode(POC_MOVLW, popGetLit(0));
5862 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5863 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5864 emitpcode(POC_MOVLW, popGetLit(1));
5868 emitpcode(POC_BCF, popGet(AOP(result),0));
5869 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5870 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5871 emitpcode(POC_BSF, popGet(AOP(result),0));
5873 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5874 AOP(result)->aopu.aop_dir,
5875 AOP(result)->aopu.aop_dir);
5876 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5877 AOP(right)->aopu.aop_dir,
5878 AOP(right)->aopu.aop_dir);
5879 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5880 AOP(left)->aopu.aop_dir,
5881 AOP(left)->aopu.aop_dir);
5882 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5883 AOP(result)->aopu.aop_dir,
5884 AOP(result)->aopu.aop_dir);
5889 symbol *tlbl = newiTempLabel(NULL);
5890 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5893 emitpcode(POC_BCF, popGet(AOP(result),0));
5894 if( AOP_TYPE(right) == AOP_ACC) {
5895 emitpcode(POC_IORLW, popGetLit(0));
5897 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5898 emitpcode(POC_BSF, popGet(AOP(result),0));
5903 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5904 pic14_emitcode(";XXX setb","c");
5905 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5906 AOP(left)->aopu.aop_dir,tlbl->key+100);
5907 pic14_toBoolean(right);
5908 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5909 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5910 jmpTrueOrFalse(ifx, tlbl);
5914 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5921 pic14_outBitC(result);
5923 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5924 genIfxJump(ifx, "c");
5928 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5929 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5930 if((AOP_TYPE(right) == AOP_LIT) &&
5931 (AOP_TYPE(result) == AOP_CRY) &&
5932 (AOP_TYPE(left) != AOP_CRY)){
5934 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5937 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5939 continueIfTrue(ifx);
5942 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5943 // lit = 0, result = boolean(left)
5945 pic14_emitcode(";XXX setb","c");
5946 pic14_toBoolean(right);
5948 symbol *tlbl = newiTempLabel(NULL);
5949 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5951 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5953 genIfxJump (ifx,"a");
5957 pic14_outBitC(result);
5961 /* if left is same as result */
5962 if(pic14_sameRegs(AOP(result),AOP(left))){
5964 for(;size--; offset++,lit>>=8) {
5965 if(AOP_TYPE(right) == AOP_LIT){
5966 if((lit & 0xff) == 0)
5967 /* or'ing with 0 has no effect */
5970 int p = my_powof2(lit & 0xff);
5972 /* only one bit is set in the literal, so use a bsf instruction */
5974 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5976 if(know_W != (int)(lit & 0xff))
5977 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5978 know_W = lit & 0xff;
5979 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5984 if (AOP_TYPE(left) == AOP_ACC) {
5985 emitpcode(POC_IORFW, popGet(AOP(right),offset));
5986 pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5988 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
5989 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5991 pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5992 pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5998 // left & result in different registers
5999 if(AOP_TYPE(result) == AOP_CRY){
6001 // if(size), result in bit
6002 // if(!size && ifx), conditional oper: if(left | right)
6003 symbol *tlbl = newiTempLabel(NULL);
6004 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6005 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6009 pic14_emitcode(";XXX setb","c");
6011 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6012 pic14_emitcode(";XXX orl","a,%s",
6013 aopGet(AOP(left),offset,FALSE,FALSE));
6014 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6019 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6020 pic14_outBitC(result);
6022 jmpTrueOrFalse(ifx, tlbl);
6023 } else for(;(size--);offset++){
6025 // result = left | right
6026 if(AOP_TYPE(right) == AOP_LIT){
6027 int t = (lit >> (offset*8)) & 0x0FFL;
6030 if (AOP_TYPE(left) != AOP_ACC) {
6031 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
6033 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6037 if (AOP_TYPE(left) == AOP_ACC) {
6038 emitpcode(POC_IORLW, popGetLit(t));
6040 emitpcode(POC_MOVLW, popGetLit(t));
6041 emitpcode(POC_IORFW, popGet(AOP(left),offset));
6043 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6048 // faster than result <- left, anl result,right
6049 // and better if result is SFR
6050 if (AOP_TYPE(left) == AOP_ACC) {
6051 emitpcode(POC_IORFW,popGet(AOP(right),offset));
6053 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6054 emitpcode(POC_IORFW,popGet(AOP(left),offset));
6056 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6061 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6062 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6063 freeAsmop(result,NULL,ic,TRUE);
6066 /*-----------------------------------------------------------------*/
6067 /* genXor - code for xclusive or */
6068 /*-----------------------------------------------------------------*/
6069 static void genXor (iCode *ic, iCode *ifx)
6071 operand *left, *right, *result;
6073 unsigned long lit = 0L;
6076 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6078 aopOp((left = IC_LEFT(ic)),ic,FALSE);
6079 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6080 aopOp((result=IC_RESULT(ic)),ic,TRUE);
6082 /* if left is a literal & right is not ||
6083 if left needs acc & right does not */
6084 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6085 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6086 operand *tmp = right ;
6091 /* if result = right then exchange them */
6092 if(pic14_sameRegs(AOP(result),AOP(right))){
6093 operand *tmp = right ;
6098 /* if right is bit then exchange them */
6099 if (AOP_TYPE(right) == AOP_CRY &&
6100 AOP_TYPE(left) != AOP_CRY){
6101 operand *tmp = right ;
6105 if(AOP_TYPE(right) == AOP_LIT)
6106 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6108 size = AOP_SIZE(result);
6112 if (AOP_TYPE(left) == AOP_CRY){
6113 if(AOP_TYPE(right) == AOP_LIT){
6114 // c = bit & literal;
6116 // lit>>1 != 0 => result = 1
6117 if(AOP_TYPE(result) == AOP_CRY){
6119 {emitpcode(POC_BSF, popGet(AOP(result),offset));
6120 pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6122 continueIfTrue(ifx);
6125 pic14_emitcode("setb","c");
6129 // lit == 0, result = left
6130 if(size && pic14_sameRegs(AOP(result),AOP(left)))
6132 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6134 // lit == 1, result = not(left)
6135 if(size && pic14_sameRegs(AOP(result),AOP(left))){
6136 emitpcode(POC_MOVLW, popGet(AOP(result),offset));
6137 emitpcode(POC_XORWF, popGet(AOP(result),offset));
6138 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6141 assert ( !"incomplete genXor" );
6142 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6143 pic14_emitcode("cpl","c");
6150 symbol *tlbl = newiTempLabel(NULL);
6151 if (AOP_TYPE(right) == AOP_CRY){
6153 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6156 int sizer = AOP_SIZE(right);
6158 // if val>>1 != 0, result = 1
6159 pic14_emitcode("setb","c");
6161 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6163 // test the msb of the lsb
6164 pic14_emitcode("anl","a,#0xfe");
6165 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6169 pic14_emitcode("rrc","a");
6171 pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6172 pic14_emitcode("cpl","c");
6173 pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6178 pic14_outBitC(result);
6180 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6181 genIfxJump(ifx, "c");
6185 if(pic14_sameRegs(AOP(result),AOP(left))){
6186 /* if left is same as result */
6187 for(;size--; offset++) {
6188 if(AOP_TYPE(right) == AOP_LIT){
6189 int t = (lit >> (offset*8)) & 0x0FFL;
6193 if (IS_AOP_PREG(left)) {
6194 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6195 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6196 aopPut(AOP(result),"a",offset);
6198 emitpcode(POC_MOVLW, popGetLit(t));
6199 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6200 pic14_emitcode("xrl","%s,%s",
6201 aopGet(AOP(left),offset,FALSE,TRUE),
6202 aopGet(AOP(right),offset,FALSE,FALSE));
6205 if (AOP_TYPE(left) == AOP_ACC)
6206 pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6208 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6209 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6211 if (IS_AOP_PREG(left)) {
6212 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6213 aopPut(AOP(result),"a",offset);
6215 pic14_emitcode("xrl","%s,a",
6216 aopGet(AOP(left),offset,FALSE,TRUE));
6222 // left & result in different registers
6223 if(AOP_TYPE(result) == AOP_CRY){
6225 // if(size), result in bit
6226 // if(!size && ifx), conditional oper: if(left ^ right)
6227 symbol *tlbl = newiTempLabel(NULL);
6228 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6230 pic14_emitcode("setb","c");
6232 if((AOP_TYPE(right) == AOP_LIT) &&
6233 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6234 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6236 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6237 pic14_emitcode("xrl","a,%s",
6238 aopGet(AOP(left),offset,FALSE,FALSE));
6240 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6245 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6246 pic14_outBitC(result);
6248 jmpTrueOrFalse(ifx, tlbl);
6249 } else for(;(size--);offset++){
6251 // result = left & right
6252 if(AOP_TYPE(right) == AOP_LIT){
6253 int t = (lit >> (offset*8)) & 0x0FFL;
6256 if (AOP_TYPE(left) != AOP_ACC) {
6257 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6259 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6260 pic14_emitcode("movf","%s,w",
6261 aopGet(AOP(left),offset,FALSE,FALSE));
6262 pic14_emitcode("movwf","%s",
6263 aopGet(AOP(result),offset,FALSE,FALSE));
6266 if (AOP_TYPE(left) == AOP_ACC) {
6267 emitpcode(POC_XORLW, popGetLit(t));
6269 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6271 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6274 if (AOP_TYPE(left) == AOP_ACC) {
6275 emitpcode(POC_XORLW, popGetLit(t));
6277 emitpcode(POC_MOVLW, popGetLit(t));
6278 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6280 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6281 pic14_emitcode("movlw","0x%x",t);
6282 pic14_emitcode("xorwf","%s,w",
6283 aopGet(AOP(left),offset,FALSE,FALSE));
6284 pic14_emitcode("movwf","%s",
6285 aopGet(AOP(result),offset,FALSE,FALSE));
6291 // faster than result <- left, anl result,right
6292 // and better if result is SFR
6293 if (AOP_TYPE(left) == AOP_ACC) {
6294 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6296 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6297 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6299 if ( AOP_TYPE(result) != AOP_ACC){
6300 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6306 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6307 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6308 freeAsmop(result,NULL,ic,TRUE);
6311 /*-----------------------------------------------------------------*/
6312 /* genInline - write the inline code out */
6313 /*-----------------------------------------------------------------*/
6314 static void genInline (iCode *ic)
6316 char *buffer, *bp, *bp1;
6319 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6321 _G.inLine += (!options.asmpeep);
6323 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6324 strcpy(buffer,IC_INLINE(ic));
6326 /* emit each line as a code */
6332 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6340 /* print label, use this special format with NULL directive
6341 * to denote that the argument should not be indented with tab */
6342 addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6349 if ((bp1 != bp) && *bp1)
6350 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6354 _G.inLine -= (!options.asmpeep);
6357 /*-----------------------------------------------------------------*/
6358 /* genRRC - rotate right with carry */
6359 /*-----------------------------------------------------------------*/
6360 static void genRRC (iCode *ic)
6362 operand *left , *result ;
6363 int size, offset = 0, same;
6366 /* rotate right with carry */
6368 result=IC_RESULT(ic);
6369 aopOp (left,ic,FALSE);
6370 aopOp (result,ic,FALSE);
6372 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6374 same = pic14_sameRegs(AOP(result),AOP(left));
6376 size = AOP_SIZE(result);
6378 /* get the lsb and put it into the carry */
6379 emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6386 emitpcode(POC_RRF, popGet(AOP(left),offset));
6388 emitpcode(POC_RRFW, popGet(AOP(left),offset));
6389 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6395 freeAsmop(left,NULL,ic,TRUE);
6396 freeAsmop(result,NULL,ic,TRUE);
6399 /*-----------------------------------------------------------------*/
6400 /* genRLC - generate code for rotate left with carry */
6401 /*-----------------------------------------------------------------*/
6402 static void genRLC (iCode *ic)
6404 operand *left , *result ;
6405 int size, offset = 0;
6409 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6410 /* rotate right with carry */
6412 result=IC_RESULT(ic);
6413 aopOp (left,ic,FALSE);
6414 aopOp (result,ic,FALSE);
6416 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6418 same = pic14_sameRegs(AOP(result),AOP(left));
6420 /* move it to the result */
6421 size = AOP_SIZE(result);
6423 /* get the msb and put it into the carry */
6424 emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6431 emitpcode(POC_RLF, popGet(AOP(left),offset));
6433 emitpcode(POC_RLFW, popGet(AOP(left),offset));
6434 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6441 freeAsmop(left,NULL,ic,TRUE);
6442 freeAsmop(result,NULL,ic,TRUE);
6445 /*-----------------------------------------------------------------*/
6446 /* genGetHbit - generates code get highest order bit */
6447 /*-----------------------------------------------------------------*/
6448 static void genGetHbit (iCode *ic)
6450 operand *left, *result;
6452 result=IC_RESULT(ic);
6453 aopOp (left,ic,FALSE);
6454 aopOp (result,ic,FALSE);
6457 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6458 /* get the highest order byte into a */
6459 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6460 if(AOP_TYPE(result) == AOP_CRY){
6461 pic14_emitcode("rlc","a");
6462 pic14_outBitC(result);
6465 pic14_emitcode("rl","a");
6466 pic14_emitcode("anl","a,#0x01");
6467 pic14_outAcc(result);
6471 freeAsmop(left,NULL,ic,TRUE);
6472 freeAsmop(result,NULL,ic,TRUE);
6475 /*-----------------------------------------------------------------*/
6476 /* AccLsh - shift left accumulator by known count */
6477 /* MARK: pic14 always rotates through CARRY! */
6478 /*-----------------------------------------------------------------*/
6479 static void AccLsh (pCodeOp *pcop,int shCount)
6482 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6483 shCount &= 0x0007; // shCount : 0..7
6490 emitpcode(POC_RLF,pcop);
6494 emitpcode(POC_RLF,pcop);
6495 emitpcode(POC_RLF,pcop);
6498 emitpcode(POC_RLF,pcop);
6499 emitpcode(POC_RLF,pcop);
6500 emitpcode(POC_RLF,pcop);
6503 emitpcode(POC_SWAPF,pcop);
6506 emitpcode(POC_SWAPF,pcop);
6507 emitpcode(POC_RLF,pcop);
6510 emitpcode(POC_SWAPF,pcop);
6511 emitpcode(POC_RLF,pcop);
6512 emitpcode(POC_RLF,pcop);
6515 emitpcode(POC_RRFW,pcop);
6516 emitpcode(POC_RRF,pcop);
6519 /* clear invalid bits */
6520 emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6521 emitpcode(POC_ANDWF, pcop);
6524 /*-----------------------------------------------------------------*/
6525 /* AccRsh - shift right accumulator by known count */
6526 /* MARK: pic14 always rotates through CARRY! */
6527 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6528 /* 1: mask out invalid bits (zero-extend) */
6529 /* 2: sign-extend result (pretty slow) */
6530 /*-----------------------------------------------------------------*/
6531 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6534 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6535 shCount &= 0x0007; // shCount : 0..7
6541 /* load sign if needed */
6542 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6543 else if (mask_mode == 1) emitCLRC;
6544 emitpcode(POC_RRF,pcop);
6548 /* load sign if needed */
6549 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6550 emitpcode(POC_RRF,pcop);
6551 /* load sign if needed */
6552 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6553 emitpcode(POC_RRF,pcop);
6554 if (mask_mode == 2) return;
6557 /* load sign if needed */
6558 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6559 emitpcode(POC_RRF,pcop);
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 if (mask_mode == 2) return;
6569 emitpcode(POC_SWAPF,pcop);
6572 emitpcode(POC_SWAPF,pcop);
6573 emitpcode(POC_RRF,pcop);
6576 emitpcode(POC_SWAPF,pcop);
6577 emitpcode(POC_RRF,pcop);
6578 emitpcode(POC_RRF,pcop);
6584 emitpcode(POC_RLFW,pcop);
6585 emitpcode(POC_CLRF,pcop);
6587 emitpcode(POC_COMF,pcop);
6590 emitpcode(POC_RLFW,pcop);
6591 emitpcode(POC_RLF,pcop);
6598 /* leave invalid bits undefined */
6602 /* clear invalid bits -- zero-extend */
6603 emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6604 emitpcode(POC_ANDWF, pcop);
6606 if (mask_mode == 2) {
6608 emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6609 emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6610 emitpcode(POC_IORWF, pcop);
6615 /*-----------------------------------------------------------------*/
6616 /* AccSRsh - signed right shift accumulator by known count */
6617 /*-----------------------------------------------------------------*/
6618 static void AccSRsh (int shCount)
6621 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6624 pic14_emitcode("mov","c,acc.7");
6625 pic14_emitcode("rrc","a");
6626 } else if(shCount == 2){
6627 pic14_emitcode("mov","c,acc.7");
6628 pic14_emitcode("rrc","a");
6629 pic14_emitcode("mov","c,acc.7");
6630 pic14_emitcode("rrc","a");
6632 tlbl = newiTempLabel(NULL);
6633 /* rotate right accumulator */
6634 AccRol(8 - shCount);
6635 /* and kill the higher order bits */
6636 pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6637 pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6638 pic14_emitcode("orl","a,#0x%02x",
6639 (unsigned char)~SRMask[shCount]);
6640 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6645 /*-----------------------------------------------------------------*/
6646 /* shiftR1Left2Result - shift right one byte from left to result */
6647 /*-----------------------------------------------------------------*/
6648 static void shiftR1Left2ResultSigned (operand *left, int offl,
6649 operand *result, int offr,
6655 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6657 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6661 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6663 emitpcode(POC_RRF, popGet(AOP(result),offr));
6665 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6666 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6672 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6674 emitpcode(POC_RRF, popGet(AOP(result),offr));
6676 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6677 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6679 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6680 emitpcode(POC_RRF, popGet(AOP(result),offr));
6686 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6688 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6689 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6692 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6693 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6694 emitpcode(POC_ANDLW, popGetLit(0x1f));
6696 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6697 emitpcode(POC_IORLW, popGetLit(0xe0));
6699 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6703 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6704 emitpcode(POC_ANDLW, popGetLit(0x0f));
6705 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6706 emitpcode(POC_IORLW, popGetLit(0xf0));
6707 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6711 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6713 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6714 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6716 emitpcode(POC_RRFW, popGet(AOP(result),offr));
6717 emitpcode(POC_ANDLW, popGetLit(0x07));
6718 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6719 emitpcode(POC_IORLW, popGetLit(0xf8));
6720 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6725 emitpcode(POC_MOVLW, popGetLit(0x00));
6726 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6727 emitpcode(POC_MOVLW, popGetLit(0xfe));
6728 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6729 emitpcode(POC_IORLW, popGetLit(0x01));
6730 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6732 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6733 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6734 emitpcode(POC_DECF, popGet(AOP(result),offr));
6735 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6736 emitpcode(POC_BCF, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6742 emitpcode(POC_MOVLW, popGetLit(0x00));
6743 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6744 emitpcode(POC_MOVLW, popGetLit(0xff));
6745 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6747 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6748 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6749 emitpcode(POC_DECF, popGet(AOP(result),offr));
6757 /*-----------------------------------------------------------------*/
6758 /* shiftR1Left2Result - shift right one byte from left to result */
6759 /*-----------------------------------------------------------------*/
6760 static void shiftR1Left2Result (operand *left, int offl,
6761 operand *result, int offr,
6762 int shCount, int sign)
6767 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6769 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6771 /* Copy the msb into the carry if signed. */
6773 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6783 emitpcode(POC_RRF, popGet(AOP(result),offr));
6785 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6786 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6792 emitpcode(POC_RRF, popGet(AOP(result),offr));
6794 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6795 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6798 emitpcode(POC_RRF, popGet(AOP(result),offr));
6803 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6805 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6806 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6809 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6810 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6811 emitpcode(POC_ANDLW, popGetLit(0x1f));
6812 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6816 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6817 emitpcode(POC_ANDLW, popGetLit(0x0f));
6818 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6822 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6823 emitpcode(POC_ANDLW, popGetLit(0x0f));
6824 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6826 emitpcode(POC_RRF, popGet(AOP(result),offr));
6831 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6832 emitpcode(POC_ANDLW, popGetLit(0x80));
6833 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6834 emitpcode(POC_RLF, popGet(AOP(result),offr));
6835 emitpcode(POC_RLF, popGet(AOP(result),offr));
6840 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6841 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6842 emitpcode(POC_RLF, popGet(AOP(result),offr));
6851 /*-----------------------------------------------------------------*/
6852 /* shiftL1Left2Result - shift left one byte from left to result */
6853 /*-----------------------------------------------------------------*/
6854 static void shiftL1Left2Result (operand *left, int offl,
6855 operand *result, int offr, int shCount)
6861 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6863 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6864 DEBUGpic14_emitcode ("; ***","same = %d",same);
6865 // l = aopGet(AOP(left),offl,FALSE,FALSE);
6867 /* shift left accumulator */
6868 //AccLsh(shCount); // don't comment out just yet...
6869 // aopPut(AOP(result),"a",offr);
6873 /* Shift left 1 bit position */
6874 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6876 emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6878 emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6879 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6883 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6884 emitpcode(POC_ANDLW,popGetLit(0x7e));
6885 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6886 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6889 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6890 emitpcode(POC_ANDLW,popGetLit(0x3e));
6891 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6892 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6893 emitpcode(POC_RLF, popGet(AOP(result),offr));
6896 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6897 emitpcode(POC_ANDLW, popGetLit(0xf0));
6898 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6901 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6902 emitpcode(POC_ANDLW, popGetLit(0xf0));
6903 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6904 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6907 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6908 emitpcode(POC_ANDLW, popGetLit(0x30));
6909 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6910 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6911 emitpcode(POC_RLF, popGet(AOP(result),offr));
6914 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6915 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6916 emitpcode(POC_RRF, popGet(AOP(result),offr));
6920 DEBUGpic14_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6926 /*-----------------------------------------------------------------*/
6927 /* movLeft2Result - move byte from left to result */
6928 /*-----------------------------------------------------------------*/
6929 static void movLeft2Result (operand *left, int offl,
6930 operand *result, int offr)
6934 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6935 if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6936 l = aopGet(AOP(left),offl,FALSE,FALSE);
6938 if (*l == '@' && (IS_AOP_PREG(result))) {
6939 pic14_emitcode("mov","a,%s",l);
6940 aopPut(AOP(result),"a",offr);
6942 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6943 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6948 /*-----------------------------------------------------------------*/
6949 /* shiftLeft_Left2ResultLit - shift left by known count */
6950 /*-----------------------------------------------------------------*/
6952 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6954 int size, same, offr, i;
6956 size = AOP_SIZE(left);
6957 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6959 same = pic14_sameRegs (AOP(left), AOP(result));
6962 shCount = shCount & 0x07;
6968 case 0: /* takes 0 or 2N cycles (for offr==0) */
6969 if (!same || offr) {
6970 for (i=size-1; i >= 0; i--)
6971 movLeft2Result (left, i, result, offr + i);
6975 case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6977 shiftLeft_Left2ResultLit (left, result, 8 * offr);
6978 shiftLeft_Left2ResultLit (result, result, shCount);
6979 return; /* prevent clearing result again */
6982 for (i=0; i < size; i++) {
6983 if (same && !offr) {
6984 emitpcode (POC_RLF, popGet (AOP(left), i));
6986 emitpcode (POC_RLFW, popGet (AOP(left), i));
6987 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6993 case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
6994 /* works in-place/with offr as well */
6995 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
6996 emitpcode (POC_ANDLW, popGetLit (0xF0));
6997 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
6999 for (i = size - 2; i >= 0; i--)
7001 emitpcode (POC_SWAPFW, popGet (AOP(left), i));
7002 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7003 emitpcode (POC_ANDLW, popGetLit (0x0F));
7004 emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
7005 emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
7009 case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
7010 /* works in-place/with offr as well */
7011 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
7012 for (i = size-2; i >= 0; i--) {
7013 emitpcode (POC_RRFW, popGet (AOP(left), i));
7014 emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
7016 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7017 emitpcode (POC_RRF, popGet (AOP(result), offr));
7021 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
7022 shiftLeft_Left2ResultLit (result, result, 1);
7023 return; /* prevent clearing result again */
7029 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7033 /*-----------------------------------------------------------------*/
7034 /* shiftRight_Left2ResultLit - shift right by known count */
7035 /*-----------------------------------------------------------------*/
7037 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
7039 int size, same, offr, i;
7041 size = AOP_SIZE(left);
7042 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7044 same = pic14_sameRegs (AOP(left), AOP(result));
7047 shCount = shCount & 0x07;
7055 case 0: /* takes 0 or 2N cycles (for offr==0) */
7056 if (!same || offr) {
7057 for (i=0; i < size; i++)
7058 movLeft2Result (left, i + offr, result, i);
7062 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7063 emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7065 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7066 shiftRight_Left2ResultLit (result, result, shCount, sign);
7067 return; /* prevent sign-extending result again */
7071 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7074 for (i = size-1; i >= 0; i--) {
7075 if (same && !offr) {
7076 emitpcode (POC_RRF, popGet (AOP(left), i));
7078 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7079 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7085 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7086 /* works in-place/with offr as well */
7087 emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7088 emitpcode (POC_ANDLW, popGetLit (0x0F));
7089 emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7091 for (i = 1; i < size; i++)
7093 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7094 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7095 emitpcode (POC_ANDLW, popGetLit (0xF0));
7096 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7097 emitpcode (POC_XORWF, popGet (AOP(result), i));
7102 emitpcode (POC_MOVLW, popGetLit (0xF0));
7103 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7104 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7108 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7109 /* works in-place/with offr as well */
7110 emitpcode (POC_RLFW, popGet (AOP(left), offr));
7111 for (i = 0; i < size-1; i++) {
7112 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7113 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7115 emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7117 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7120 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7125 shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7126 shiftRight_Left2ResultLit (result, result, 1, sign);
7127 return; /* prevent sign extending result again */
7132 addSign (result, size, sign);
7136 /*-----------------------------------------------------------------*/
7137 /* shiftL2Left2Result - shift left two bytes from left to result */
7138 /*-----------------------------------------------------------------*/
7139 static void shiftL2Left2Result (operand *left, int offl,
7140 operand *result, int offr, int shCount)
7144 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7146 if(pic14_sameRegs(AOP(result), AOP(left))) {
7154 emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7155 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7156 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7160 emitpcode(POC_RLF, popGet(AOP(result),offr));
7161 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7167 emitpcode(POC_MOVLW, popGetLit(0x0f));
7168 emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7169 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7170 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7171 emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7172 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7173 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7175 emitpcode(POC_RLF, popGet(AOP(result),offr));
7176 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7180 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7181 emitpcode(POC_RRF, popGet(AOP(result),offr));
7182 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7183 emitpcode(POC_RRF, popGet(AOP(result),offr));
7184 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7185 emitpcode(POC_ANDLW,popGetLit(0xc0));
7186 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7187 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7188 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7189 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7192 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7193 emitpcode(POC_RRFW, popGet(AOP(result),offr));
7194 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7195 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7196 emitpcode(POC_RRF, popGet(AOP(result),offr));
7206 /* note, use a mov/add for the shift since the mov has a
7207 chance of getting optimized out */
7208 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7209 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7210 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7211 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7212 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7216 emitpcode(POC_RLF, popGet(AOP(result),offr));
7217 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7223 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7224 emitpcode(POC_ANDLW, popGetLit(0xF0));
7225 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7226 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7227 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7228 emitpcode(POC_ANDLW, popGetLit(0xF0));
7229 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7230 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7234 emitpcode(POC_RLF, popGet(AOP(result),offr));
7235 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7239 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7240 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7241 emitpcode(POC_RRFW, popGet(AOP(result),offl));
7242 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7244 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7245 emitpcode(POC_RRF, popGet(AOP(result),offr));
7246 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7247 emitpcode(POC_ANDLW,popGetLit(0xc0));
7248 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7249 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7250 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7251 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7254 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7255 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7256 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7257 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7258 emitpcode(POC_RRF, popGet(AOP(result),offr));
7264 /*-----------------------------------------------------------------*/
7265 /* shiftR2Left2Result - shift right two bytes from left to result */
7266 /*-----------------------------------------------------------------*/
7267 static void shiftR2Left2Result (operand *left, int offl,
7268 operand *result, int offr,
7269 int shCount, int sign)
7274 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7275 same = pic14_sameRegs(AOP(result), AOP(left));
7277 if(same && ((offl + MSB16) == offr)){
7279 /* don't crash result[offr] */
7280 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7281 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7284 movLeft2Result(left,offl, result, offr);
7285 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7288 /* a:x >> shCount (x = lsb(result))*/
7291 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7293 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7302 emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7307 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7308 emitpcode(POC_RRF,popGet(AOP(result),offr));
7310 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7311 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7312 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7313 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7318 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7321 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7322 emitpcode(POC_RRF,popGet(AOP(result),offr));
7329 emitpcode(POC_MOVLW, popGetLit(0xf0));
7330 emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7331 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7333 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7334 emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7335 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7336 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7338 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7339 emitpcode(POC_ANDLW, popGetLit(0x0f));
7340 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7342 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7343 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7344 emitpcode(POC_ANDLW, popGetLit(0xf0));
7345 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7346 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7350 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7351 emitpcode(POC_RRF, popGet(AOP(result),offr));
7355 emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7356 emitpcode(POC_BTFSC,
7357 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7358 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7366 emitpcode(POC_RLF, popGet(AOP(result),offr));
7367 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7369 emitpcode(POC_RLF, popGet(AOP(result),offr));
7370 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7371 emitpcode(POC_RLFW, popGet(AOP(result),offr));
7372 emitpcode(POC_ANDLW,popGetLit(0x03));
7374 emitpcode(POC_BTFSC,
7375 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7376 emitpcode(POC_IORLW,popGetLit(0xfc));
7378 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7379 emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7380 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7381 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7383 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7384 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7385 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7386 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7387 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7388 emitpcode(POC_RLF, popGet(AOP(result),offr));
7389 emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7390 emitpcode(POC_ANDLW,popGetLit(0x03));
7392 emitpcode(POC_BTFSC,
7393 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7394 emitpcode(POC_IORLW,popGetLit(0xfc));
7396 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7397 //emitpcode(POC_RLF, popGet(AOP(result),offr));
7404 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7405 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7406 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7407 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7410 emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7412 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7416 /*-----------------------------------------------------------------*/
7417 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7418 /*-----------------------------------------------------------------*/
7419 static void shiftLLeftOrResult (operand *left, int offl,
7420 operand *result, int offr, int shCount)
7423 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7425 /* shift left accumulator */
7426 AccLsh(left,offl,shCount);
7427 /* or with result */
7428 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7429 assert ( !"broken (modifies left, fails for left==result))" );
7432 /*-----------------------------------------------------------------*/
7433 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7434 /*-----------------------------------------------------------------*/
7435 static void shiftRLeftOrResult (operand *left, int offl,
7436 operand *result, int offr, int shCount)
7439 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7441 /* shift right accumulator */
7442 AccRsh(left,offl,shCount);
7443 /* or with result */
7444 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7445 assert ( !"broken (modifies left, fails for left==result))" );
7448 /*-----------------------------------------------------------------*/
7449 /* genlshOne - left shift a one byte quantity by known count */
7450 /*-----------------------------------------------------------------*/
7451 static void genlshOne (operand *result, operand *left, int shCount)
7454 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7455 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7458 /*-----------------------------------------------------------------*/
7459 /* genlshTwo - left shift two bytes by known amount != 0 */
7460 /*-----------------------------------------------------------------*/
7461 static void genlshTwo (operand *result,operand *left, int shCount)
7466 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7467 size = pic14_getDataSize(result);
7469 /* if shCount >= 8 */
7475 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7477 movLeft2Result(left, LSB, result, MSB16);
7479 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7482 /* 1 <= shCount <= 7 */
7485 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7487 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7491 /*-----------------------------------------------------------------*/
7492 /* shiftLLong - shift left one long from left to result */
7493 /* offl = LSB or MSB16 */
7494 /*-----------------------------------------------------------------*/
7495 static void shiftLLong (operand *left, operand *result, int offr )
7498 int size = AOP_SIZE(result);
7501 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7502 if(size >= LSB+offr){
7503 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7505 pic14_emitcode("add","a,acc");
7506 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7507 size >= MSB16+offr && offr != LSB )
7508 pic14_emitcode("xch","a,%s",
7509 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7511 aopPut(AOP(result),"a",LSB+offr);
7514 if(size >= MSB16+offr){
7515 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7516 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7519 pic14_emitcode("rlc","a");
7520 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7521 size >= MSB24+offr && offr != LSB)
7522 pic14_emitcode("xch","a,%s",
7523 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7525 aopPut(AOP(result),"a",MSB16+offr);
7528 if(size >= MSB24+offr){
7529 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7530 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7533 pic14_emitcode("rlc","a");
7534 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7535 size >= MSB32+offr && offr != LSB )
7536 pic14_emitcode("xch","a,%s",
7537 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7539 aopPut(AOP(result),"a",MSB24+offr);
7542 if(size > MSB32+offr){
7543 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7544 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7547 pic14_emitcode("rlc","a");
7548 aopPut(AOP(result),"a",MSB32+offr);
7551 aopPut(AOP(result),zero,LSB);
7554 /*-----------------------------------------------------------------*/
7555 /* genlshFour - shift four byte by a known amount != 0 */
7556 /*-----------------------------------------------------------------*/
7557 static void genlshFour (operand *result, operand *left, int shCount)
7562 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7563 size = AOP_SIZE(result);
7565 /* if shifting more that 3 bytes */
7566 if (shCount >= 24 ) {
7569 /* lowest order of left goes to the highest
7570 order of the destination */
7571 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7573 movLeft2Result(left, LSB, result, MSB32);
7574 aopPut(AOP(result),zero,LSB);
7575 aopPut(AOP(result),zero,MSB16);
7576 aopPut(AOP(result),zero,MSB32);
7580 /* more than two bytes */
7581 else if ( shCount >= 16 ) {
7582 /* lower order two bytes goes to higher order two bytes */
7584 /* if some more remaining */
7586 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7588 movLeft2Result(left, MSB16, result, MSB32);
7589 movLeft2Result(left, LSB, result, MSB24);
7591 aopPut(AOP(result),zero,MSB16);
7592 aopPut(AOP(result),zero,LSB);
7596 /* if more than 1 byte */
7597 else if ( shCount >= 8 ) {
7598 /* lower order three bytes goes to higher order three bytes */
7602 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7604 movLeft2Result(left, LSB, result, MSB16);
7606 else{ /* size = 4 */
7608 movLeft2Result(left, MSB24, result, MSB32);
7609 movLeft2Result(left, MSB16, result, MSB24);
7610 movLeft2Result(left, LSB, result, MSB16);
7611 aopPut(AOP(result),zero,LSB);
7613 else if(shCount == 1)
7614 shiftLLong(left, result, MSB16);
7616 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7617 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7618 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7619 aopPut(AOP(result),zero,LSB);
7624 /* 1 <= shCount <= 7 */
7625 else if(shCount <= 2){
7626 shiftLLong(left, result, LSB);
7628 shiftLLong(result, result, LSB);
7630 /* 3 <= shCount <= 7, optimize */
7632 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7633 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7634 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7640 /*-----------------------------------------------------------------*/
7641 /* genLeftShiftLiteral - left shifting by known count */
7642 /*-----------------------------------------------------------------*/
7643 static void genLeftShiftLiteral (operand *left,
7648 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7652 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7653 freeAsmop(right,NULL,ic,TRUE);
7655 aopOp(left,ic,FALSE);
7656 aopOp(result,ic,FALSE);
7658 size = getSize(operandType(result));
7661 pic14_emitcode("; shift left ","result %d, left %d",size,
7665 /* I suppose that the left size >= result size */
7668 movLeft2Result(left, size, result, size);
7672 else if(shCount >= (size * 8))
7674 aopPut(AOP(result),zero,size);
7678 genlshOne (result,left,shCount);
7683 genlshTwo (result,left,shCount);
7687 genlshFour (result,left,shCount);
7691 freeAsmop(left,NULL,ic,TRUE);
7692 freeAsmop(result,NULL,ic,TRUE);
7696 /*-----------------------------------------------------------------*
7697 * genMultiAsm - repeat assembly instruction for size of register.
7698 * if endian == 1, then the high byte (i.e base address + size of
7699 * register) is used first else the low byte is used first;
7700 *-----------------------------------------------------------------*/
7701 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7707 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7720 emitpcode(poc, popGet(AOP(reg),offset));
7727 /*-----------------------------------------------------------------*/
7728 /* genLeftShift - generates code for left shifting */
7729 /*-----------------------------------------------------------------*/
7730 static void genLeftShift (iCode *ic)
7732 operand *left,*right, *result;
7734 unsigned long lit = 0L;
7736 symbol *tlbl , *tlbl1;
7740 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7742 right = IC_RIGHT(ic);
7744 result = IC_RESULT(ic);
7746 aopOp(right,ic,FALSE);
7747 aopOp(left,ic,FALSE);
7748 aopOp(result,ic,FALSE);
7751 /* if the shift count is known then do it
7752 as efficiently as possible */
7753 if (AOP_TYPE(right) == AOP_LIT) {
7754 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7758 /* shift count is unknown then we have to form
7759 a loop get the loop count in B : Note: we take
7760 only the lower order byte since shifting
7761 more that 32 bits make no sense anyway, ( the
7762 largest size of an object can be only 32 bits ) */
7764 /* this code fails for RIGHT == RESULT */
7765 assert (!pic14_sameRegs (AOP(right), AOP(result)));
7767 /* now move the left to the result if they are not the
7769 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
7770 AOP_SIZE(result) > 1) {
7772 size = AOP_SIZE(result);
7775 l = aopGet(AOP(left),offset,FALSE,TRUE);
7776 if (*l == '@' && (IS_AOP_PREG(result))) {
7778 pic14_emitcode("mov","a,%s",l);
7779 aopPut(AOP(result),"a",offset);
7781 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
7782 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7783 //aopPut(AOP(result),l,offset);
7789 if(AOP_TYPE(left) == AOP_LIT)
7790 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7792 size = AOP_SIZE(result);
7794 /* if it is only one byte then */
7796 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7797 emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7798 emitpcode(POC_ANDLW, popGetLit(0xf0));
7799 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7800 emitpcode(POC_MOVFW, popGet(AOP(left),0));
7801 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7802 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7803 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7804 emitpcode(POC_RLFW, popGet(AOP(result),0));
7805 emitpcode(POC_ANDLW, popGetLit(0xfe));
7806 emitpcode(POC_ADDFW, popGet(AOP(result),0));
7807 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7808 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7811 tlbl = newiTempLabel(NULL);
7812 if (!pic14_sameRegs(AOP(left),AOP(result))) {
7813 mov2w (AOP(left), 0);
7814 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7817 emitpcode(POC_COMFW, popGet(AOP(right),0));
7818 emitpcode(POC_RRF, popGet(AOP(result),0));
7819 emitpLabel(tlbl->key);
7820 emitpcode(POC_RLF, popGet(AOP(result),0));
7821 emitpcode(POC_ADDLW, popGetLit(1));
7823 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7828 if (pic14_sameRegs(AOP(left),AOP(result))) {
7830 tlbl = newiTempLabel(NULL);
7831 emitpcode(POC_COMFW, popGet(AOP(right),0));
7832 genMultiAsm(POC_RRF, result, size,1);
7833 emitpLabel(tlbl->key);
7834 genMultiAsm(POC_RLF, result, size,0);
7835 emitpcode(POC_ADDLW, popGetLit(1));
7837 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7841 //tlbl = newiTempLabel(NULL);
7843 //tlbl1 = newiTempLabel(NULL);
7845 //reAdjustPreg(AOP(result));
7847 //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7848 //pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7849 //l = aopGet(AOP(result),offset,FALSE,FALSE);
7851 //pic14_emitcode("add","a,acc");
7852 //aopPut(AOP(result),"a",offset++);
7854 // l = aopGet(AOP(result),offset,FALSE,FALSE);
7856 // pic14_emitcode("rlc","a");
7857 // aopPut(AOP(result),"a",offset++);
7859 //reAdjustPreg(AOP(result));
7861 //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7862 //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7865 tlbl = newiTempLabel(NULL);
7866 tlbl1= newiTempLabel(NULL);
7868 size = AOP_SIZE(result);
7871 pctemp = popGetTempReg(); /* grab a temporary working register. */
7873 emitpcode(POC_MOVFW, popGet(AOP(right),0));
7875 /* offset should be 0, 1 or 3 */
7876 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7878 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
7880 emitpcode(POC_MOVWF, pctemp);
7883 emitpLabel(tlbl->key);
7886 emitpcode(POC_RLF, popGet(AOP(result),0));
7888 emitpcode(POC_RLF, popGet(AOP(result),offset++));
7890 emitpcode(POC_DECFSZ, pctemp);
7891 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7892 emitpLabel(tlbl1->key);
7894 popReleaseTempReg(pctemp);
7898 freeAsmop (right,NULL,ic,TRUE);
7899 freeAsmop(left,NULL,ic,TRUE);
7900 freeAsmop(result,NULL,ic,TRUE);
7905 /*-----------------------------------------------------------------*/
7906 /* genrshOne - right shift a one byte quantity by known count */
7907 /*-----------------------------------------------------------------*/
7908 static void genrshOne (operand *result, operand *left,
7909 int shCount, int sign)
7912 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7913 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7916 /*-----------------------------------------------------------------*/
7917 /* genrshTwo - right shift two bytes by known amount != 0 */
7918 /*-----------------------------------------------------------------*/
7919 static void genrshTwo (operand *result,operand *left,
7920 int shCount, int sign)
7923 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7924 /* if shCount >= 8 */
7928 shiftR1Left2Result(left, MSB16, result, LSB,
7931 movLeft2Result(left, MSB16, result, LSB);
7933 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7936 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7937 emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7941 /* 1 <= shCount <= 7 */
7943 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
7946 /*-----------------------------------------------------------------*/
7947 /* shiftRLong - shift right one long from left to result */
7948 /* offl = LSB or MSB16 */
7949 /*-----------------------------------------------------------------*/
7950 static void shiftRLong (operand *left, int offl,
7951 operand *result, int sign)
7956 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7958 size = AOP_SIZE(left);
7959 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7962 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7966 assert (offl >= 0 && offl < size);
7968 same = pic14_sameRegs (AOP(left), AOP(result));
7970 /* perform the shift */
7973 if (same && !offl) {
7974 emitpcode (POC_RRF, popGet (AOP(result), size));
7976 emitpcode (POC_RRFW, popGet (AOP(left), size));
7977 emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7981 addSign (result, AOP_SIZE(left) - offl, sign);
7984 /*-----------------------------------------------------------------*/
7985 /* genrshFour - shift four byte by a known amount != 0 */
7986 /*-----------------------------------------------------------------*/
7987 static void genrshFour (operand *result, operand *left,
7988 int shCount, int sign)
7991 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7992 /* if shifting more that 3 bytes */
7993 if(shCount >= 24 ) {
7996 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7998 movLeft2Result(left, MSB32, result, LSB);
8000 addSign(result, MSB16, sign);
8002 else if(shCount >= 16){
8005 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8007 movLeft2Result(left, MSB24, result, LSB);
8008 movLeft2Result(left, MSB32, result, MSB16);
8010 addSign(result, MSB24, sign);
8012 else if(shCount >= 8){
8015 shiftRLong(left, MSB16, result, sign);
8016 else if(shCount == 0){
8017 movLeft2Result(left, MSB16, result, LSB);
8018 movLeft2Result(left, MSB24, result, MSB16);
8019 movLeft2Result(left, MSB32, result, MSB24);
8020 addSign(result, MSB32, sign);
8023 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8024 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8025 /* the last shift is signed */
8026 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8027 addSign(result, MSB32, sign);
8030 else{ /* 1 <= shCount <= 7 */
8032 shiftRLong(left, LSB, result, sign);
8034 shiftRLong(result, LSB, result, sign);
8037 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8038 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8039 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8044 /*-----------------------------------------------------------------*/
8045 /* genRightShiftLiteral - right shifting by known count */
8046 /*-----------------------------------------------------------------*/
8047 static void genRightShiftLiteral (operand *left,
8053 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8057 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8058 freeAsmop(right,NULL,ic,TRUE);
8060 aopOp(left,ic,FALSE);
8061 aopOp(result,ic,FALSE);
8064 pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8068 lsize = pic14_getDataSize(left);
8069 res_size = pic14_getDataSize(result);
8070 /* test the LEFT size !!! */
8072 /* I suppose that the left size >= result size */
8075 movLeft2Result(left, res_size, result, res_size);
8078 else if(shCount >= (lsize * 8)){
8081 emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8083 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8084 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8089 emitpcode(POC_MOVLW, popGetLit(0));
8090 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8091 emitpcode(POC_MOVLW, popGetLit(0xff));
8093 emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8098 emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8105 genrshOne (result,left,shCount,sign);
8109 genrshTwo (result,left,shCount,sign);
8113 genrshFour (result,left,shCount,sign);
8121 freeAsmop(left,NULL,ic,TRUE);
8122 freeAsmop(result,NULL,ic,TRUE);
8127 /*-----------------------------------------------------------------*/
8128 /* genSignedRightShift - right shift of signed number */
8129 /*-----------------------------------------------------------------*/
8130 static void genSignedRightShift (iCode *ic)
8132 operand *right, *left, *result;
8135 symbol *tlbl, *tlbl1 ;
8138 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8140 /* we do it the hard way put the shift count in b
8141 and loop thru preserving the sign */
8143 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8145 right = IC_RIGHT(ic);
8147 result = IC_RESULT(ic);
8149 aopOp(right,ic,FALSE);
8150 aopOp(left,ic,FALSE);
8151 aopOp(result,ic,FALSE);
8154 if ( AOP_TYPE(right) == AOP_LIT) {
8155 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8156 //genRightShiftLiteral (left,right,result,ic,1);
8159 /* shift count is unknown then we have to form
8160 a loop get the loop count in B : Note: we take
8161 only the lower order byte since shifting
8162 more that 32 bits make no sense anyway, ( the
8163 largest size of an object can be only 32 bits ) */
8165 //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8166 //pic14_emitcode("inc","b");
8167 //freeAsmop (right,NULL,ic,TRUE);
8168 //aopOp(left,ic,FALSE);
8169 //aopOp(result,ic,FALSE);
8171 /* now move the left to the result if they are not the
8173 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
8174 AOP_SIZE(result) > 1) {
8176 size = AOP_SIZE(result);
8180 l = aopGet(AOP(left),offset,FALSE,TRUE);
8181 if (*l == '@' && IS_AOP_PREG(result)) {
8182 pic14_emitcode("mov","a,%s",l);
8183 aopPut(AOP(result),"a",offset);
8185 aopPut(AOP(result),l,offset);
8187 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8188 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8194 /* mov the highest order bit to OVR */
8195 tlbl = newiTempLabel(NULL);
8196 tlbl1= newiTempLabel(NULL);
8198 size = AOP_SIZE(result);
8201 pctemp = popGetTempReg(); /* grab a temporary working register. */
8203 emitpcode(POC_MOVFW, popGet(AOP(right),0));
8205 /* offset should be 0, 1 or 3 */
8206 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8208 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8210 emitpcode(POC_MOVWF, pctemp);
8213 emitpLabel(tlbl->key);
8215 emitpcode(POC_RLFW, popGet(AOP(result),offset));
8216 emitpcode(POC_RRF, popGet(AOP(result),offset));
8219 emitpcode(POC_RRF, popGet(AOP(result),--offset));
8222 emitpcode(POC_DECFSZ, pctemp);
8223 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8224 emitpLabel(tlbl1->key);
8226 popReleaseTempReg(pctemp);
8228 size = AOP_SIZE(result);
8230 pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8231 pic14_emitcode("rlc","a");
8232 pic14_emitcode("mov","ov,c");
8233 /* if it is only one byte then */
8235 l = aopGet(AOP(left),0,FALSE,FALSE);
8237 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8238 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8239 pic14_emitcode("mov","c,ov");
8240 pic14_emitcode("rrc","a");
8241 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8242 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8243 aopPut(AOP(result),"a",0);
8247 reAdjustPreg(AOP(result));
8248 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8249 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8250 pic14_emitcode("mov","c,ov");
8252 l = aopGet(AOP(result),offset,FALSE,FALSE);
8254 pic14_emitcode("rrc","a");
8255 aopPut(AOP(result),"a",offset--);
8257 reAdjustPreg(AOP(result));
8258 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8259 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8264 freeAsmop(left,NULL,ic,TRUE);
8265 freeAsmop(result,NULL,ic,TRUE);
8266 freeAsmop(right,NULL,ic,TRUE);
8270 /*-----------------------------------------------------------------*/
8271 /* loadSignToC - load the operand's sign bit into CARRY */
8272 /*-----------------------------------------------------------------*/
8274 static void loadSignToC (operand *op)
8277 assert (op && AOP(op) && AOP_SIZE(op));
8280 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8284 /*-----------------------------------------------------------------*/
8285 /* genRightShift - generate code for right shifting */
8286 /*-----------------------------------------------------------------*/
8287 static void genGenericShift (iCode *ic, int shiftRight)
8289 operand *right, *left, *result;
8292 symbol *tlbl, *tlbl1, *inverselbl;
8295 /* if signed then we do it the hard way preserve the
8296 sign bit moving it inwards */
8297 retype = getSpec(operandType(IC_RESULT(ic)));
8298 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8300 /* signed & unsigned types are treated the same : i.e. the
8301 signed is NOT propagated inwards : quoting from the
8302 ANSI - standard : "for E1 >> E2, is equivalent to division
8303 by 2**E2 if unsigned or if it has a non-negative value,
8304 otherwise the result is implementation defined ", MY definition
8305 is that the sign does not get propagated */
8307 right = IC_RIGHT(ic);
8309 result = IC_RESULT(ic);
8311 aopOp(right,ic,FALSE);
8312 aopOp(left,ic,FALSE);
8313 aopOp(result,ic,FALSE);
8315 /* if the shift count is known then do it
8316 as efficiently as possible */
8317 if (AOP_TYPE(right) == AOP_LIT) {
8318 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8322 shiftRight = !shiftRight;
8326 shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8328 shiftLeft_Left2ResultLit (left, result, lit);
8329 //genRightShiftLiteral (left,right,result,ic, 0);
8333 /* shift count is unknown then we have to form
8334 a loop get the loop count in B : Note: we take
8335 only the lower order byte since shifting
8336 more that 32 bits make no sense anyway, ( the
8337 largest size of an object can be only 32 bits ) */
8339 /* we must not overwrite the shift counter */
8340 assert (!pic14_sameRegs(AOP(right),AOP(result)));
8342 /* now move the left to the result if they are not the
8344 if (!pic14_sameRegs(AOP(left),AOP(result)))
8346 size = min(AOP_SIZE(result), AOP_SIZE(left));
8348 mov2w(AOP(left), size);
8349 movwf(AOP(result), size);
8351 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8354 tlbl = newiTempLabel(NULL);
8355 tlbl1= newiTempLabel(NULL);
8357 size = AOP_SIZE(result);
8359 mov2w(AOP(right),0);
8360 if (!SPEC_USIGN(operandType(right)))
8362 inverselbl = newiTempLabel(NULL);
8363 /* signed shift count -- invert shift direction for c<0 */
8364 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8365 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8367 emitpcode(POC_SUBLW, popGetLit(0)); /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8368 /* check for `a = b >> c' with `-c == 0' */
8370 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8371 emitpLabel(tlbl->key);
8372 /* propagate the sign bit inwards for SIGNED result */
8373 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8374 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8375 emitpcode(POC_ADDLW, popGetLit(1)); /* clears CARRY (unless W==0 afterwards) */
8377 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8379 if (!SPEC_USIGN(operandType(right)))
8381 symbol *inv_loop = newiTempLabel(NULL);
8383 shiftRight = !shiftRight; /* invert shift direction */
8385 /* we came here from the code above -- we are done */
8386 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8388 /* emit code for shifting N<0 steps, count is already in W */
8389 emitpLabel(inverselbl->key);
8390 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8391 emitpLabel(inv_loop->key);
8392 /* propagate the sign bit inwards for SIGNED result */
8393 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8394 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8395 emitpcode(POC_ADDLW, popGetLit(1));
8397 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8400 emitpLabel(tlbl1->key);
8402 freeAsmop(left,NULL,ic,TRUE);
8403 freeAsmop (right,NULL,ic,TRUE);
8404 freeAsmop(result,NULL,ic,TRUE);
8407 static void genRightShift (iCode *ic)
8409 genGenericShift(ic, 1);
8412 static void genLeftShift (iCode *ic)
8414 genGenericShift(ic, 0);
8417 /*-----------------------------------------------------------------*/
8418 /* SetIrp - Set IRP bit */
8419 /*-----------------------------------------------------------------*/
8420 void SetIrp(operand *result) {
8422 if (AOP_TYPE(result) == AOP_LIT) {
8423 unsigned lit = (unsigned)operandLitValue(result);
8429 if (PCOP(AOP(result))->type == PO_LITERAL) {
8430 int addrs = PCOL(AOP(result))->lit;
8436 emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8437 if(AOP_SIZE(result) > 1) {
8438 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8446 setup_fsr (operand *ptr)
8449 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8451 /* also setup-up IRP */
8455 /*-----------------------------------------------------------------*/
8456 /* emitPtrByteGet - emits code to get a byte into WREG from an */
8457 /* arbitrary pointer (__code, __data, generic) */
8458 /*-----------------------------------------------------------------*/
8460 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8467 if (!alreadyAddressed) setup_fsr (src);
8468 emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8472 assert( AOP_SIZE(src) == 2 );
8474 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8476 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8477 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
8478 call_libraryfunc ("__gptrget1");
8482 assert( AOP_SIZE(src) == 3 );
8484 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8486 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8488 call_libraryfunc ("__gptrget1");
8492 assert( !"unhandled pointer type" );
8497 /*-----------------------------------------------------------------*/
8498 /* emitPtrByteSet - emits code to set a byte from src through a */
8499 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR). */
8500 /*-----------------------------------------------------------------*/
8502 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8509 if (!alreadyAddressed) setup_fsr (dst);
8510 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8514 assert( !"trying to assign to __code pointer" );
8518 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8520 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8522 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8524 call_libraryfunc ("__gptrput1");
8528 assert( !"unhandled pointer type" );
8533 /*-----------------------------------------------------------------*/
8534 /* genUnpackBits - generates code for unpacking bits */
8535 /*-----------------------------------------------------------------*/
8536 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8538 int rsize; /* result size */
8539 sym_link *etype; /* bitfield type information */
8540 int blen; /* bitfield length */
8541 int bstr; /* bitfield starting bit within byte */
8544 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8545 etype = getSpec(operandType(result));
8546 rsize = getSize (operandType (result));
8547 blen = SPEC_BLEN (etype);
8548 bstr = SPEC_BSTR (etype);
8550 /* single bit field case */
8552 if (ifx) { /* that is for an if statement */
8555 resolveIfx(&rIfx,ifx);
8556 if (ptype == -1) /* direct */
8557 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8559 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8560 emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8561 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8565 assert (!pic14_sameRegs (AOP(result), AOP(left)));
8566 for (i=0; i < AOP_SIZE(result); i++)
8567 emitpcode (POC_CLRF, popGet (AOP(result), i));
8572 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8573 /* adjust result below */
8580 emitPtrByteGet (left, ptype, FALSE);
8581 emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8583 /* adjust result below */
8587 assert( !"unhandled pointer type" );
8590 /* move sign-/zero extended bit to result */
8591 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8592 emitpcode (POC_INCF, popGet (AOP(result), 0));
8594 emitpcode (POC_DECF, popGet (AOP(result), 0));
8596 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8600 else if (blen <= 8 && ((blen + bstr) <= 8))
8605 for (i=0; i < AOP_SIZE(result); i++)
8606 emitpcode (POC_CLRF, popGet (AOP(result), i));
8611 mov2w(AOP(left), 0);
8618 emitPtrByteGet (left, ptype, FALSE);
8622 assert( !"unhandled pointer type" );
8626 emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8627 movwf(AOP(result), 0);
8628 AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8630 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8632 /* signed bitfield */
8633 assert (bstr + blen > 0);
8634 emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8635 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8636 emitpcode(POC_IORWF, popGet(AOP(result),0));
8638 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8642 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8646 /*-----------------------------------------------------------------*/
8647 /* genDataPointerGet - generates code when ptr offset is known */
8648 /*-----------------------------------------------------------------*/
8649 static void genDataPointerGet (operand *left,
8653 int size , offset = 0;
8656 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8659 /* optimization - most of the time, left and result are the same
8660 * address, but different types. for the pic code, we could omit
8663 aopOp(result,ic,TRUE);
8665 if (pic14_sameRegs (AOP(left), AOP(result)))
8668 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8670 //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8672 size = AOP_SIZE(result);
8673 if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8677 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8678 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8682 freeAsmop(left,NULL,ic,TRUE);
8683 freeAsmop(result,NULL,ic,TRUE);
8687 /*-----------------------------------------------------------------*/
8688 /* genNearPointerGet - pic14_emitcode for near pointer fetch */
8689 /*-----------------------------------------------------------------*/
8690 static void genNearPointerGet (operand *left,
8695 sym_link *ltype = operandType(left);
8696 sym_link *rtype = operandType(result);
8697 sym_link *retype= getSpec(rtype); /* bitfield type information */
8701 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8704 aopOp(left,ic,FALSE);
8706 /* if left is rematerialisable and
8707 result is not bit variable type and
8708 the left is pointer to data space i.e
8709 lower 128 bytes of space */
8710 if (AOP_TYPE(left) == AOP_PCODE && //AOP_TYPE(left) == AOP_IMMD &&
8711 !IS_BITVAR(retype) &&
8712 PIC_IS_DATA_PTR(ltype)) {
8713 genDataPointerGet (left,result,ic);
8717 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8718 aopOp (result,ic,FALSE);
8720 /* Check if can access directly instead of via a pointer */
8721 if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8722 && AOP_SIZE(result) == 1)
8727 if (IS_BITFIELD(getSpec(operandType(result))))
8729 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8733 /* If the pointer value is not in a the FSR then need to put it in */
8734 /* Must set/reset IRP bit for use with FSR. */
8739 /* if bitfield then unpack the bits */
8741 /* we have can just get the values */
8742 int size = AOP_SIZE(result);
8745 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8749 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8751 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8752 if (AOP_TYPE(result) == AOP_LIT) {
8753 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8755 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8757 if (size && !direct)
8758 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8763 /* now some housekeeping stuff */
8765 /* we had to allocate for this iCode */
8766 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8767 freeAsmop(NULL,aop,ic,TRUE);
8769 /* we did not allocate which means left
8770 already in a pointer register, then
8771 if size > 0 && this could be used again
8772 we have to point it back to where it
8774 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8775 if (AOP_SIZE(result) > 1 &&
8776 !OP_SYMBOL(left)->remat &&
8777 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8779 int size = AOP_SIZE(result) - 1;
8781 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8787 freeAsmop(left,NULL,ic,TRUE);
8788 freeAsmop(result,NULL,ic,TRUE);
8793 /*-----------------------------------------------------------------*/
8794 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch */
8795 /*-----------------------------------------------------------------*/
8796 static void genPagedPointerGet (operand *left,
8803 sym_link *rtype, *retype;
8806 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8808 rtype = operandType(result);
8809 retype= getSpec(rtype);
8811 aopOp(left,ic,FALSE);
8813 /* if the value is already in a pointer register
8814 then don't need anything more */
8815 if (!AOP_INPREG(AOP(left))) {
8816 /* otherwise get a free pointer register */
8818 preg = getFreePtr(ic,&aop,FALSE);
8819 pic14_emitcode("mov","%s,%s",
8821 aopGet(AOP(left),0,FALSE,TRUE));
8822 rname = preg->name ;
8824 rname = aopGet(AOP(left),0,FALSE,FALSE);
8826 freeAsmop(left,NULL,ic,TRUE);
8827 aopOp (result,ic,FALSE);
8829 /* if bitfield then unpack the bits */
8830 if (IS_BITFIELD(retype))
8831 genUnpackBits (result,left,rname,PPOINTER,0);
8833 /* we have can just get the values */
8834 int size = AOP_SIZE(result);
8839 pic14_emitcode("movx","a,@%s",rname);
8840 aopPut(AOP(result),"a",offset);
8845 pic14_emitcode("inc","%s",rname);
8849 /* now some housekeeping stuff */
8851 /* we had to allocate for this iCode */
8852 freeAsmop(NULL,aop,ic,TRUE);
8854 /* we did not allocate which means left
8855 already in a pointer register, then
8856 if size > 0 && this could be used again
8857 we have to point it back to where it
8859 if (AOP_SIZE(result) > 1 &&
8860 !OP_SYMBOL(left)->remat &&
8861 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8863 int size = AOP_SIZE(result) - 1;
8865 pic14_emitcode("dec","%s",rname);
8870 freeAsmop(result,NULL,ic,TRUE);
8875 /*-----------------------------------------------------------------*/
8876 /* genFarPointerGet - gget value from far space */
8877 /*-----------------------------------------------------------------*/
8878 static void genFarPointerGet (operand *left,
8879 operand *result, iCode *ic)
8882 sym_link *retype = getSpec(operandType(result));
8885 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8887 aopOp(left,ic,FALSE);
8889 /* if the operand is already in dptr
8890 then we do nothing else we move the value to dptr */
8891 if (AOP_TYPE(left) != AOP_STR) {
8892 /* if this is remateriazable */
8893 if (AOP_TYPE(left) == AOP_IMMD)
8894 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8895 else { /* we need to get it byte by byte */
8896 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8897 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8898 if (options.model == MODEL_FLAT24)
8900 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8904 /* so dptr know contains the address */
8905 freeAsmop(left,NULL,ic,TRUE);
8906 aopOp(result,ic,FALSE);
8908 /* if bit then unpack */
8909 if (IS_BITFIELD(retype))
8910 genUnpackBits(result,left,"dptr",FPOINTER,0);
8912 size = AOP_SIZE(result);
8916 pic14_emitcode("movx","a,@dptr");
8917 aopPut(AOP(result),"a",offset++);
8919 pic14_emitcode("inc","dptr");
8923 freeAsmop(result,NULL,ic,TRUE);
8928 /*-----------------------------------------------------------------*/
8929 /* genCodePointerGet - get value from code space */
8930 /*-----------------------------------------------------------------*/
8931 static void genCodePointerGet (operand *left,
8932 operand *result, iCode *ic)
8935 sym_link *retype = getSpec(operandType(result));
8937 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8939 aopOp(left,ic,FALSE);
8941 /* if the operand is already in dptr
8942 then we do nothing else we move the value to dptr */
8943 if (AOP_TYPE(left) != AOP_STR) {
8944 /* if this is remateriazable */
8945 if (AOP_TYPE(left) == AOP_IMMD)
8946 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8947 else { /* we need to get it byte by byte */
8948 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8949 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8950 if (options.model == MODEL_FLAT24)
8952 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8956 /* so dptr know contains the address */
8957 freeAsmop(left,NULL,ic,TRUE);
8958 aopOp(result,ic,FALSE);
8960 /* if bit then unpack */
8961 if (IS_BITFIELD(retype))
8962 genUnpackBits(result,left,"dptr",CPOINTER,0);
8964 size = AOP_SIZE(result);
8968 pic14_emitcode("clr","a");
8969 pic14_emitcode("movc","a,@a+dptr");
8970 aopPut(AOP(result),"a",offset++);
8972 pic14_emitcode("inc","dptr");
8976 freeAsmop(result,NULL,ic,TRUE);
8979 /*-----------------------------------------------------------------*/
8980 /* genGenPointerGet - gget value from generic pointer space */
8981 /*-----------------------------------------------------------------*/
8982 static void genGenPointerGet (operand *left,
8983 operand *result, iCode *ic)
8986 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8987 aopOp(left,ic,FALSE);
8988 aopOp(result,ic,FALSE);
8991 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8993 if (IS_BITFIELD(getSpec(operandType(result))))
8995 genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
9000 /* emit call to __gptrget */
9001 char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
9002 int size = AOP_SIZE(result);
9005 assert (size > 0 && size <= 4);
9007 /* pass arguments */
9008 assert (AOP_SIZE(left) == 3);
9009 mov2w(AOP(left), 0);
9010 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9011 mov2w(AOP(left), 1);
9012 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9013 mov2w(AOP(left), 2);
9014 call_libraryfunc (func[size]);
9017 movwf (AOP(result), --size);
9019 emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
9020 movwf (AOP(result), size);
9024 freeAsmop(left,NULL,ic,TRUE);
9025 freeAsmop(result,NULL,ic,TRUE);
9029 /*-----------------------------------------------------------------*/
9030 /* genConstPointerGet - get value from const generic pointer space */
9031 /*-----------------------------------------------------------------*/
9032 static void genConstPointerGet (operand *left,
9033 operand *result, iCode *ic)
9035 //sym_link *retype = getSpec(operandType(result));
9037 symbol *albl, *blbl;//, *clbl;
9044 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9045 aopOp(left,ic,FALSE);
9046 aopOp(result,ic,FALSE);
9048 size = AOP_SIZE(result);
9050 DEBUGpic14_AopType(__LINE__,left,NULL,result);
9052 DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
9054 lit = op_isLitLike (left);
9055 poc = lit ? POC_MOVLW : POC_MOVFW;
9057 if (IS_BITFIELD(getSpec(operandType(result))))
9059 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
9064 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
9065 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
9066 assert (size > 0 && size <= 4);
9069 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9071 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9072 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
9073 call_libraryfunc (func[size]);
9075 movwf(AOP(result),size-1);
9076 for (i = 1; i < size; i++)
9078 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
9079 movwf(AOP(result),size - 1 - i);
9084 freeAsmop(left,NULL,ic,TRUE);
9085 freeAsmop(result,NULL,ic,TRUE);
9088 /*-----------------------------------------------------------------*/
9089 /* genPointerGet - generate code for pointer get */
9090 /*-----------------------------------------------------------------*/
9091 static void genPointerGet (iCode *ic)
9093 operand *left, *result ;
9094 sym_link *type, *etype;
9098 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9101 result = IC_RESULT(ic) ;
9103 /* depending on the type of pointer we need to
9104 move it to the correct pointer register */
9105 type = operandType(left);
9106 etype = getSpec(type);
9108 if (IS_PTR_CONST(type))
9109 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9111 /* if left is of type of pointer then it is simple */
9112 if (IS_PTR(type) && !IS_FUNC(type->next))
9113 p_type = DCL_TYPE(type);
9115 /* we have to go by the storage class */
9116 p_type = PTR_TYPE(SPEC_OCLS(etype));
9118 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9120 if (SPEC_OCLS(etype)->codesp ) {
9121 DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9122 //p_type = CPOINTER ;
9125 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9126 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9127 /*p_type = FPOINTER ;*/
9129 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9130 DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9131 /* p_type = PPOINTER; */
9133 if (SPEC_OCLS(etype) == idata )
9134 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9135 /* p_type = IPOINTER; */
9137 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9138 /* p_type = POINTER ; */
9141 /* now that we have the pointer type we assign
9142 the pointer values */
9148 genNearPointerGet (left,result,ic);
9152 genPagedPointerGet(left,result,ic);
9156 genFarPointerGet (left,result,ic);
9160 genConstPointerGet (left,result,ic);
9164 genGenPointerGet (left,result,ic);
9167 assert ( !"unhandled pointer type" );
9173 /*-----------------------------------------------------------------*/
9174 /* genPackBits - generates code for packed bit storage */
9175 /*-----------------------------------------------------------------*/
9176 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9178 int blen; /* bitfield length */
9179 int bstr; /* bitfield starting bit within byte */
9180 int litval; /* source literal value (if AOP_LIT) */
9181 unsigned char mask; /* bitmask within current byte */
9184 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9186 blen = SPEC_BLEN (etype);
9187 bstr = SPEC_BSTR (etype);
9189 /* If the bitfield length is less than a byte and does not cross byte boundaries */
9190 if ((blen <= 8) && ((bstr + blen) <= 8))
9192 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9193 (unsigned char) (0xFF >> (8 - bstr)));
9195 if (AOP_TYPE (right) == AOP_LIT)
9197 /* Case with a bitfield length <8 and literal source */
9198 int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9205 if (AOP(result)->type == AOP_PCODE)
9206 pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9208 pcop = popGet(AOP(result),0);
9209 emitpcode(lit?POC_BSF:POC_BCF,pcop);
9215 emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9219 assert( !"trying to assign to bitfield via pointer to __code space" );
9223 emitPtrByteGet(result, p_type, FALSE);
9225 emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9227 emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9229 emitPtrByteSet(result, p_type, TRUE);
9233 assert( !"unhandled pointer type" );
9235 } // switch (p_type)
9238 litval = lit << bstr;
9239 litval &= (~mask) & 0x00ff;
9244 mov2w (AOP(result), 0);
9245 if ((litval|mask) != 0x00ff)
9246 emitpcode(POC_ANDLW, popGetLit (mask));
9248 emitpcode(POC_IORLW, popGetLit (litval));
9249 movwf (AOP(result), 0);
9255 emitPtrByteGet(result, p_type, FALSE);
9256 if ((litval|mask) != 0x00ff)
9257 emitpcode(POC_ANDLW, popGetLit (mask));
9259 emitpcode(POC_IORLW, popGetLit (litval));
9260 emitPtrByteSet(result, p_type, TRUE);
9264 assert( !"trying to assign to bitfield via pointer to __code space" );
9268 assert( !"unhandled pointer type" );
9275 /* right is no literal */
9280 /* Note more efficient code, of pre clearing bit then only setting it if required,
9281 * can only be done if it is known that the result is not a SFR */
9282 emitpcode(POC_RRFW,popGet(AOP(right),0));
9284 emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9286 emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9292 emitPtrByteGet (result, p_type, FALSE);
9293 emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9294 emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9295 emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9296 emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9297 emitPtrByteSet (result, p_type, TRUE);
9301 assert( !"trying to assign to bitfield via pointer to __code space" );
9305 assert( !"unhandled pointer type" );
9310 /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9311 pCodeOp *temp = popGetTempReg ();
9313 mov2w (AOP(right), 0);
9315 emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9317 emitpcode(POC_MOVWF, temp);
9319 AccLsh (temp, bstr);
9325 mov2w (AOP(result), 0);
9326 emitpcode(POC_ANDLW, popGetLit (mask));
9327 emitpcode(POC_IORFW, temp);
9328 movwf (AOP(result), 0);
9334 emitPtrByteGet (result, p_type, FALSE);
9335 emitpcode(POC_ANDLW, popGetLit (mask));
9336 emitpcode(POC_IORFW, temp);
9337 emitPtrByteSet (result, p_type, TRUE);
9341 assert( !"trying to assign to bitfield via pointer to __code space" );
9345 assert( !"unhandled pointer type" );
9349 popReleaseTempReg (temp);
9351 } // if (AOP(right)->type != AOP_LIT)
9353 } // if (blen <= 8 && ((blen + bstr) <= 8))
9355 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9358 /*-----------------------------------------------------------------*/
9359 /* genDataPointerSet - remat pointer to data space */
9360 /*-----------------------------------------------------------------*/
9361 static void genDataPointerSet(operand *right,
9365 int size, offset = 0 ;
9369 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9370 aopOp(right,ic,FALSE);
9371 aopOp(result,ic,FALSE);
9373 assert (IS_SYMOP(result));
9374 assert (IS_PTR(OP_SYM_TYPE(result)));
9376 size = AOP_SIZE(right);
9377 ressize = getSize(OP_SYM_ETYPE(result));
9378 if (size > ressize) size = ressize;
9379 //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9381 //assert( !"what's going on here?" );
9384 if ( AOP_TYPE(result) == AOP_PCODE) {
9385 fprintf(stderr,"genDataPointerSet %s, %d\n",
9386 AOP(result)->aopu.pcop->name,
9387 PCOI(AOP(result)->aopu.pcop)->offset);
9391 // tsd, was l+1 - the underline `_' prefix was being stripped
9393 emitpComment ("%s:%u: size=%d/%d, offset=%i", __FILE__,__LINE__, size, ressize, offset);
9395 if (AOP_TYPE(right) == AOP_LIT) {
9396 unsigned int lit = pic14aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
9397 //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9399 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9400 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9402 emitpcode(POC_CLRF, popGet(AOP(result), offset));
9405 //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9406 emitpcode(POC_MOVFW, popGet(AOP(right), offset));
9407 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9413 freeAsmop(right,NULL,ic,TRUE);
9414 freeAsmop(result,NULL,ic,TRUE);
9417 /*-----------------------------------------------------------------*/
9418 /* genNearPointerSet - pic14_emitcode for near pointer put */
9419 /*-----------------------------------------------------------------*/
9420 static void genNearPointerSet (operand *right,
9425 sym_link *ptype = operandType(result);
9426 sym_link *retype = getSpec(operandType(right));
9427 sym_link *letype = getSpec(ptype);
9432 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9433 aopOp(result,ic,FALSE);
9436 /* if the result is rematerializable &
9437 in data space & not a bit variable */
9438 //if (AOP_TYPE(result) == AOP_IMMD &&
9439 if (AOP_TYPE(result) == AOP_PCODE &&
9440 PIC_IS_DATA_PTR(ptype) &&
9441 !IS_BITVAR (retype) &&
9442 !IS_BITVAR (letype)) {
9443 genDataPointerSet (right,result,ic);
9444 freeAsmop(result,NULL,ic,TRUE);
9449 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9450 aopOp(right,ic,FALSE);
9451 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9453 /* Check if can access directly instead of via a pointer */
9454 if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9458 if (IS_BITFIELD (letype))
9460 genPackBits (letype, result, right, direct?-1:POINTER);
9464 /* If the pointer value is not in a the FSR then need to put it in */
9465 /* Must set/reset IRP bit for use with FSR. */
9466 /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9471 /* we have can just get the values */
9472 int size = AOP_SIZE(right);
9475 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9477 char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9479 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9481 if (AOP_TYPE(right) == AOP_LIT) {
9482 emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9484 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9487 emitpcode(POC_MOVWF,popGet(AOP(result),0));
9489 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9491 if (size && !direct)
9492 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9497 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9498 /* now some housekeeping stuff */
9500 /* we had to allocate for this iCode */
9501 freeAsmop(NULL,aop,ic,TRUE);
9503 /* we did not allocate which means left
9504 already in a pointer register, then
9505 if size > 0 && this could be used again
9506 we have to point it back to where it
9508 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9509 if (AOP_SIZE(right) > 1 &&
9510 !OP_SYMBOL(result)->remat &&
9511 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9513 int size = AOP_SIZE(right) - 1;
9515 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9519 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9522 freeAsmop(right,NULL,ic,TRUE);
9523 freeAsmop(result,NULL,ic,TRUE);
9527 /*-----------------------------------------------------------------*/
9528 /* genPagedPointerSet - pic14_emitcode for Paged pointer put */
9529 /*-----------------------------------------------------------------*/
9530 static void genPagedPointerSet (operand *right,
9540 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9542 retype= getSpec(operandType(right));
9544 aopOp(result,ic,FALSE);
9546 /* if the value is already in a pointer register
9547 then don't need anything more */
9548 if (!AOP_INPREG(AOP(result))) {
9549 /* otherwise get a free pointer register */
9551 preg = getFreePtr(ic,&aop,FALSE);
9552 pic14_emitcode("mov","%s,%s",
9554 aopGet(AOP(result),0,FALSE,TRUE));
9555 rname = preg->name ;
9557 rname = aopGet(AOP(result),0,FALSE,FALSE);
9559 freeAsmop(result,NULL,ic,TRUE);
9560 aopOp (right,ic,FALSE);
9562 /* if bitfield then unpack the bits */
9563 if (IS_BITFIELD(retype))
9564 genPackBits (retype,result,right,rname,PPOINTER);
9566 /* we have can just get the values */
9567 int size = AOP_SIZE(right);
9571 l = aopGet(AOP(right),offset,FALSE,TRUE);
9574 pic14_emitcode("movx","@%s,a",rname);
9577 pic14_emitcode("inc","%s",rname);
9583 /* now some housekeeping stuff */
9585 /* we had to allocate for this iCode */
9586 freeAsmop(NULL,aop,ic,TRUE);
9588 /* we did not allocate which means left
9589 already in a pointer register, then
9590 if size > 0 && this could be used again
9591 we have to point it back to where it
9593 if (AOP_SIZE(right) > 1 &&
9594 !OP_SYMBOL(result)->remat &&
9595 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9597 int size = AOP_SIZE(right) - 1;
9599 pic14_emitcode("dec","%s",rname);
9604 freeAsmop(right,NULL,ic,TRUE);
9609 /*-----------------------------------------------------------------*/
9610 /* genFarPointerSet - set value from far space */
9611 /*-----------------------------------------------------------------*/
9612 static void genFarPointerSet (operand *right,
9613 operand *result, iCode *ic)
9616 sym_link *retype = getSpec(operandType(right));
9619 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9620 aopOp(result,ic,FALSE);
9622 /* if the operand is already in dptr
9623 then we do nothing else we move the value to dptr */
9624 if (AOP_TYPE(result) != AOP_STR) {
9625 /* if this is remateriazable */
9626 if (AOP_TYPE(result) == AOP_IMMD)
9627 pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9628 else { /* we need to get it byte by byte */
9629 pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9630 pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9631 if (options.model == MODEL_FLAT24)
9633 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9637 /* so dptr know contains the address */
9638 freeAsmop(result,NULL,ic,TRUE);
9639 aopOp(right,ic,FALSE);
9641 /* if bit then unpack */
9642 if (IS_BITFIELD(retype))
9643 genPackBits(retype,result,right,"dptr",FPOINTER);
9645 size = AOP_SIZE(right);
9649 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9651 pic14_emitcode("movx","@dptr,a");
9653 pic14_emitcode("inc","dptr");
9657 freeAsmop(right,NULL,ic,TRUE);
9661 /*-----------------------------------------------------------------*/
9662 /* genGenPointerSet - set value from generic pointer space */
9663 /*-----------------------------------------------------------------*/
9664 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9666 sym_link *retype = getSpec(operandType(result));
9669 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9670 aopOp(right,ic,FALSE);
9671 aopOp(result,ic,FALSE);
9674 DEBUGpic14_AopType(__LINE__,right,NULL,result);
9676 if (IS_BITFIELD(retype))
9678 genPackBits (retype, result, right, GPOINTER);
9683 /* emit call to __gptrput */
9684 char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9685 int size = AOP_SIZE(right);
9688 assert (size == getSize(OP_SYM_ETYPE(result)));
9689 assert (size > 0 && size <= 4);
9691 /* pass arguments */
9692 /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9698 mov2w_op (right, off);
9699 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9704 assert (AOP_SIZE(result) == 3);
9705 mov2w(AOP(result), 0);
9706 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9707 mov2w(AOP(result), 1);
9708 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9709 mov2w(AOP(result), 2);
9710 call_libraryfunc (func[size]);
9713 freeAsmop(right,NULL,ic,TRUE);
9714 freeAsmop(result,NULL,ic,TRUE);
9717 /*-----------------------------------------------------------------*/
9718 /* genPointerSet - stores the value into a pointer location */
9719 /*-----------------------------------------------------------------*/
9720 static void genPointerSet (iCode *ic)
9722 operand *right, *result ;
9723 sym_link *type, *etype;
9727 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9729 right = IC_RIGHT(ic);
9730 result = IC_RESULT(ic) ;
9732 /* depending on the type of pointer we need to
9733 move it to the correct pointer register */
9734 type = operandType(result);
9735 etype = getSpec(type);
9736 /* if left is of type of pointer then it is simple */
9737 if (IS_PTR(type) && !IS_FUNC(type->next)) {
9738 p_type = DCL_TYPE(type);
9741 /* we have to go by the storage class */
9742 p_type = PTR_TYPE(SPEC_OCLS(etype));
9744 /* if (SPEC_OCLS(etype)->codesp ) { */
9745 /* p_type = CPOINTER ; */
9748 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9749 /* p_type = FPOINTER ; */
9751 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9752 /* p_type = PPOINTER ; */
9754 /* if (SPEC_OCLS(etype) == idata ) */
9755 /* p_type = IPOINTER ; */
9757 /* p_type = POINTER ; */
9760 /* now that we have the pointer type we assign
9761 the pointer values */
9767 genNearPointerSet (right,result,ic);
9771 genPagedPointerSet (right,result,ic);
9775 genFarPointerSet (right,result,ic);
9779 genGenPointerSet (right,result,ic);
9783 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9784 "genPointerSet: illegal pointer type");
9788 /*-----------------------------------------------------------------*/
9789 /* genIfx - generate code for Ifx statement */
9790 /*-----------------------------------------------------------------*/
9791 static void genIfx (iCode *ic, iCode *popIc)
9793 operand *cond = IC_COND(ic);
9797 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9799 aopOp(cond,ic,FALSE);
9801 /* get the value into acc */
9802 if (AOP_TYPE(cond) != AOP_CRY)
9803 pic14_toBoolean(cond);
9807 /* if there was something to be popped then do it */
9813 /* This assumes that CARRY is set iff cond is true */
9816 assert (!IC_FALSE(ic));
9817 emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
9819 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9821 assert (IC_FALSE(ic));
9822 emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
9824 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9828 static int hasWarned = 0;
9831 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
9838 /* now Z is set iff !cond */
9841 assert (!IC_FALSE(ic));
9843 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9846 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9852 /* the result is now in the accumulator */
9853 freeAsmop(cond,NULL,ic,TRUE);
9856 /*-----------------------------------------------------------------*/
9857 /* genAddrOf - generates code for address of */
9858 /*-----------------------------------------------------------------*/
9859 static void genAddrOf (iCode *ic)
9861 operand *right, *result, *left;
9865 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9868 //aopOp(IC_RESULT(ic),ic,FALSE);
9870 aopOp((left=IC_LEFT(ic)),ic,FALSE);
9871 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9872 aopOp((result=IC_RESULT(ic)),ic,TRUE);
9874 DEBUGpic14_AopType(__LINE__,left,right,result);
9875 assert (IS_SYMOP (left));
9877 /* sanity check: generic pointers to code space are not yet supported,
9878 * pionters to codespace must not be assigned addresses of __data values. */
9880 fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9881 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)));
9882 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)));
9883 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)));
9884 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)));
9887 if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9888 fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9889 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9890 OP_SYMBOL(left)->name);
9891 } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9892 fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9893 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9894 OP_SYMBOL(left)->name);
9897 size = AOP_SIZE(IC_RESULT(ic));
9898 if (IS_GENPTR(OP_SYM_TYPE(result))) {
9900 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9905 /* fixing bug #863624, reported from (errolv) */
9906 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9907 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9910 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9911 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9916 if (IS_GENPTR(OP_SYM_TYPE(result)))
9918 /* provide correct tag */
9919 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9920 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9921 movwf (AOP(result), 2);
9924 freeAsmop(left,NULL,ic,FALSE);
9925 freeAsmop(result,NULL,ic,TRUE);
9930 /*-----------------------------------------------------------------*/
9931 /* genFarFarAssign - assignment when both are in far space */
9932 /*-----------------------------------------------------------------*/
9933 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9935 int size = AOP_SIZE(right);
9938 /* first push the right side on to the stack */
9940 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9942 pic14_emitcode ("push","acc");
9945 freeAsmop(right,NULL,ic,FALSE);
9946 /* now assign DPTR to result */
9947 aopOp(result,ic,FALSE);
9948 size = AOP_SIZE(result);
9950 pic14_emitcode ("pop","acc");
9951 aopPut(AOP(result),"a",--offset);
9953 freeAsmop(result,NULL,ic,FALSE);
9958 /*-----------------------------------------------------------------*/
9959 /* genAssign - generate code for assignment */
9960 /*-----------------------------------------------------------------*/
9961 static void genAssign (iCode *ic)
9963 operand *result, *right;
9964 int size, offset,know_W;
9965 unsigned long lit = 0L;
9967 result = IC_RESULT(ic);
9968 right = IC_RIGHT(ic) ;
9971 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9973 /* if they are the same */
9974 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9977 aopOp(right,ic,FALSE);
9978 aopOp(result,ic,TRUE);
9980 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9982 /* if they are the same registers */
9983 if (pic14_sameRegs(AOP(right),AOP(result)))
9986 /* special case: assign from __code */
9987 if (!IS_ITEMP(right) /* --> iTemps never reside in __code */
9988 && IS_SYMOP (right) /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
9989 && !IS_FUNC(OP_SYM_TYPE(right)) /* --> we would want its address instead of the first instruction */
9990 && !IS_CODEPTR(OP_SYM_TYPE(right)) /* --> get symbols address instread */
9991 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
9993 emitpComment ("genAssign from CODESPACE");
9994 genConstPointerGet (right, result, ic);
9998 /* just for symmetry reasons... */
9999 if (!IS_ITEMP(result)
10000 && IS_SYMOP (result)
10001 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
10003 assert ( !"cannot write to CODESPACE" );
10006 /* if the result is a bit */
10007 if (AOP_TYPE(result) == AOP_CRY) {
10009 /* if the right size is a literal then
10010 we know what the value is */
10011 if (AOP_TYPE(right) == AOP_LIT) {
10013 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10014 popGet(AOP(result),0));
10016 if (((int) operandLitValue(right)))
10017 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10018 AOP(result)->aopu.aop_dir,
10019 AOP(result)->aopu.aop_dir);
10021 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10022 AOP(result)->aopu.aop_dir,
10023 AOP(result)->aopu.aop_dir);
10027 /* the right is also a bit variable */
10028 if (AOP_TYPE(right) == AOP_CRY) {
10029 emitpcode(POC_BCF, popGet(AOP(result),0));
10030 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10031 emitpcode(POC_BSF, popGet(AOP(result),0));
10033 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10034 AOP(result)->aopu.aop_dir,
10035 AOP(result)->aopu.aop_dir);
10036 pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
10037 AOP(right)->aopu.aop_dir,
10038 AOP(right)->aopu.aop_dir);
10039 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10040 AOP(result)->aopu.aop_dir,
10041 AOP(result)->aopu.aop_dir);
10045 /* we need to or */
10046 emitpcode(POC_BCF, popGet(AOP(result),0));
10047 pic14_toBoolean(right);
10049 emitpcode(POC_BSF, popGet(AOP(result),0));
10050 //aopPut(AOP(result),"a",0);
10054 /* bit variables done */
10056 size = AOP_SIZE(result);
10058 if(AOP_TYPE(right) == AOP_LIT)
10059 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10061 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
10062 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10063 if(aopIdx(AOP(result),0) == 4) {
10064 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10065 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10066 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10069 DEBUGpic14_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
10074 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10075 if(AOP_TYPE(right) == AOP_LIT) {
10077 if(know_W != (int)(lit&0xff))
10078 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10080 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10082 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10086 } else if (AOP_TYPE(right) == AOP_CRY) {
10087 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10089 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10090 emitpcode(POC_INCF, popGet(AOP(result),0));
10093 mov2w_op (right, offset);
10094 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10102 freeAsmop (right,NULL,ic,FALSE);
10103 freeAsmop (result,NULL,ic,TRUE);
10106 /*-----------------------------------------------------------------*/
10107 /* genJumpTab - genrates code for jump table */
10108 /*-----------------------------------------------------------------*/
10109 static void genJumpTab (iCode *ic)
10115 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10117 aopOp(IC_JTCOND(ic),ic,FALSE);
10118 /* get the condition into accumulator */
10119 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10121 /* multiply by three */
10122 pic14_emitcode("add","a,acc");
10123 pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10125 jtab = newiTempLabel(NULL);
10126 pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10127 pic14_emitcode("jmp","@a+dptr");
10128 pic14_emitcode("","%05d_DS_:",jtab->key+100);
10130 emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10131 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10132 emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10133 emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10135 emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10136 emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10137 emitpLabel(jtab->key);
10139 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10141 /* now generate the jump labels */
10142 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10143 jtab = setNextItem(IC_JTLABELS(ic))) {
10144 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10145 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10151 /*-----------------------------------------------------------------*/
10152 /* genMixedOperation - gen code for operators between mixed types */
10153 /*-----------------------------------------------------------------*/
10155 TSD - Written for the PIC port - but this unfortunately is buggy.
10156 This routine is good in that it is able to efficiently promote
10157 types to different (larger) sizes. Unfortunately, the temporary
10158 variables that are optimized out by this routine are sometimes
10159 used in other places. So until I know how to really parse the
10160 iCode tree, I'm going to not be using this routine :(.
10162 static int genMixedOperation (iCode *ic)
10166 operand *result = IC_RESULT(ic);
10167 sym_link *ctype = operandType(IC_LEFT(ic));
10168 operand *right = IC_RIGHT(ic);
10174 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10176 pic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10182 nextright = IC_RIGHT(nextic);
10183 nextleft = IC_LEFT(nextic);
10184 nextresult = IC_RESULT(nextic);
10186 aopOp(right,ic,FALSE);
10187 aopOp(result,ic,FALSE);
10188 aopOp(nextright, nextic, FALSE);
10189 aopOp(nextleft, nextic, FALSE);
10190 aopOp(nextresult, nextic, FALSE);
10192 if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10194 operand *t = right;
10198 pic14_emitcode(";remove right +","");
10200 } else if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10202 operand *t = right;
10206 pic14_emitcode(";remove left +","");
10210 big = AOP_SIZE(nextleft);
10211 small = AOP_SIZE(nextright);
10213 switch(nextic->op) {
10216 pic14_emitcode(";optimize a +","");
10217 /* if unsigned or not an integral type */
10218 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10219 pic14_emitcode(";add a bit to something","");
10222 pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10224 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10225 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10226 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10228 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10236 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10237 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10238 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10241 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10243 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10244 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10245 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10246 pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10247 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10250 pic14_emitcode("rlf","known_zero,w");
10257 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10258 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10259 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10261 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10271 freeAsmop(right,NULL,ic,TRUE);
10272 freeAsmop(result,NULL,ic,TRUE);
10273 freeAsmop(nextright,NULL,ic,TRUE);
10274 freeAsmop(nextleft,NULL,ic,TRUE);
10276 nextic->generated = 1;
10283 /*-----------------------------------------------------------------*/
10284 /* genCast - gen code for casting */
10285 /*-----------------------------------------------------------------*/
10286 static void genCast (iCode *ic)
10288 operand *result = IC_RESULT(ic);
10289 sym_link *restype = operandType(result);
10290 sym_link *rtype = operandType(IC_RIGHT(ic));
10291 operand *right = IC_RIGHT(ic);
10295 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10296 /* if they are equivalent then do nothing */
10297 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10300 aopOp(right,ic,FALSE) ;
10301 aopOp(result,ic,FALSE);
10303 DEBUGpic14_AopType(__LINE__,NULL,right,result);
10305 /* if the result is a bit */
10306 if (AOP_TYPE(result) == AOP_CRY) {
10307 assert(!"assigning to bit variables is not supported");
10310 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10312 size = AOP_SIZE(result);
10314 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10316 emitpcode(POC_CLRF, popGet(AOP(result),0));
10317 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10318 emitpcode(POC_INCF, popGet(AOP(result),0));
10321 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
10326 if (IS_PTR(restype))
10328 operand *result = IC_RESULT(ic);
10329 //operand *left = IC_LEFT(ic);
10330 operand *right = IC_RIGHT(ic);
10333 /* copy common part */
10334 int max, size = AOP_SIZE(result);
10335 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10336 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10338 /* warn if we discard generic opinter tag */
10339 if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10341 //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10347 mov2w_op (right, size);
10348 movwf (AOP(result), size);
10351 /* upcast into generic pointer type? */
10352 if (IS_GENPTR(restype)
10353 && (size < AOP_SIZE(result))
10354 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10356 //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10359 switch (DCL_TYPE(rtype))
10361 case POINTER: /* __data */
10362 case FPOINTER: /* __data */
10363 assert (AOP_SIZE(right) == 2);
10364 tag = GPTRTAG_DATA;
10367 case CPOINTER: /* __code */
10368 assert (AOP_SIZE(right) == 2);
10369 tag = GPTRTAG_CODE;
10372 case GPOINTER: /* unknown destination, __data or __code */
10373 /* assume __data space (address of immediate) */
10374 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10375 if (AOP(right)->code)
10376 tag = GPTRTAG_CODE;
10378 tag = GPTRTAG_DATA;
10382 assert (!"unhandled pointer type");
10385 /* convert other values into pointers to __data space */
10386 tag = GPTRTAG_DATA;
10389 assert (AOP_SIZE(result) == 3);
10391 emitpcode(POC_CLRF, popGet(AOP(result), 2));
10393 emitpcode(POC_MOVLW, popGetLit(tag));
10394 movwf(AOP(result), 2);
10397 addSign(result, max, 0);
10402 /* if they are the same size : or less */
10403 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10405 /* if they are in the same place */
10406 if (pic14_sameRegs(AOP(right),AOP(result)))
10409 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10410 if (IS_PTR_CONST(rtype))
10411 DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10412 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10413 DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10415 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10416 emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10417 emitpcode(POC_MOVWF, popGet(AOP(result),0));
10418 emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10419 emitpcode(POC_MOVWF, popGet(AOP(result),1));
10420 if(AOP_SIZE(result) <2)
10421 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10425 /* if they in different places then copy */
10426 size = AOP_SIZE(result);
10429 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10430 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10432 //aopPut(AOP(result),
10433 // aopGet(AOP(right),offset,FALSE,FALSE),
10442 /* so we now know that the size of destination is greater
10443 than the size of the source.
10444 Now, if the next iCode is an operator then we might be
10445 able to optimize the operation without performing a cast.
10447 if(0 && genMixedOperation(ic)) {
10448 /* XXX: cannot optimize: must copy regs! */
10452 /* we move to result for the size of source */
10453 size = AOP_SIZE(right);
10456 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10457 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10461 addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10464 freeAsmop(right,NULL,ic,TRUE);
10465 freeAsmop(result,NULL,ic,TRUE);
10469 /*-----------------------------------------------------------------*/
10470 /* genDjnz - generate decrement & jump if not zero instrucion */
10471 /*-----------------------------------------------------------------*/
10472 static int genDjnz (iCode *ic, iCode *ifx)
10474 symbol *lbl, *lbl1;
10476 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10481 /* if the if condition has a false label
10482 then we cannot save */
10486 /* if the minus is not of the form
10488 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10489 !IS_OP_LITERAL(IC_RIGHT(ic)))
10492 if (operandLitValue(IC_RIGHT(ic)) != 1)
10495 /* if the size of this greater than one then no
10497 if (getSize(operandType(IC_RESULT(ic))) > 1)
10500 /* otherwise we can save BIG */
10501 lbl = newiTempLabel(NULL);
10502 lbl1= newiTempLabel(NULL);
10504 aopOp(IC_RESULT(ic),ic,FALSE);
10506 if (IS_AOP_PREG(IC_RESULT(ic))) {
10507 pic14_emitcode("dec","%s",
10508 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10509 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10510 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10514 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10515 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10517 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10518 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10521 /* pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10522 /* pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10523 /* pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10524 /* pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10527 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10528 ifx->generated = 1;
10532 /*-----------------------------------------------------------------*/
10533 /* genReceive - generate code for a receive iCode */
10534 /*-----------------------------------------------------------------*/
10535 static void genReceive (iCode *ic)
10538 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10540 if (isOperandInFarSpace(IC_RESULT(ic)) &&
10541 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10542 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10544 int size = getSize(operandType(IC_RESULT(ic)));
10545 int offset = fReturnSizePic - size;
10547 pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10548 fReturn[fReturnSizePic - offset - 1] : "acc"));
10551 aopOp(IC_RESULT(ic),ic,FALSE);
10552 size = AOP_SIZE(IC_RESULT(ic));
10555 pic14_emitcode ("pop","acc");
10556 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10561 aopOp(IC_RESULT(ic),ic,FALSE);
10563 assignResultValue(IC_RESULT(ic));
10566 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10569 /*-----------------------------------------------------------------*/
10570 /* genDummyRead - generate code for dummy read of volatiles */
10571 /*-----------------------------------------------------------------*/
10573 genDummyRead (iCode * ic)
10576 pic14_emitcode ("; genDummyRead","");
10577 pic14_emitcode ("; not implemented","");
10582 /*-----------------------------------------------------------------*/
10583 /* genpic14Code - generate code for pic14 based controllers */
10584 /*-----------------------------------------------------------------*/
10586 * At this point, ralloc.c has gone through the iCode and attempted
10587 * to optimize in a way suitable for a PIC. Now we've got to generate
10588 * PIC instructions that correspond to the iCode.
10590 * Once the instructions are generated, we'll pass through both the
10591 * peep hole optimizer and the pCode optimizer.
10592 *-----------------------------------------------------------------*/
10594 void genpic14Code (iCode *lic)
10601 lineHead = lineCurr = NULL;
10603 pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10606 /* if debug information required */
10607 if (options.debug && currFunc) {
10609 debugFile->writeFunction (currFunc, lic);
10614 for (ic = lic ; ic ; ic = ic->next ) {
10616 //DEBUGpic14_emitcode(";ic","");
10617 //fprintf (stderr, "in ic loop\n");
10618 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10619 //ic->lineno, printCLine(ic->filename, ic->lineno));
10621 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10623 //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10624 cline = printCLine (ic->filename, ic->lineno);
10625 if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10626 addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10627 //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10630 if (options.iCodeInAsm) {
10631 emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10633 /* if the result is marked as
10634 spilt and rematerializable or code for
10635 this has already been generated then
10637 if (resultRemat(ic) || ic->generated )
10640 /* depending on the operation */
10659 /* IPOP happens only when trying to restore a
10660 spilt live range, if there is an ifx statement
10661 following this pop then the if statement might
10662 be using some of the registers being popped which
10663 would destory the contents of the register so
10664 we need to check for this condition and handle it */
10666 ic->next->op == IFX &&
10667 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10668 genIfx (ic->next,ic);
10686 genEndFunction (ic);
10706 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10723 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
10727 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10734 /* note these two are xlated by algebraic equivalence
10735 during parsing SDCC.y */
10736 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10737 "got '>=' or '<=' shouldn't have come here");
10741 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10753 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10757 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10761 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10785 genRightShift (ic);
10788 case GET_VALUE_AT_ADDRESS:
10793 if (POINTER_SET(ic))
10820 addSet(&_G.sendSet,ic);
10823 case DUMMY_READ_VOLATILE:
10828 fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10835 /* now we are ready to call the
10836 peep hole optimizer */
10837 if (!options.nopeep) {
10838 peepHole (&lineHead);
10840 /* now do the actual printing */
10841 printLine (lineHead,codeOutFile);
10844 DFPRINTF((stderr,"printing pBlock\n\n"));
10845 printpBlock(stdout,pb);
10851 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10852 * (meaning: representing its own address) or not (referencing its contents).
10853 * This can only be decided based on the operand's type. */
10855 aop_isLitLike (asmop *aop)
10858 if (aop->type == AOP_LIT) return 1;
10859 if (aop->type == AOP_IMMD) return 1;
10860 if ((aop->type == AOP_PCODE) &&
10861 ((aop->aopu.pcop->type == PO_LITERAL)))
10863 /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10864 * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10871 op_isLitLike (operand *op)
10874 if (aop_isLitLike (AOP(op))) return 1;
10875 if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10876 if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;