1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for pic
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 PIC port - Scott Dattalo scott@dattalo.com (2000)
8 cont'd - Raphael Neider <rneider AT web.de> (2005)
10 This program is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the
12 Free Software Foundation; either version 2, or (at your option) any
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 In other words, you are welcome to use, share and improve this program.
25 You are forbidden to forbid anyone else to use, share and improve
26 what you give them. Help stamp out software-hoarding!
29 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
30 Made everything static
31 -------------------------------------------------------------------------*/
37 #include "SDCCglobl.h"
41 #include "SDCCpeeph.h"
46 /* When changing these, you must also update the assembler template
47 * in device/lib/libsdcc/macros.inc */
48 #define GPTRTAG_DATA 0x00
49 #define GPTRTAG_CODE 0x80
51 /* The PIC port(s) need not differentiate between POINTER and FPOINTER. */
52 #define PIC_IS_DATA_PTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
53 #define PIC_IS_FARPTR(x) (PIC_IS_DATA_PTR(x))
55 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
56 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
57 void genMult8X8_8 (operand *, operand *,operand *);
58 extern void printpBlock(FILE *of, pBlock *pb);
60 static int labelOffset=0;
61 extern int debug_verbose;
62 extern int pic14_hasInterrupt;
63 //static int optimized_for_speed = 0;
65 /* max_key keeps track of the largest label number used in
66 a function. This is then used to adjust the label offset
67 for the next function.
70 static int GpsuedoStkPtr=0;
72 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
73 extern char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
74 unsigned int pic14aopLiteral (value *val, int offset);
75 const char *AopType(short type);
77 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0x00ff)
79 /* this is the down and dirty file with all kinds of
80 kludgy & hacky stuff. This is what it is all about
81 CODE GENERATION for a specific MCU . some of the
82 routines may be reusable, will have to see */
84 static char *zero = "#0x00";
85 static char *one = "#0x01";
86 static char *spname = "sp";
88 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
89 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
90 static char **fReturn = fReturnpic14;
92 //static char *accUse[] = {"a","b"};
94 //static short rbank = -1;
106 /* Resolved ifx structure. This structure stores information
107 about an iCode ifx that makes it easier to generate code.
109 typedef struct resolvedIfx {
110 symbol *lbl; /* pointer to a label */
111 int condition; /* true or false ifx */
112 int generated; /* set true when the code associated with the ifx
116 extern int pic14_ptrRegReq ;
117 extern int pic14_nRegs;
118 extern FILE *codeOutFile;
119 static void saverbank (int, iCode *,bool);
121 static lineNode *lineHead = NULL;
122 static lineNode *lineCurr = NULL;
125 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
126 0xE0, 0xC0, 0x80, 0x00};
127 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
128 0x07, 0x03, 0x01, 0x00};
133 /*-----------------------------------------------------------------*/
134 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
135 /* exponent of 2 is returned, otherwise -1 is */
137 /* note that this is similar to the function `powof2' in SDCCsymt */
141 /*-----------------------------------------------------------------*/
142 static int my_powof2 (unsigned long num)
145 if( (num & (num-1)) == 0) {
158 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
161 DEBUGpic14_emitcode ("; ","line = %d result %s=%s, size=%d, left %s=%s, size=%d, right %s=%s, size=%d",
163 ((result) ? AopType(AOP_TYPE(result)) : "-"),
164 ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
165 ((result) ? AOP_SIZE(result) : 0),
166 ((left) ? AopType(AOP_TYPE(left)) : "-"),
167 ((left) ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
168 ((left) ? AOP_SIZE(left) : 0),
169 ((right) ? AopType(AOP_TYPE(right)) : "-"),
170 ((right) ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
171 ((right) ? AOP_SIZE(right) : 0));
175 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
178 DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
180 ((result) ? AopType(AOP_TYPE(result)) : "-"),
181 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
182 ((left) ? AopType(AOP_TYPE(left)) : "-"),
183 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
184 ((right) ? AopType(AOP_TYPE(right)) : "-"),
185 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
189 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
192 char lb[INITIAL_INLINEASM];
193 unsigned char *lbp = (unsigned char *)lb;
195 if(!debug_verbose && !options.debug)
202 sprintf(lb,"%s\t",inst);
204 sprintf(lb,"%s",inst);
205 vsprintf(lb+(strlen(lb)),fmt,ap);
209 while (isspace(*lbp)) lbp++;
212 lineCurr = (lineCurr ?
213 connectLine(lineCurr,newLineNode(lb)) :
214 (lineHead = newLineNode(lb)));
215 lineCurr->isInline = _G.inLine;
216 lineCurr->isDebug = _G.debugLine;
218 addpCode2pBlock(pb,newpCodeCharP(lb));
223 static void Safe_vsnprintf (char *buf, size_t size, const char *fmt, va_list ap)
225 #if defined (HAVE_VSNPRINTF)
226 vsnprintf (buf, size, fmt, ap);
227 #elif defined (HAVE_VSPRINTF)
228 vsprintf (buf, size, fmt, ap);
229 if (strlen (buf) >= size)
231 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
233 #elif defined (HAVE_SNPRINTF)
234 snprintf (buf, size, "vs(n)printf required");
235 #elif defined (HAVE_SRINTF)
236 sprintf (buf, "vs(n)printf required");
237 if (strlen (buf) >= size)
239 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
242 assert ( !"neither vsnprintf nor vsprintf is present -- unable to proceed" );
246 void emitpComment (const char *fmt, ...)
253 Safe_vsnprintf (buffer, 4096, fmt, va);
254 //fprintf (stderr, "%s\n" ,buffer);
255 addpCode2pBlock (pb, newpCodeCharP (buffer));
258 Safe_vsnprintf (buffer, 4096, fmt, va);
259 fprintf (stderr, "No current pBlock -- discarding comment [%s]\n", buffer);
265 void emitpLabel(int key)
267 addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
270 /* gen.h defines a macro emitpcode that should be used to call emitpcode
271 * as this allows for easy debugging (ever asked the question: where was
272 * this instruction geenrated? Here is the answer... */
273 void emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
276 addpCode2pBlock(pb,newpCode(poc,pcop));
278 DEBUGpic14_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
281 void emitpcodeNULLop(PIC_OPCODE poc)
284 addpCode2pBlock(pb,newpCode(poc,NULL));
289 /*-----------------------------------------------------------------*/
290 /* pic14_emitcode - writes the code into a file : for now it is simple */
291 /*-----------------------------------------------------------------*/
292 void pic14_emitcode (char *inst,char *fmt, ...)
295 char lb[INITIAL_INLINEASM];
296 unsigned char *lbp = (unsigned char *)lb;
302 sprintf(lb,"%s\t",inst);
304 sprintf(lb,"%s",inst);
305 vsprintf(lb+(strlen(lb)),fmt,ap);
309 while (isspace(*lbp)) lbp++;
312 lineCurr = (lineCurr ?
313 connectLine(lineCurr,newLineNode(lb)) :
314 (lineHead = newLineNode(lb)));
315 lineCurr->isInline = _G.inLine;
316 lineCurr->isDebug = _G.debugLine;
319 addpCode2pBlock(pb,newpCodeCharP(lb));
324 /*-----------------------------------------------------------------*/
325 /* pic14_emitDebuggerSymbol - associate the current code location */
326 /* with a debugger symbol */
327 /*-----------------------------------------------------------------*/
329 pic14_emitDebuggerSymbol (char * debugSym)
332 pic14_emitcode ("", ";%s ==.", debugSym);
337 /*-----------------------------------------------------------------*/
338 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
339 /*-----------------------------------------------------------------*/
340 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
342 bool r0iu = FALSE , r1iu = FALSE;
343 bool r0ou = FALSE , r1ou = FALSE;
345 /* the logic: if r0 & r1 used in the instruction
346 then we are in trouble otherwise */
348 /* first check if r0 & r1 are used by this
349 instruction, in which case we are in trouble */
350 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
351 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
356 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
357 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
359 /* if no usage of r0 then return it */
360 if (!r0iu && !r0ou) {
361 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
362 (*aopp)->type = AOP_R0;
364 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
367 /* if no usage of r1 then return it */
368 if (!r1iu && !r1ou) {
369 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
370 (*aopp)->type = AOP_R1;
372 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
375 /* now we know they both have usage */
376 /* if r0 not used in this instruction */
378 /* push it if not already pushed */
380 //pic14_emitcode ("push","%s",
381 // pic14_regWithIdx(R0_IDX)->dname);
385 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
386 (*aopp)->type = AOP_R0;
388 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
391 /* if r1 not used then */
394 /* push it if not already pushed */
396 //pic14_emitcode ("push","%s",
397 // pic14_regWithIdx(R1_IDX)->dname);
401 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
402 (*aopp)->type = AOP_R1;
403 return pic14_regWithIdx(R1_IDX);
407 /* I said end of world but not quite end of world yet */
408 /* if this is a result then we can push it on the stack*/
410 (*aopp)->type = AOP_STK;
414 /* other wise this is true end of the world */
415 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
416 "getFreePtr should never reach here");
421 /*-----------------------------------------------------------------*/
422 /* newAsmop - creates a new asmOp */
423 /*-----------------------------------------------------------------*/
424 asmop *newAsmop (short type)
428 aop = Safe_calloc(1,sizeof(asmop));
433 static void genSetDPTR(int n)
437 pic14_emitcode(";", "Select standard DPTR");
438 pic14_emitcode("mov", "dps, #0x00");
442 pic14_emitcode(";", "Select alternate DPTR");
443 pic14_emitcode("mov", "dps, #0x01");
447 /*-----------------------------------------------------------------*/
448 /* resolveIfx - converts an iCode ifx into a form more useful for */
449 /* generating code */
450 /*-----------------------------------------------------------------*/
451 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
456 // DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
458 resIfx->condition = 1; /* assume that the ifx is true */
459 resIfx->generated = 0; /* indicate that the ifx has not been used */
462 resIfx->lbl = NULL; /* this is wrong: newiTempLabel(NULL); / * oops, there is no ifx. so create a label */
464 DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
465 __FUNCTION__,__LINE__,resIfx->lbl->key);
469 resIfx->lbl = IC_TRUE(ifx);
471 resIfx->lbl = IC_FALSE(ifx);
472 resIfx->condition = 0;
476 DEBUGpic14_emitcode("; ***","ifx true is non-null");
478 DEBUGpic14_emitcode("; ***","ifx false is non-null");
482 // DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
485 /*-----------------------------------------------------------------*/
486 /* pointerCode - returns the code for a pointer type */
487 /*-----------------------------------------------------------------*/
489 static int pointerCode (sym_link *etype)
492 return PTR_TYPE(SPEC_OCLS(etype));
497 /*-----------------------------------------------------------------*/
498 /* aopForSym - for a true symbol */
499 /*-----------------------------------------------------------------*/
500 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
503 memmap *space= SPEC_OCLS(sym->etype);
505 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
506 /* if already has one */
511 /* assign depending on the storage class */
512 /* if it is on the stack or indirectly addressable */
513 /* space we need to assign either r0 or r1 to it */
514 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
515 sym->aop = aop = newAsmop(0);
516 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
517 aop->size = getSize(sym->type);
519 /* now assign the address of the variable to
520 the pointer register */
521 if (aop->type != AOP_STK) {
525 pic14_emitcode("push","acc");
527 pic14_emitcode("mov","a,_bp");
528 pic14_emitcode("add","a,#0x%02x",
530 ((char)(sym->stack - _G.nRegsSaved )) :
531 ((char)sym->stack)) & 0xff);
532 pic14_emitcode("mov","%s,a",
533 aop->aopu.aop_ptr->name);
536 pic14_emitcode("pop","acc");
538 pic14_emitcode("mov","%s,#%s",
539 aop->aopu.aop_ptr->name,
541 aop->paged = space->paged;
543 aop->aopu.aop_stk = sym->stack;
547 if (sym->onStack && options.stack10bit)
549 /* It's on the 10 bit stack, which is located in
553 //DEBUGpic14_emitcode(";","%d",__LINE__);
556 pic14_emitcode("push","acc");
558 pic14_emitcode("mov","a,_bp");
559 pic14_emitcode("add","a,#0x%02x",
561 ((char)(sym->stack - _G.nRegsSaved )) :
562 ((char)sym->stack)) & 0xff);
565 pic14_emitcode ("mov","dpx1,#0x40");
566 pic14_emitcode ("mov","dph1,#0x00");
567 pic14_emitcode ("mov","dpl1, a");
571 pic14_emitcode("pop","acc");
573 sym->aop = aop = newAsmop(AOP_DPTR2);
574 aop->size = getSize(sym->type);
579 //DEBUGpic14_emitcode(";","%d",__LINE__);
580 /* if in bit space */
581 if (IN_BITSPACE(space)) {
582 sym->aop = aop = newAsmop (AOP_CRY);
583 aop->aopu.aop_dir = sym->rname ;
584 aop->size = getSize(sym->type);
585 //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
588 /* if it is in direct space */
589 if (IN_DIRSPACE(space)) {
590 sym->aop = aop = newAsmop (AOP_DIR);
591 aop->aopu.aop_dir = sym->rname ;
592 aop->size = getSize(sym->type);
593 DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
597 /* special case for a function */
598 if (IS_FUNC(sym->type)) {
600 sym->aop = aop = newAsmop(AOP_PCODE);
601 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
602 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
603 PCOI(aop->aopu.pcop)->_function = 1;
604 PCOI(aop->aopu.pcop)->index = 0;
605 aop->size = FPTRSIZE;
607 sym->aop = aop = newAsmop(AOP_IMMD);
608 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
609 strcpy(aop->aopu.aop_immd,sym->rname);
610 aop->size = FPTRSIZE;
612 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
616 if (IS_ARRAY(sym->type)) {
617 sym->aop = aop = newAsmop(AOP_PCODE);
618 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
619 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
620 PCOI(aop->aopu.pcop)->_function = 0;
621 PCOI(aop->aopu.pcop)->index = 0;
622 aop->size = getSize(sym->etype) * DCL_ELEM(sym->type);
624 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
628 /* only remaining is far space */
629 /* in which case DPTR gets the address */
630 sym->aop = aop = newAsmop(AOP_PCODE);
632 aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
633 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
634 PCOI(aop->aopu.pcop)->index = 0;
636 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
637 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
639 allocDirReg (IC_LEFT(ic));
641 aop->size = FPTRSIZE;
643 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
644 sym->aop = aop = newAsmop(AOP_DPTR);
645 pic14_emitcode ("mov","dptr,#%s", sym->rname);
646 aop->size = getSize(sym->type);
648 DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
651 /* if it is in code space */
652 if (IN_CODESPACE(space))
658 /*-----------------------------------------------------------------*/
659 /* aopForRemat - rematerialzes an object */
660 /*-----------------------------------------------------------------*/
661 static asmop *aopForRemat (operand *op) // x symbol *sym)
663 symbol *sym = OP_SYMBOL(op);
665 asmop *aop = newAsmop(AOP_PCODE);
669 ic = sym->rematiCode;
671 DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
672 if(IS_OP_POINTER(op)) {
673 DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
677 val += (int) operandLitValue(IC_RIGHT(ic));
678 } else if (ic->op == '-') {
679 val -= (int) operandLitValue(IC_RIGHT(ic));
683 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
686 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
687 aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
688 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
689 PCOI(aop->aopu.pcop)->index = val;
691 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
692 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
693 val, IS_PTR_CONST(operandType(op)));
695 // DEBUGpic14_emitcode(";","aop type %s",AopType(AOP_TYPE(IC_LEFT(ic))));
697 allocDirReg (IC_LEFT(ic));
702 int aopIdx (asmop *aop, int offset)
707 if(aop->type != AOP_REG)
710 return aop->aopu.aop_reg[offset]->rIdx;
713 /*-----------------------------------------------------------------*/
714 /* regsInCommon - two operands have some registers in common */
715 /*-----------------------------------------------------------------*/
716 static bool regsInCommon (operand *op1, operand *op2)
721 /* if they have registers in common */
722 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
725 sym1 = OP_SYMBOL(op1);
726 sym2 = OP_SYMBOL(op2);
728 if (sym1->nRegs == 0 || sym2->nRegs == 0)
731 for (i = 0 ; i < sym1->nRegs ; i++) {
736 for (j = 0 ; j < sym2->nRegs ;j++ ) {
740 if (sym2->regs[j] == sym1->regs[i])
748 /*-----------------------------------------------------------------*/
749 /* operandsEqu - equivalent */
750 /*-----------------------------------------------------------------*/
751 static bool operandsEqu ( operand *op1, operand *op2)
755 /* if they not symbols */
756 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
759 sym1 = OP_SYMBOL(op1);
760 sym2 = OP_SYMBOL(op2);
762 /* if both are itemps & one is spilt
763 and the other is not then false */
764 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
765 sym1->isspilt != sym2->isspilt )
768 /* if they are the same */
772 if (sym1->rname[0] && sym2->rname[0]
773 && strcmp (sym1->rname, sym2->rname) == 0)
777 /* if left is a tmp & right is not */
781 (sym1->usl.spillLoc == sym2))
788 (sym2->usl.spillLoc == sym1))
794 /*-----------------------------------------------------------------*/
795 /* pic14_sameRegs - two asmops have the same registers */
796 /*-----------------------------------------------------------------*/
797 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
804 if (aop1->type != AOP_REG ||
805 aop2->type != AOP_REG )
808 if (aop1->size != aop2->size )
811 for (i = 0 ; i < aop1->size ; i++ )
812 if (aop1->aopu.aop_reg[i] !=
813 aop2->aopu.aop_reg[i] )
819 /*-----------------------------------------------------------------*/
820 /* aopOp - allocates an asmop for an operand : */
821 /*-----------------------------------------------------------------*/
822 void aopOp (operand *op, iCode *ic, bool result)
831 /* if this a literal */
832 if (IS_OP_LITERAL(op)) {
833 op->aop = aop = newAsmop(AOP_LIT);
834 aop->aopu.aop_lit = op->operand.valOperand;
835 aop->size = getSize(operandType(op));
840 sym_link *type = operandType(op);
841 if(IS_PTR_CONST(type))
842 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
845 /* if already has a asmop then continue */
849 /* if the underlying symbol has a aop */
850 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
851 DEBUGpic14_emitcode(";","%d",__LINE__);
852 op->aop = OP_SYMBOL(op)->aop;
856 /* if this is a true symbol */
857 if (IS_TRUE_SYMOP(op)) {
858 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
859 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
863 /* this is a temporary : this has
869 e) can be a return use only */
874 /* if the type is a conditional */
875 if (sym->regType == REG_CND) {
876 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
881 /* if it is spilt then two situations
883 b) has a spill location */
884 if (sym->isspilt || sym->nRegs == 0) {
886 DEBUGpic14_emitcode(";","%d",__LINE__);
887 /* rematerialize it NOW */
890 sym->aop = op->aop = aop = aopForRemat (op);
891 aop->size = getSize(sym->type);
892 //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
897 /* WREG is not usable as an ordinary operand with PIC architecture,
898 * one might introduce a scratch register that can be used to make
899 * WREG accesible as an operand... disable WREG for now */
902 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
903 aop->size = getSize(sym->type);
904 for ( i = 0 ; i < 2 ; i++ )
905 aop->aopu.aop_str[i] = accUse[i];
906 DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
912 if(sym->isptr) { // && sym->uptr
913 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
914 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
916 //PCOI(aop->aopu.pcop)->_const = 0;
917 //PCOI(aop->aopu.pcop)->index = 0;
919 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
920 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
922 //allocDirReg (IC_LEFT(ic));
924 aop->size = getSize(sym->type);
925 DEBUGpic14_emitcode(";","%d",__LINE__);
932 aop = op->aop = sym->aop = newAsmop(AOP_STR);
933 aop->size = getSize(sym->type);
934 for ( i = 0 ; i < fReturnSizePic ; i++ )
935 aop->aopu.aop_str[i] = fReturn[i];
937 DEBUGpic14_emitcode(";","%d",__LINE__);
942 /* else spill location */
943 if (sym->usl.spillLoc)
945 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
947 /* force a new aop if sizes differ */
948 sym->usl.spillLoc->aop = NULL;
950 DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
951 __FUNCTION__,__LINE__,
952 sym->usl.spillLoc->rname,
953 sym->rname, sym->usl.spillLoc->offset);
955 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
956 //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
957 aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname,
959 sym->usl.spillLoc->offset);
960 aop->size = getSize(sym->type);
967 sym_link *type = operandType(op);
968 if(IS_PTR_CONST(type))
969 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
972 /* must be in a register */
973 DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
974 sym->aop = op->aop = aop = newAsmop(AOP_REG);
975 aop->size = sym->nRegs;
976 for ( i = 0 ; i < sym->nRegs ;i++)
977 aop->aopu.aop_reg[i] = sym->regs[i];
980 /*-----------------------------------------------------------------*/
981 /* freeAsmop - free up the asmop given to an operand */
982 /*----------------------------------------------------------------*/
983 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1000 /* depending on the asmop type only three cases need work AOP_RO
1001 , AOP_R1 && AOP_STK */
1003 switch (aop->type) {
1007 pic14_emitcode ("pop","ar0");
1011 bitVectUnSetBit(ic->rUsed,R0_IDX);
1017 pic14_emitcode ("pop","ar1");
1021 bitVectUnSetBit(ic->rUsed,R1_IDX);
1027 int stk = aop->aopu.aop_stk + aop->size;
1028 bitVectUnSetBit(ic->rUsed,R0_IDX);
1029 bitVectUnSetBit(ic->rUsed,R1_IDX);
1031 getFreePtr(ic,&aop,FALSE);
1033 if (options.stack10bit)
1035 /* I'm not sure what to do here yet... */
1038 "*** Warning: probably generating bad code for "
1039 "10 bit stack mode.\n");
1043 pic14_emitcode ("mov","a,_bp");
1044 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1045 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1047 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1051 pic14_emitcode("pop","acc");
1052 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1054 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1057 freeAsmop(op,NULL,ic,TRUE);
1059 pic14_emitcode("pop","ar0");
1064 pic14_emitcode("pop","ar1");
1072 /* all other cases just dealloc */
1076 OP_SYMBOL(op)->aop = NULL;
1077 /* if the symbol has a spill */
1079 SPIL_LOC(op)->aop = NULL;
1084 /*-----------------------------------------------------------------*/
1085 /* aopGet - for fetching value of the aop */
1086 /*-----------------------------------------------------------------*/
1087 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1092 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1093 /* offset is greater than
1095 if (offset > (aop->size - 1) &&
1096 aop->type != AOP_LIT)
1099 /* depending on type */
1100 switch (aop->type) {
1104 DEBUGpic14_emitcode(";","%d",__LINE__);
1105 /* if we need to increment it */
1106 while (offset > aop->coff) {
1107 pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);
1111 while (offset < aop->coff) {
1112 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1116 aop->coff = offset ;
1118 pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1119 return (dname ? "acc" : "a");
1121 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1122 rs = Safe_calloc(1,strlen(s)+1);
1128 DEBUGpic14_emitcode(";","%d",__LINE__);
1129 if (aop->type == AOP_DPTR2)
1134 while (offset > aop->coff) {
1135 pic14_emitcode ("inc","dptr");
1139 while (offset < aop->coff) {
1140 pic14_emitcode("lcall","__decdptr");
1146 pic14_emitcode("clr","a");
1147 pic14_emitcode("movc","a,@a+dptr");
1150 pic14_emitcode("movx","a,@dptr");
1153 if (aop->type == AOP_DPTR2)
1158 return (dname ? "acc" : "a");
1163 sprintf (s,"%s",aop->aopu.aop_immd);
1166 sprintf(s,"(%s >> %d)",
1171 aop->aopu.aop_immd);
1172 DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1173 rs = Safe_calloc(1,strlen(s)+1);
1179 sprintf(s,"(%s + %d)",
1182 DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1184 sprintf(s,"%s",aop->aopu.aop_dir);
1185 rs = Safe_calloc(1,strlen(s)+1);
1191 // return aop->aopu.aop_reg[offset]->dname;
1193 return aop->aopu.aop_reg[offset]->name;
1196 //pic14_emitcode(";","%d",__LINE__);
1197 return aop->aopu.aop_dir;
1200 DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1201 return "AOP_accumulator_bug";
1204 sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1205 rs = Safe_calloc(1,strlen(s)+1);
1210 aop->coff = offset ;
1211 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1214 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1216 return aop->aopu.aop_str[offset];
1220 pCodeOp *pcop = aop->aopu.pcop;
1221 DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1224 DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
1225 sprintf(s,"(%s+%d)", pcop->name,offset);
1227 DEBUGpic14_emitcode(";","%s",pcop->name);
1228 sprintf(s,"%s", pcop->name);
1231 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1234 rs = Safe_calloc(1,strlen(s)+1);
1240 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1241 "aopget got unsupported aop->type");
1246 /*-----------------------------------------------------------------*/
1247 /* popGetTempReg - create a new temporary pCodeOp */
1248 /*-----------------------------------------------------------------*/
1249 pCodeOp *popGetTempReg(void)
1254 pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1255 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1256 PCOR(pcop)->r->wasUsed=1;
1257 PCOR(pcop)->r->isFree=0;
1263 /*-----------------------------------------------------------------*/
1264 /* popReleaseTempReg - create a new temporary pCodeOp */
1265 /*-----------------------------------------------------------------*/
1266 void popReleaseTempReg(pCodeOp *pcop)
1269 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1270 PCOR(pcop)->r->isFree = 1;
1273 /*-----------------------------------------------------------------*/
1274 /* popGetLabel - create a new pCodeOp of type PO_LABEL */
1275 /*-----------------------------------------------------------------*/
1276 pCodeOp *popGetLabel(unsigned int key)
1279 DEBUGpic14_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1281 if(key>(unsigned int)max_key)
1284 return newpCodeOpLabel(NULL,key+100+labelOffset);
1287 /*-------------------------------------------------------------------*/
1288 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1289 /*-------------------------------------------------------------------*/
1290 pCodeOp *popGetHighLabel(unsigned int key)
1293 pcop = popGetLabel(key);
1294 PCOLAB(pcop)->offset = 1;
1298 /*-----------------------------------------------------------------*/
1299 /* popGetLit - asm operator to pcode operator conversion */
1300 /*-----------------------------------------------------------------*/
1301 pCodeOp *popGetLit(unsigned int lit)
1304 return newpCodeOpLit((unsigned char)lit);
1307 /*-----------------------------------------------------------------*/
1308 /* popGetImmd - asm operator to pcode immediate conversion */
1309 /*-----------------------------------------------------------------*/
1310 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1313 return newpCodeOpImmd(name, offset,index, 0, is_func);
1316 extern set *externs;
1318 /*-----------------------------------------------------------------*/
1319 /* popGetWithString - asm operator to pcode operator conversion */
1320 /*-----------------------------------------------------------------*/
1321 pCodeOp *popGetWithString(char *str, int isExtern)
1327 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1331 pcop = newpCodeOp(str,PO_STR);
1332 PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1337 pCodeOp *popGetExternal (char *str)
1339 pCodeOp *pcop = popGetWithString (str, 1);
1345 for (sym = setFirstItem (externs); !found && sym; sym = setNextItem (externs))
1347 if (!strcmp (str, sym->rname))
1353 sym = newSymbol(str, 0);
1354 strncpy(sym->rname, str, SDCC_NAME_MAX);
1355 addSet (&externs, sym);
1361 /*-----------------------------------------------------------------*/
1362 /* popRegFromString - */
1363 /*-----------------------------------------------------------------*/
1364 pCodeOp *popRegFromString(char *str, int size, int offset)
1367 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1368 pcop->type = PO_DIR;
1370 DEBUGpic14_emitcode(";","%d",__LINE__);
1375 pcop->name = Safe_calloc(1,strlen(str)+1);
1376 strcpy(pcop->name,str);
1378 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1380 PCOR(pcop)->r = dirregWithName(pcop->name);
1381 if(PCOR(pcop)->r == NULL) {
1382 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1383 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1384 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1386 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1388 PCOR(pcop)->instance = offset;
1393 /*-----------------------------------------------------------------*/
1394 /*-----------------------------------------------------------------*/
1395 pCodeOp *popRegFromIdx(int rIdx)
1399 DEBUGpic14_emitcode ("; ***","%s,%d , rIdx=0x%x",
1400 __FUNCTION__,__LINE__,rIdx);
1402 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1404 PCOR(pcop)->rIdx = rIdx;
1405 PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1406 PCOR(pcop)->r->isFree = 0;
1407 PCOR(pcop)->r->wasUsed = 1;
1409 pcop->type = PCOR(pcop)->r->pc_type;
1415 /*-----------------------------------------------------------------*/
1416 /* popGet - asm operator to pcode operator conversion */
1417 /*-----------------------------------------------------------------*/
1418 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1420 //char *s = buffer ;
1425 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1426 /* offset is greater than
1431 /* XXX: still needed for BIT operands (AOP_CRY) */
1432 if (offset > (aop->size - 1) &&
1433 aop->type != AOP_LIT)
1434 return NULL; //zero;
1436 /* depending on type */
1437 switch (aop->type) {
1444 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1448 DEBUGpic14_emitcode(";","%d",__LINE__);
1449 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1452 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1454 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1455 pcop->type = PO_DIR;
1457 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1458 strcpy(pcop->name,aop->aopu.aop_dir);
1459 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1460 if(PCOR(pcop)->r == NULL) {
1461 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1462 PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1463 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1465 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1467 PCOR(pcop)->instance = offset;
1475 assert (offset < aop->size);
1476 rIdx = aop->aopu.aop_reg[offset]->rIdx;
1478 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1479 PCOR(pcop)->rIdx = rIdx;
1480 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1481 PCOR(pcop)->r->wasUsed=1;
1482 PCOR(pcop)->r->isFree=0;
1484 PCOR(pcop)->instance = offset;
1485 pcop->type = PCOR(pcop)->r->pc_type;
1486 //rs = aop->aopu.aop_reg[offset]->name;
1487 DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1492 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1493 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1494 //if(PCOR(pcop)->r == NULL)
1495 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1499 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1502 DEBUGpic14_emitcode(";","%d %s",__LINE__,aop->aopu.aop_str[offset]);
1503 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1505 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1506 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1507 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1508 pcop->type = PCOR(pcop)->r->pc_type;
1509 pcop->name = PCOR(pcop)->r->name;
1516 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1518 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1519 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1520 switch (aop->aopu.pcop->type)
1523 pcop = pCodeOpCopy (aop->aopu.pcop);
1524 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1525 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1526 PCOI(pcop)->index += offset;
1527 //PCOI(pcop)->offset = 0;
1530 pcop = pCodeOpCopy (aop->aopu.pcop);
1531 PCOR(pcop)->instance = offset;
1534 assert ( !"unhandled pCode type" );
1540 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1541 "popGet got unsupported aop->type");
1545 /*-----------------------------------------------------------------*/
1546 /* popGetAddr - access the low/high word of a symbol (immediate) */
1547 /* (for non-PO_IMMEDIATEs this is the same as popGet) */
1548 /*-----------------------------------------------------------------*/
1549 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1551 if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1553 pCodeOp *pcop = aop->aopu.pcop;
1554 assert (offset <= GPTRSIZE);
1556 /* special case: index >= 2 should return GPOINTER-style values */
1559 pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1563 pcop = pCodeOpCopy (pcop);
1564 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1565 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1566 PCOI(pcop)->offset += offset;
1567 PCOI(pcop)->index += index;
1568 //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);
1571 return popGet (aop, offset + index);
1575 /*-----------------------------------------------------------------*/
1576 /* aopPut - puts a string for a aop */
1577 /*-----------------------------------------------------------------*/
1578 void aopPut (asmop *aop, char *s, int offset)
1583 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1585 if (aop->size && offset > ( aop->size - 1)) {
1586 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1587 "aopPut got offset > aop->size");
1591 /* will assign value to value */
1592 /* depending on where it is ofcourse */
1593 switch (aop->type) {
1596 sprintf(d,"(%s + %d)",
1597 aop->aopu.aop_dir,offset);
1598 fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1601 sprintf(d,"%s",aop->aopu.aop_dir);
1604 DEBUGpic14_emitcode(";","%d",__LINE__);
1606 pic14_emitcode("movf","%s,w",s);
1607 pic14_emitcode("movwf","%s",d);
1610 pic14_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
1611 if(offset >= aop->size) {
1612 emitpcode(POC_CLRF,popGet(aop,offset));
1615 emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
1618 emitpcode(POC_MOVWF,popGet(aop,offset));
1624 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1625 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1628 strcmp(s,"r0") == 0 ||
1629 strcmp(s,"r1") == 0 ||
1630 strcmp(s,"r2") == 0 ||
1631 strcmp(s,"r3") == 0 ||
1632 strcmp(s,"r4") == 0 ||
1633 strcmp(s,"r5") == 0 ||
1634 strcmp(s,"r6") == 0 ||
1635 strcmp(s,"r7") == 0 )
1636 pic14_emitcode("mov","%s,%s ; %d",
1637 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1641 if(strcmp(s,"W")==0 )
1642 pic14_emitcode("movf","%s,w ; %d",s,__LINE__);
1644 pic14_emitcode("movwf","%s",
1645 aop->aopu.aop_reg[offset]->name);
1647 if(strcmp(s,zero)==0) {
1648 emitpcode(POC_CLRF,popGet(aop,offset));
1650 } else if(strcmp(s,"W")==0) {
1651 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1652 pcop->type = PO_GPR_REGISTER;
1654 PCOR(pcop)->rIdx = -1;
1655 PCOR(pcop)->r = NULL;
1657 DEBUGpic14_emitcode(";","%d",__LINE__);
1658 pcop->name = Safe_strdup(s);
1659 emitpcode(POC_MOVFW,pcop);
1660 emitpcode(POC_MOVWF,popGet(aop,offset));
1661 } else if(strcmp(s,one)==0) {
1662 emitpcode(POC_CLRF,popGet(aop,offset));
1663 emitpcode(POC_INCF,popGet(aop,offset));
1665 emitpcode(POC_MOVWF,popGet(aop,offset));
1673 if (aop->type == AOP_DPTR2)
1679 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1680 "aopPut writting to code space");
1684 while (offset > aop->coff) {
1686 pic14_emitcode ("inc","dptr");
1689 while (offset < aop->coff) {
1691 pic14_emitcode("lcall","__decdptr");
1696 /* if not in accumulater */
1699 pic14_emitcode ("movx","@dptr,a");
1701 if (aop->type == AOP_DPTR2)
1709 while (offset > aop->coff) {
1711 pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1713 while (offset < aop->coff) {
1715 pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1721 pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1726 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1728 if (strcmp(s,"r0") == 0 ||
1729 strcmp(s,"r1") == 0 ||
1730 strcmp(s,"r2") == 0 ||
1731 strcmp(s,"r3") == 0 ||
1732 strcmp(s,"r4") == 0 ||
1733 strcmp(s,"r5") == 0 ||
1734 strcmp(s,"r6") == 0 ||
1735 strcmp(s,"r7") == 0 ) {
1737 sprintf(buffer,"a%s",s);
1738 pic14_emitcode("mov","@%s,%s",
1739 aop->aopu.aop_ptr->name,buffer);
1741 pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1746 if (strcmp(s,"a") == 0)
1747 pic14_emitcode("push","acc");
1749 pic14_emitcode("push","%s",s);
1754 /* if bit variable */
1755 if (!aop->aopu.aop_dir) {
1756 pic14_emitcode("clr","a");
1757 pic14_emitcode("rlc","a");
1760 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1763 pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1766 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1768 lbl = newiTempLabel(NULL);
1770 if (strcmp(s,"a")) {
1773 pic14_emitcode("clr","c");
1774 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1775 pic14_emitcode("cpl","c");
1776 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1777 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1784 if (strcmp(aop->aopu.aop_str[offset],s))
1785 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1790 if (!offset && (strcmp(s,"acc") == 0))
1793 if (strcmp(aop->aopu.aop_str[offset],s))
1794 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1798 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1799 "aopPut got unsupported aop->type");
1805 /*-----------------------------------------------------------------*/
1806 /* mov2w_op - generate either a MOVLW or MOVFW based operand type */
1807 /*-----------------------------------------------------------------*/
1808 static void mov2w_op (operand *op, int offset)
1813 /* for PO_IMMEDIATEs: use address or value? */
1814 if (op_isLitLike (op))
1816 /* access address of op */
1817 if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
1818 if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
1820 if (offset == GPTRSIZE-1)
1821 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1823 emitpcode (POC_MOVLW, popGetLit (0));
1826 emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
1828 /* access value stored in op */
1829 mov2w (AOP(op), offset);
1834 /*-----------------------------------------------------------------*/
1835 /* mov2w - generate either a MOVLW or MOVFW based operand type */
1836 /*-----------------------------------------------------------------*/
1837 void mov2w (asmop *aop, int offset)
1843 DEBUGpic14_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
1845 if ( aop_isLitLike (aop) )
1846 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1848 emitpcode(POC_MOVFW,popGet(aop,offset));
1852 static void movwf (asmop *op, int offset)
1854 emitpcode (POC_MOVWF, popGet(op, offset));
1857 static pCodeOp *get_argument_pcop (int idx)
1859 assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1860 return popRegFromIdx (Gstack_base_addr - (idx - 1));
1863 static pCodeOp *get_return_val_pcop (int offset)
1865 assert (offset > 0 && "the most significant byte is returned via WREG");
1866 return popRegFromIdx (Gstack_base_addr - (offset - 1));
1869 static void pass_argument (operand *op, int offset, int idx)
1872 mov2w_op (op, offset);
1874 emitpcode(POC_MOVWF, get_argument_pcop (idx));
1877 static void get_returnvalue (operand *op, int offset, int idx)
1880 emitpcode(POC_MOVFW, get_return_val_pcop (idx));
1881 movwf(AOP(op), offset);
1884 static void call_libraryfunc (char *name)
1886 /* library code might reside in different page... */
1887 emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1888 /* call the library function */
1889 emitpcode (POC_CALL, popGetExternal (name));
1890 /* might return from different page... */
1891 emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1894 /*-----------------------------------------------------------------*/
1895 /* reAdjustPreg - points a register back to where it should */
1896 /*-----------------------------------------------------------------*/
1897 static void reAdjustPreg (asmop *aop)
1901 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1903 if ((size = aop->size) <= 1)
1906 switch (aop->type) {
1910 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1914 if (aop->type == AOP_DPTR2)
1920 pic14_emitcode("lcall","__decdptr");
1923 if (aop->type == AOP_DPTR2)
1936 /*-----------------------------------------------------------------*/
1937 /* opIsGptr: returns non-zero if the passed operand is */
1938 /* a generic pointer type. */
1939 /*-----------------------------------------------------------------*/
1940 static int opIsGptr(operand *op)
1942 sym_link *type = operandType(op);
1944 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1945 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1953 /*-----------------------------------------------------------------*/
1954 /* pic14_getDataSize - get the operand data size */
1955 /*-----------------------------------------------------------------*/
1956 int pic14_getDataSize(operand *op)
1960 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1963 size = getSize(OP_SYM_ETYPE(op));
1965 //return AOP_SIZE(op);
1967 // tsd- in the pic port, the genptr size is 1, so this code here
1968 // fails. ( in the 8051 port, the size was 4).
1970 size = AOP_SIZE(op);
1971 if (IS_GENPTR(OP_SYM_TYPE(op)))
1973 sym_link *type = operandType(op);
1974 if (IS_GENPTR(type))
1976 /* generic pointer; arithmetic operations
1977 * should ignore the high byte (pointer type).
1980 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1987 /*-----------------------------------------------------------------*/
1988 /* pic14_outAcc - output Acc */
1989 /*-----------------------------------------------------------------*/
1990 void pic14_outAcc(operand *result)
1993 DEBUGpic14_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
1994 DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1997 size = pic14_getDataSize(result);
1999 emitpcode(POC_MOVWF,popGet(AOP(result),0));
2002 /* unsigned or positive */
2004 emitpcode(POC_CLRF,popGet(AOP(result),offset++));
2009 /*-----------------------------------------------------------------*/
2010 /* pic14_outBitC - output a bit C */
2011 /*-----------------------------------------------------------------*/
2012 void pic14_outBitC(operand *result)
2015 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2016 /* if the result is bit */
2017 if (AOP_TYPE(result) == AOP_CRY)
2018 aopPut(AOP(result),"c",0);
2020 pic14_emitcode("clr","a ; %d", __LINE__);
2021 pic14_emitcode("rlc","a");
2022 pic14_outAcc(result);
2026 /*-----------------------------------------------------------------*/
2027 /* pic14_toBoolean - emit code for orl a,operator(sizeop) */
2028 /*-----------------------------------------------------------------*/
2029 void pic14_toBoolean(operand *oper)
2031 int size = AOP_SIZE(oper);
2034 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2039 /* MOVFW does not load the flags... */
2040 if (AOP_TYPE(oper) == AOP_ACC) {
2041 emitpcode(POC_IORLW, popGetLit(0));
2044 emitpcode(POC_MOVLW, popGetLit(0));
2048 if ( AOP_TYPE(oper) != AOP_ACC) {
2049 emitpcode(POC_MOVFW,popGet(AOP(oper),0));
2054 while (offset < size) {
2055 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
2057 /* Z is set iff (oper == 0) */
2061 /*-----------------------------------------------------------------*/
2062 /* genNot - generate code for ! operation */
2063 /*-----------------------------------------------------------------*/
2064 static void genNot (iCode *ic)
2071 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2072 /* assign asmOps to operand & result */
2073 aopOp (IC_LEFT(ic),ic,FALSE);
2074 aopOp (IC_RESULT(ic),ic,TRUE);
2076 DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2077 /* if in bit space then a special case */
2078 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2079 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2080 emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
2081 emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
2083 emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
2084 emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
2085 emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
2090 size = AOP_SIZE(IC_LEFT(ic));
2091 mov2w (AOP(IC_LEFT(ic)),0);
2094 if (op_isLitLike (IC_LEFT(ic)))
2095 emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
2097 emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
2099 emitpcode(POC_MOVLW, popGetLit (0));
2101 emitpcode(POC_MOVLW, popGetLit (1));
2102 movwf(AOP(IC_RESULT(ic)), 0);
2104 for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
2106 emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
2111 /* release the aops */
2112 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2113 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2117 /*-----------------------------------------------------------------*/
2118 /* genCpl - generate code for complement */
2119 /*-----------------------------------------------------------------*/
2120 static void genCpl (iCode *ic)
2122 operand *left, *result;
2127 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2128 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2129 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2131 /* if both are in bit space then
2133 if (AOP_TYPE(result) == AOP_CRY &&
2134 AOP_TYPE(left) == AOP_CRY ) {
2136 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir);
2137 pic14_emitcode("cpl","c");
2138 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir);
2142 size = AOP_SIZE(result);
2143 if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
2146 if(AOP_TYPE(left) == AOP_ACC)
2147 emitpcode(POC_XORLW, popGetLit(0xff));
2149 emitpcode(POC_COMFW,popGet(AOP(left),offset));
2151 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
2154 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2158 /* release the aops */
2159 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2160 freeAsmop(result,NULL,ic,TRUE);
2163 /*-----------------------------------------------------------------*/
2164 /* genUminusFloat - unary minus for floating points */
2165 /*-----------------------------------------------------------------*/
2166 static void genUminusFloat(operand *op,operand *result)
2168 int size ,offset =0 ;
2173 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2174 /* for this we just need to flip the
2175 first it then copy the rest in place */
2176 size = AOP_SIZE(op) - 1;
2177 l = aopGet(AOP(op),3,FALSE,FALSE);
2181 pic14_emitcode("cpl","acc.7");
2182 aopPut(AOP(result),"a",3);
2186 aopGet(AOP(op),offset,FALSE,FALSE),
2192 /*-----------------------------------------------------------------*/
2193 /* genUminus - unary minus code generation */
2194 /*-----------------------------------------------------------------*/
2195 static void genUminus (iCode *ic)
2198 sym_link *optype, *rtype;
2202 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2204 aopOp(IC_LEFT(ic),ic,FALSE);
2205 aopOp(IC_RESULT(ic),ic,TRUE);
2207 /* if both in bit space then special
2209 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2210 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2212 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0));
2213 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2214 emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0));
2219 optype = operandType(IC_LEFT(ic));
2220 rtype = operandType(IC_RESULT(ic));
2222 /* if float then do float stuff */
2223 if (IS_FLOAT(optype)) {
2224 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2228 /* otherwise subtract from zero by taking the 2's complement */
2229 size = AOP_SIZE(IC_LEFT(ic));
2231 for(i=0; i<size; i++) {
2232 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2233 emitpcode(POC_COMF, popGet(AOP(IC_LEFT(ic)),i));
2235 emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2236 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2240 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0));
2241 for(i=1; i<size; i++) {
2243 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),i));
2247 /* release the aops */
2248 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2249 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2252 /*-----------------------------------------------------------------*/
2253 /* saveRegisters - will look for a call and save the registers */
2254 /*-----------------------------------------------------------------*/
2255 static void saveRegisters(iCode *lic)
2264 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2266 for (ic = lic ; ic ; ic = ic->next)
2267 if (ic->op == CALL || ic->op == PCALL)
2271 fprintf(stderr,"found parameter push with no function call\n");
2275 /* if the registers have been saved already then
2277 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2280 /* find the registers in use at this time
2281 and push them away to safety */
2282 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2286 if (options.useXstack) {
2287 if (bitVectBitValue(rsave,R0_IDX))
2288 pic14_emitcode("mov","b,r0");
2289 pic14_emitcode("mov","r0,%s",spname);
2290 for (i = 0 ; i < pic14_nRegs ; i++) {
2291 if (bitVectBitValue(rsave,i)) {
2293 pic14_emitcode("mov","a,b");
2295 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2296 pic14_emitcode("movx","@r0,a");
2297 pic14_emitcode("inc","r0");
2300 pic14_emitcode("mov","%s,r0",spname);
2301 if (bitVectBitValue(rsave,R0_IDX))
2302 pic14_emitcode("mov","r0,b");
2304 //for (i = 0 ; i < pic14_nRegs ; i++) {
2305 // if (bitVectBitValue(rsave,i))
2306 // pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2309 dtype = operandType(IC_LEFT(ic));
2310 if (currFunc && dtype &&
2311 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2312 IFFUNC_ISISR(currFunc->type) &&
2315 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2318 /*-----------------------------------------------------------------*/
2319 /* unsaveRegisters - pop the pushed registers */
2320 /*-----------------------------------------------------------------*/
2321 static void unsaveRegisters (iCode *ic)
2328 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2329 /* find the registers in use at this time
2330 and push them away to safety */
2331 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2334 if (options.useXstack) {
2335 pic14_emitcode("mov","r0,%s",spname);
2336 for (i = pic14_nRegs ; i >= 0 ; i--) {
2337 if (bitVectBitValue(rsave,i)) {
2338 pic14_emitcode("dec","r0");
2339 pic14_emitcode("movx","a,@r0");
2341 pic14_emitcode("mov","b,a");
2343 pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2347 pic14_emitcode("mov","%s,r0",spname);
2348 if (bitVectBitValue(rsave,R0_IDX))
2349 pic14_emitcode("mov","r0,b");
2351 //for (i = pic14_nRegs ; i >= 0 ; i--) {
2352 // if (bitVectBitValue(rsave,i))
2353 // pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2359 /*-----------------------------------------------------------------*/
2361 /*-----------------------------------------------------------------*/
2362 static void pushSide(operand * oper, int size)
2366 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2368 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2369 if (AOP_TYPE(oper) != AOP_REG &&
2370 AOP_TYPE(oper) != AOP_DIR &&
2372 pic14_emitcode("mov","a,%s",l);
2373 pic14_emitcode("push","acc");
2375 pic14_emitcode("push","%s",l);
2380 /*-----------------------------------------------------------------*/
2381 /* assignResultValue - */
2382 /*-----------------------------------------------------------------*/
2383 static void assignResultValue(operand * oper)
2385 int size = AOP_SIZE(oper);
2390 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2392 DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2394 /* assign MSB first (passed via WREG) */
2396 get_returnvalue (oper, size, offset + GpsuedoStkPtr);
2402 /*-----------------------------------------------------------------*/
2403 /* genIpush - genrate code for pushing this gets a little complex */
2404 /*-----------------------------------------------------------------*/
2405 static void genIpush (iCode *ic)
2409 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2411 int size, offset = 0 ;
2415 /* if this is not a parm push : ie. it is spill push
2416 and spill push is always done on the local stack */
2417 if (!ic->parmPush) {
2419 /* and the item is spilt then do nothing */
2420 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2423 aopOp(IC_LEFT(ic),ic,FALSE);
2424 size = AOP_SIZE(IC_LEFT(ic));
2425 /* push it on the stack */
2427 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2432 pic14_emitcode("push","%s",l);
2437 /* this is a paramter push: in this case we call
2438 the routine to find the call and save those
2439 registers that need to be saved */
2442 /* then do the push */
2443 aopOp(IC_LEFT(ic),ic,FALSE);
2446 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2447 size = AOP_SIZE(IC_LEFT(ic));
2450 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2451 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
2452 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2454 pic14_emitcode("mov","a,%s",l);
2455 pic14_emitcode("push","acc");
2457 pic14_emitcode("push","%s",l);
2460 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2464 /*-----------------------------------------------------------------*/
2465 /* genIpop - recover the registers: can happen only for spilling */
2466 /*-----------------------------------------------------------------*/
2467 static void genIpop (iCode *ic)
2471 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2472 assert (!"genIpop -- unimplemented");
2477 /* if the temp was not pushed then */
2478 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2481 aopOp(IC_LEFT(ic),ic,FALSE);
2482 size = AOP_SIZE(IC_LEFT(ic));
2485 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2488 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2492 /*-----------------------------------------------------------------*/
2493 /* unsaverbank - restores the resgister bank from stack */
2494 /*-----------------------------------------------------------------*/
2495 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2499 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2505 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2507 if (options.useXstack) {
2509 r = getFreePtr(ic,&aop,FALSE);
2512 pic14_emitcode("mov","%s,_spx",r->name);
2513 pic14_emitcode("movx","a,@%s",r->name);
2514 pic14_emitcode("mov","psw,a");
2515 pic14_emitcode("dec","%s",r->name);
2518 pic14_emitcode ("pop","psw");
2521 for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2522 if (options.useXstack) {
2523 pic14_emitcode("movx","a,@%s",r->name);
2524 //pic14_emitcode("mov","(%s+%d),a",
2525 // regspic14[i].base,8*bank+regspic14[i].offset);
2526 pic14_emitcode("dec","%s",r->name);
2529 pic14_emitcode("pop",""); //"(%s+%d)",
2530 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2533 if (options.useXstack) {
2535 pic14_emitcode("mov","_spx,%s",r->name);
2536 freeAsmop(NULL,aop,ic,TRUE);
2542 /*-----------------------------------------------------------------*/
2543 /* saverbank - saves an entire register bank on the stack */
2544 /*-----------------------------------------------------------------*/
2545 static void saverbank (int bank, iCode *ic, bool pushPsw)
2549 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2555 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2556 if (options.useXstack) {
2559 r = getFreePtr(ic,&aop,FALSE);
2560 pic14_emitcode("mov","%s,_spx",r->name);
2564 for (i = 0 ; i < pic14_nRegs ;i++) {
2565 if (options.useXstack) {
2566 pic14_emitcode("inc","%s",r->name);
2567 //pic14_emitcode("mov","a,(%s+%d)",
2568 // regspic14[i].base,8*bank+regspic14[i].offset);
2569 pic14_emitcode("movx","@%s,a",r->name);
2571 pic14_emitcode("push","");// "(%s+%d)",
2572 //regspic14[i].base,8*bank+regspic14[i].offset);
2576 if (options.useXstack) {
2577 pic14_emitcode("mov","a,psw");
2578 pic14_emitcode("movx","@%s,a",r->name);
2579 pic14_emitcode("inc","%s",r->name);
2580 pic14_emitcode("mov","_spx,%s",r->name);
2581 freeAsmop (NULL,aop,ic,TRUE);
2584 pic14_emitcode("push","psw");
2586 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2592 /*-----------------------------------------------------------------*/
2593 /* genCall - generates a call statement */
2594 /*-----------------------------------------------------------------*/
2595 static void genCall (iCode *ic)
2604 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2606 /* if caller saves & we have not saved then */
2610 /* if we are calling a function that is not using
2611 the same register bank then we need to save the
2612 destination registers on the stack */
2613 dtype = operandType(IC_LEFT(ic));
2614 if (currFunc && dtype &&
2615 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2616 IFFUNC_ISISR(currFunc->type) &&
2619 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2621 /* if send set is not empty the assign */
2624 /* For the Pic port, there is no data stack.
2625 * So parameters passed to functions are stored
2626 * in registers. (The pCode optimizer will get
2627 * rid of most of these :).
2629 int psuedoStkPtr=-1;
2630 int firstTimeThruLoop = 1;
2632 _G.sendSet = reverseSet(_G.sendSet);
2634 /* First figure how many parameters are getting passed */
2635 for (sic = setFirstItem(_G.sendSet) ; sic ;
2636 sic = setNextItem(_G.sendSet)) {
2638 aopOp(IC_LEFT(sic),sic,FALSE);
2639 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2640 freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2643 for (sic = setFirstItem(_G.sendSet) ; sic ;
2644 sic = setNextItem(_G.sendSet)) {
2645 int size, offset = 0;
2647 aopOp(IC_LEFT(sic),sic,FALSE);
2648 size = AOP_SIZE(IC_LEFT(sic));
2651 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2652 AopType(AOP_TYPE(IC_LEFT(sic))));
2654 if(!firstTimeThruLoop) {
2655 /* If this is not the first time we've been through the loop
2656 * then we need to save the parameter in a temporary
2657 * register. The last byte of the last parameter is
2659 emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2662 firstTimeThruLoop=0;
2664 mov2w_op (IC_LEFT(sic), offset);
2667 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2672 sym = OP_SYMBOL(IC_LEFT(ic));
2673 name = sym->rname[0] ? sym->rname : sym->name;
2674 isExtern = IS_EXTERN(sym->etype);
2676 emitpcode(POC_PAGESEL,popGetWithString(name,1)); /* Extern functions maybe on another page - must call pagesel */
2678 emitpcode(POC_CALL,popGetWithString(name,isExtern));
2680 emitpcode(POC_PAGESEL,popGetWithString("$",0)); /* May have returned from another page - must call pagesel to restore PCLATH before next goto or call instruction */
2683 /* if we need assign a result value */
2684 if ((IS_ITEMP(IC_RESULT(ic)) &&
2685 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2686 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2687 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2690 aopOp(IC_RESULT(ic),ic,FALSE);
2693 assignResultValue(IC_RESULT(ic));
2695 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2696 AopType(AOP_TYPE(IC_RESULT(ic))));
2698 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2701 /* if register bank was saved then pop them */
2703 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2705 /* if we hade saved some registers then unsave them */
2706 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2707 unsaveRegisters (ic);
2712 /*-----------------------------------------------------------------*/
2713 /* genPcall - generates a call by pointer statement */
2714 /*-----------------------------------------------------------------*/
2715 static void genPcall (iCode *ic)
2718 symbol *albl = newiTempLabel(NULL);
2719 symbol *blbl = newiTempLabel(NULL);
2726 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2727 /* if caller saves & we have not saved then */
2731 /* if we are calling a function that is not using
2732 the same register bank then we need to save the
2733 destination registers on the stack */
2734 dtype = operandType(IC_LEFT(ic));
2735 if (currFunc && dtype &&
2736 IFFUNC_ISISR(currFunc->type) &&
2737 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2738 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2741 aopOp(left,ic,FALSE);
2742 DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2744 poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2746 pushSide(IC_LEFT(ic), FPTRSIZE);
2748 /* if send set is not empty, assign parameters */
2751 DEBUGpic14_emitcode ("; ***","%s %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2752 /* no way to pass args - W always gets used to make the call */
2754 /* first idea - factor out a common helper function and call it.
2755 But don't know how to get it generated only once in its own block
2757 if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2760 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2761 DEBUGpic14_emitcode ("; ***","%s %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2762 buffer = Safe_calloc(1,strlen(rname)+16);
2763 sprintf(buffer, "%s_goto_helper", rname);
2764 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2768 emitpcode(POC_CALL,popGetLabel(albl->key));
2769 pcop = popGetLabel(blbl->key);
2770 emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
2771 emitpcode(POC_GOTO,pcop);
2772 emitpLabel(albl->key);
2774 emitpcode(poc,popGetAddr(AOP(left),1,0));
2775 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2776 emitpcode(poc,popGetAddr(AOP(left),0,0));
2777 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2779 emitpLabel(blbl->key);
2781 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2783 /* if we need to assign a result value */
2784 if ((IS_ITEMP(IC_RESULT(ic)) &&
2785 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2786 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2787 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2790 aopOp(IC_RESULT(ic),ic,FALSE);
2795 assignResultValue(IC_RESULT(ic));
2797 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2800 /* if register bank was saved then unsave them */
2801 if (currFunc && dtype &&
2802 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2803 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2805 /* if we hade saved some registers then
2808 unsaveRegisters (ic);
2812 /*-----------------------------------------------------------------*/
2813 /* resultRemat - result is rematerializable */
2814 /*-----------------------------------------------------------------*/
2815 static int resultRemat (iCode *ic)
2817 // DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2820 if (SKIP_IC(ic) || ic->op == IFX)
2823 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2824 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2825 if (sym->remat && !POINTER_SET(ic))
2832 #if defined(__BORLANDC__) || defined(_MSC_VER)
2833 #define STRCASECMP stricmp
2835 #define STRCASECMP strcasecmp
2839 /*-----------------------------------------------------------------*/
2840 /* inExcludeList - return 1 if the string is in exclude Reg list */
2841 /*-----------------------------------------------------------------*/
2842 static bool inExcludeList(char *s)
2844 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2847 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2848 if (options.excludeRegs[i] &&
2849 STRCASECMP(options.excludeRegs[i],"none") == 0)
2852 for ( i = 0 ; options.excludeRegs[i]; i++) {
2853 if (options.excludeRegs[i] &&
2854 STRCASECMP(s,options.excludeRegs[i]) == 0)
2861 /*-----------------------------------------------------------------*/
2862 /* genFunction - generated code for function entry */
2863 /*-----------------------------------------------------------------*/
2864 static void genFunction (iCode *ic)
2871 DEBUGpic14_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2873 labelOffset += (max_key+4);
2877 /* create the function header */
2878 pic14_emitcode(";","-----------------------------------------");
2879 pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2880 pic14_emitcode(";","-----------------------------------------");
2882 pic14_emitcode("","%s:",sym->rname);
2883 addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2885 ftype = operandType(IC_LEFT(ic));
2887 /* if critical function then turn interrupts off */
2888 if (IFFUNC_ISCRITICAL(ftype))
2889 pic14_emitcode("clr","ea");
2891 /* here we need to generate the equates for the
2892 register bank if required */
2894 if (FUNC_REGBANK(ftype) != rbank) {
2897 rbank = FUNC_REGBANK(ftype);
2898 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2899 if (strcmp(regspic14[i].base,"0") == 0)
2900 pic14_emitcode("","%s = 0x%02x",
2902 8*rbank+regspic14[i].offset);
2904 pic14_emitcode ("","%s = %s + 0x%02x",
2907 8*rbank+regspic14[i].offset);
2912 /* if this is an interrupt service routine */
2913 if (IFFUNC_ISISR(sym->type)) {
2914 /* already done in pic14createInterruptVect() - delete me
2915 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2916 emitpcodeNULLop(POC_NOP);
2917 emitpcodeNULLop(POC_NOP);
2918 emitpcodeNULLop(POC_NOP);
2920 emitpcode(POC_MOVWF, popCopyReg(&pc_wsave));
2921 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2922 emitpcode(POC_CLRF, popCopyReg(&pc_status));
2923 emitpcode(POC_MOVWF, popCopyReg(&pc_ssave));
2924 emitpcode(POC_MOVFW, popCopyReg(&pc_pclath));
2925 emitpcode(POC_MOVWF, popCopyReg(&pc_psave));
2926 emitpcode(POC_CLRF, popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2928 pBlockConvert2ISR(pb);
2929 pic14_hasInterrupt = 1;
2931 if (!inExcludeList("acc"))
2932 pic14_emitcode ("push","acc");
2933 if (!inExcludeList("b"))
2934 pic14_emitcode ("push","b");
2935 if (!inExcludeList("dpl"))
2936 pic14_emitcode ("push","dpl");
2937 if (!inExcludeList("dph"))
2938 pic14_emitcode ("push","dph");
2939 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2941 pic14_emitcode ("push", "dpx");
2942 /* Make sure we're using standard DPTR */
2943 pic14_emitcode ("push", "dps");
2944 pic14_emitcode ("mov", "dps, #0x00");
2945 if (options.stack10bit)
2947 /* This ISR could conceivably use DPTR2. Better save it. */
2948 pic14_emitcode ("push", "dpl1");
2949 pic14_emitcode ("push", "dph1");
2950 pic14_emitcode ("push", "dpx1");
2953 /* if this isr has no bank i.e. is going to
2954 run with bank 0 , then we need to save more
2956 if (!FUNC_REGBANK(sym->type)) {
2958 /* if this function does not call any other
2959 function then we can be economical and
2960 save only those registers that are used */
2961 if (! IFFUNC_HASFCALL(sym->type)) {
2964 /* if any registers used */
2965 if (sym->regsUsed) {
2966 /* save the registers used */
2967 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2968 if (bitVectBitValue(sym->regsUsed,i) ||
2969 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2970 pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);
2975 /* this function has a function call cannot
2976 determines register usage so we will have the
2978 saverbank(0,ic,FALSE);
2983 /* if callee-save to be used for this function
2984 then save the registers being used in this function */
2985 if (IFFUNC_CALLEESAVES(sym->type)) {
2988 /* if any registers used */
2989 if (sym->regsUsed) {
2990 /* save the registers used */
2991 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2992 if (bitVectBitValue(sym->regsUsed,i) ||
2993 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2994 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
3002 /* set the register bank to the desired value */
3003 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
3004 pic14_emitcode("push","psw");
3005 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);
3008 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3010 if (options.useXstack) {
3011 pic14_emitcode("mov","r0,%s",spname);
3012 pic14_emitcode("mov","a,_bp");
3013 pic14_emitcode("movx","@r0,a");
3014 pic14_emitcode("inc","%s",spname);
3018 /* set up the stack */
3019 pic14_emitcode ("push","_bp"); /* save the callers stack */
3021 pic14_emitcode ("mov","_bp,%s",spname);
3024 /* adjust the stack for the function */
3029 werror(W_STACK_OVERFLOW,sym->name);
3031 if (i > 3 && sym->recvSize < 4) {
3033 pic14_emitcode ("mov","a,sp");
3034 pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3035 pic14_emitcode ("mov","sp,a");
3040 pic14_emitcode("inc","sp");
3045 pic14_emitcode ("mov","a,_spx");
3046 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3047 pic14_emitcode ("mov","_spx,a");
3052 /*-----------------------------------------------------------------*/
3053 /* genEndFunction - generates epilogue for functions */
3054 /*-----------------------------------------------------------------*/
3055 static void genEndFunction (iCode *ic)
3057 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3061 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3063 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3065 pic14_emitcode ("mov","%s,_bp",spname);
3068 /* if use external stack but some variables were
3069 added to the local stack then decrement the
3071 if (options.useXstack && sym->stack) {
3072 pic14_emitcode("mov","a,sp");
3073 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3074 pic14_emitcode("mov","sp,a");
3078 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3079 if (options.useXstack) {
3080 pic14_emitcode("mov","r0,%s",spname);
3081 pic14_emitcode("movx","a,@r0");
3082 pic14_emitcode("mov","_bp,a");
3083 pic14_emitcode("dec","%s",spname);
3087 pic14_emitcode ("pop","_bp");
3091 /* restore the register bank */
3092 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3093 pic14_emitcode ("pop","psw");
3095 if (IFFUNC_ISISR(sym->type)) {
3097 /* now we need to restore the registers */
3098 /* if this isr has no bank i.e. is going to
3099 run with bank 0 , then we need to save more
3101 if (!FUNC_REGBANK(sym->type)) {
3103 /* if this function does not call any other
3104 function then we can be economical and
3105 save only those registers that are used */
3106 if (! IFFUNC_HASFCALL(sym->type)) {
3109 /* if any registers used */
3110 if (sym->regsUsed) {
3111 /* save the registers used */
3112 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3113 if (bitVectBitValue(sym->regsUsed,i) ||
3114 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3115 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3120 /* this function has a function call cannot
3121 determines register usage so we will have the
3123 unsaverbank(0,ic,FALSE);
3127 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3129 if (options.stack10bit)
3131 pic14_emitcode ("pop", "dpx1");
3132 pic14_emitcode ("pop", "dph1");
3133 pic14_emitcode ("pop", "dpl1");
3135 pic14_emitcode ("pop", "dps");
3136 pic14_emitcode ("pop", "dpx");
3138 if (!inExcludeList("dph"))
3139 pic14_emitcode ("pop","dph");
3140 if (!inExcludeList("dpl"))
3141 pic14_emitcode ("pop","dpl");
3142 if (!inExcludeList("b"))
3143 pic14_emitcode ("pop","b");
3144 if (!inExcludeList("acc"))
3145 pic14_emitcode ("pop","acc");
3147 if (IFFUNC_ISCRITICAL(sym->type))
3148 pic14_emitcode("setb","ea");
3151 /* if debug then send end of function */
3152 /* if (options.debug && currFunc) { */
3154 debugFile->writeEndFunction (currFunc, ic, 1);
3157 pic14_emitcode ("reti","");
3158 emitpcode(POC_MOVFW, popCopyReg(&pc_psave));
3159 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
3160 emitpcode(POC_CLRF, popCopyReg(&pc_status));
3161 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3162 emitpcode(POC_MOVWF, popCopyReg(&pc_status));
3163 emitpcode(POC_SWAPF, popCopyReg(&pc_wsave));
3164 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3165 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3166 emitpcodeNULLop(POC_RETFIE);
3169 if (IFFUNC_ISCRITICAL(sym->type))
3170 pic14_emitcode("setb","ea");
3172 if (IFFUNC_CALLEESAVES(sym->type)) {
3175 /* if any registers used */
3176 if (sym->regsUsed) {
3177 /* save the registers used */
3178 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3179 if (bitVectBitValue(sym->regsUsed,i) ||
3180 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3181 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3187 /* if debug then send end of function */
3189 debugFile->writeEndFunction (currFunc, ic, 1);
3192 pic14_emitcode ("return","");
3193 emitpcodeNULLop(POC_RETURN);
3195 /* Mark the end of a function */
3196 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3201 /*-----------------------------------------------------------------*/
3202 /* genRet - generate code for return statement */
3203 /*-----------------------------------------------------------------*/
3204 static void genRet (iCode *ic)
3206 int size,offset = 0;
3210 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3211 /* if we have no return value then
3212 just generate the "ret" */
3216 /* we have something to return then
3217 move the return value into place */
3218 aopOp(IC_LEFT(ic),ic,FALSE);
3219 size = AOP_SIZE(IC_LEFT(ic));
3221 for (offset = 0; offset < size; offset++)
3223 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
3226 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3229 /* generate a jump to the return label
3230 if the next is not the return statement */
3231 if (!(ic->next && ic->next->op == LABEL &&
3232 IC_LABEL(ic->next) == returnLabel)) {
3234 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3239 /*-----------------------------------------------------------------*/
3240 /* genLabel - generates a label */
3241 /*-----------------------------------------------------------------*/
3242 static void genLabel (iCode *ic)
3246 /* special case never generate */
3247 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3248 if (IC_LABEL(ic) == entryLabel)
3251 emitpLabel(IC_LABEL(ic)->key);
3252 pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3255 /*-----------------------------------------------------------------*/
3256 /* genGoto - generates a goto */
3257 /*-----------------------------------------------------------------*/
3259 static void genGoto (iCode *ic)
3263 emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3264 pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3268 /*-----------------------------------------------------------------*/
3269 /* genMultbits :- multiplication of bits */
3270 /*-----------------------------------------------------------------*/
3271 static void genMultbits (operand *left,
3276 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3278 if(!pic14_sameRegs(AOP(result),AOP(right)))
3279 emitpcode(POC_BSF, popGet(AOP(result),0));
3281 emitpcode(POC_BTFSC,popGet(AOP(right),0));
3282 emitpcode(POC_BTFSS,popGet(AOP(left),0));
3283 emitpcode(POC_BCF, popGet(AOP(result),0));
3288 /*-----------------------------------------------------------------*/
3289 /* genMultOneByte : 8 bit multiplication & division */
3290 /*-----------------------------------------------------------------*/
3291 static void genMultOneByte (operand *left,
3295 char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
3303 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3304 DEBUGpic14_AopType(__LINE__,left,right,result);
3305 DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3307 /* (if two literals, the value is computed before) */
3308 /* if one literal, literal on the right */
3309 if (AOP_TYPE(left) == AOP_LIT){
3315 assert (AOP_SIZE(left) == AOP_SIZE(right));
3317 size = min(AOP_SIZE(result),AOP_SIZE(left));
3318 offset = Gstack_base_addr - (2*size - 1);
3320 /* pass right operand as argument */
3321 for (i=0; i < size; i++)
3323 mov2w (AOP(right), i);
3324 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3327 /* pass left operand as argument */
3328 for (i=0; i < size; i++)
3330 mov2w (AOP(left), i);
3331 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3333 assert (offset == Gstack_base_addr);
3335 /* call library routine */
3336 assert (size > 0 && size <= 4);
3337 call_libraryfunc (func[size]);
3340 movwf (AOP(result), size-1);
3341 for (i=0; i < size - 1; i++)
3343 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
3344 movwf (AOP(result), size - 2 - i);
3347 /* now (zero-/sign) extend the result to its size */
3348 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
3351 /*-----------------------------------------------------------------*/
3352 /* genMult - generates code for multiplication */
3353 /*-----------------------------------------------------------------*/
3354 static void genMult (iCode *ic)
3356 operand *left = IC_LEFT(ic);
3357 operand *right = IC_RIGHT(ic);
3358 operand *result= IC_RESULT(ic);
3362 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3363 /* assign the amsops */
3364 aopOp (left,ic,FALSE);
3365 aopOp (right,ic,FALSE);
3366 aopOp (result,ic,TRUE);
3368 DEBUGpic14_AopType(__LINE__,left,right,result);
3370 /* special cases first */
3372 if (AOP_TYPE(left) == AOP_CRY &&
3373 AOP_TYPE(right)== AOP_CRY) {
3374 genMultbits(left,right,result);
3378 /* if both are of size == 1 */
3379 if (AOP_SIZE(left) == 1 &&
3380 AOP_SIZE(right) == 1 ) {
3381 genMultOneByte(left,right,result);
3385 /* should have been converted to function call */
3389 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3390 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3391 freeAsmop(result,NULL,ic,TRUE);
3394 /*-----------------------------------------------------------------*/
3395 /* genDivbits :- division of bits */
3396 /*-----------------------------------------------------------------*/
3397 static void genDivbits (operand *left,
3406 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3407 /* the result must be bit */
3408 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3409 l = aopGet(AOP(left),0,FALSE,FALSE);
3413 pic14_emitcode("div","ab");
3414 pic14_emitcode("rrc","a");
3415 aopPut(AOP(result),"c",0);
3418 /*-----------------------------------------------------------------*/
3419 /* genDivOneByte : 8 bit division */
3420 /*-----------------------------------------------------------------*/
3421 static void genDivOneByte (operand *left,
3428 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3430 assert (AOP_SIZE(result) == 1);
3431 assert (AOP_SIZE(right) == 1);
3432 assert (AOP_SIZE(left) == 1);
3434 size = min(AOP_SIZE(result),AOP_SIZE(left));
3436 if (AOP_TYPE(right) == AOP_LIT)
3438 /* XXX: might add specialized code */
3441 if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3443 /* unsigned division */
3445 mov2w(AOP(right),0);
3446 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3448 call_libraryfunc("__divuchar");
3449 movwf(AOP(result),0);
3454 temp = popGetTempReg();
3455 lbl = newiTempLabel(NULL);
3457 /* XXX: improve this naive approach:
3458 [result] = [a] / [b]
3459 ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
3463 movwf temp // temp <-- left
3464 movf right,W // W <-- right
3468 subwf temp,F // temp <-- temp - W
3469 skipNC // subwf clears CARRY (i.e. sets BORROW) if temp < W
3471 decf result // we just subtract once too often
3474 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3475 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
3478 emitpcode(POC_MOVWF, temp);
3479 mov2w(AOP(right),0);
3480 emitpcode(POC_CLRF, popGet(AOP(result),0));
3482 emitpLabel(lbl->key);
3483 emitpcode(POC_INCF, popGet(AOP(result),0));
3484 emitpcode(POC_SUBWF, temp);
3486 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3487 emitpcode(POC_DECF, popGet(AOP(result),0));
3492 /* signed division */
3493 mov2w(AOP(right),0);
3494 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3496 call_libraryfunc("__divschar");
3497 movwf(AOP(result),0);
3500 /* now performed the signed/unsigned division -- extend result */
3501 addSign(result, 1, !SPEC_USIGN(operandType(result)));
3504 /*-----------------------------------------------------------------*/
3505 /* genDiv - generates code for division */
3506 /*-----------------------------------------------------------------*/
3507 static void genDiv (iCode *ic)
3509 operand *left = IC_LEFT(ic);
3510 operand *right = IC_RIGHT(ic);
3511 operand *result= IC_RESULT(ic);
3514 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3515 /* assign the amsops */
3516 aopOp (left,ic,FALSE);
3517 aopOp (right,ic,FALSE);
3518 aopOp (result,ic,TRUE);
3520 /* special cases first */
3522 if (AOP_TYPE(left) == AOP_CRY &&
3523 AOP_TYPE(right)== AOP_CRY) {
3524 genDivbits(left,right,result);
3528 /* if both are of size == 1 */
3529 if (AOP_SIZE(left) == 1 &&
3530 AOP_SIZE(right) == 1 ) {
3531 genDivOneByte(left,right,result);
3535 /* should have been converted to function call */
3538 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3539 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3540 freeAsmop(result,NULL,ic,TRUE);
3543 /*-----------------------------------------------------------------*/
3544 /* genModbits :- modulus of bits */
3545 /*-----------------------------------------------------------------*/
3546 static void genModbits (operand *left,
3554 /* the result must be bit */
3555 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3556 l = aopGet(AOP(left),0,FALSE,FALSE);
3560 pic14_emitcode("div","ab");
3561 pic14_emitcode("mov","a,b");
3562 pic14_emitcode("rrc","a");
3563 aopPut(AOP(result),"c",0);
3566 /*-----------------------------------------------------------------*/
3567 /* genModOneByte : 8 bit modulus */
3568 /*-----------------------------------------------------------------*/
3569 static void genModOneByte (operand *left,
3576 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3578 assert (AOP_SIZE(result) == 1);
3579 assert (AOP_SIZE(right) == 1);
3580 assert (AOP_SIZE(left) == 1);
3582 size = min(AOP_SIZE(result),AOP_SIZE(left));
3584 if (AOP_TYPE(right) == AOP_LIT)
3586 /* XXX: might add specialized code */
3589 if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3591 /* unsigned division */
3593 mov2w(AOP(right),0);
3594 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3596 call_libraryfunc("__moduchar");
3597 movwf(AOP(result),0);
3602 lbl = newiTempLabel(NULL);
3604 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3606 /* XXX: improve this naive approach:
3607 [result] = [a] % [b]
3608 ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3612 movwf result // result <-- left
3613 movf right,W // W <-- right
3615 subwf result,F // result <-- result - W
3616 skipNC // subwf clears CARRY (i.e. sets BORROW) if result < W
3618 addwf result, F // we just subtract once too often
3621 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3622 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3624 if (!pic14_sameRegs(AOP(left), AOP(result)))
3627 emitpcode(POC_MOVWF, popGet(AOP(result),0));
3629 mov2w(AOP(right),0);
3631 emitpLabel(lbl->key);
3632 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3634 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3635 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3640 /* signed division */
3641 mov2w(AOP(right),0);
3642 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3644 call_libraryfunc("__modschar");
3645 movwf(AOP(result),0);
3648 /* now we performed the signed/unsigned modulus -- extend result */
3649 addSign(result, 1, !SPEC_USIGN(operandType(result)));
3652 /*-----------------------------------------------------------------*/
3653 /* genMod - generates code for division */
3654 /*-----------------------------------------------------------------*/
3655 static void genMod (iCode *ic)
3657 operand *left = IC_LEFT(ic);
3658 operand *right = IC_RIGHT(ic);
3659 operand *result= IC_RESULT(ic);
3662 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3663 /* assign the amsops */
3664 aopOp (left,ic,FALSE);
3665 aopOp (right,ic,FALSE);
3666 aopOp (result,ic,TRUE);
3668 /* special cases first */
3670 if (AOP_TYPE(left) == AOP_CRY &&
3671 AOP_TYPE(right)== AOP_CRY) {
3672 genModbits(left,right,result);
3676 /* if both are of size == 1 */
3677 if (AOP_SIZE(left) == 1 &&
3678 AOP_SIZE(right) == 1 ) {
3679 genModOneByte(left,right,result);
3683 /* should have been converted to function call */
3687 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3688 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3689 freeAsmop(result,NULL,ic,TRUE);
3692 /*-----------------------------------------------------------------*/
3693 /* genIfxJump :- will create a jump depending on the ifx */
3694 /*-----------------------------------------------------------------*/
3696 note: May need to add parameter to indicate when a variable is in bit space.
3698 static void genIfxJump (iCode *ic, char *jval)
3702 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3703 /* if true label then we jump if condition
3705 if ( IC_TRUE(ic) ) {
3707 if(strcmp(jval,"a") == 0)
3709 else if (strcmp(jval,"c") == 0)
3712 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3713 emitpcode(POC_BTFSC, newpCodeOpBit(jval,-1,1));
3716 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3717 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3721 /* false label is present */
3722 if(strcmp(jval,"a") == 0)
3724 else if (strcmp(jval,"c") == 0)
3727 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3728 emitpcode(POC_BTFSS, newpCodeOpBit(jval,-1,1));
3731 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3732 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3737 /* mark the icode as generated */
3742 /*-----------------------------------------------------------------*/
3744 /*-----------------------------------------------------------------*/
3745 static void genSkip(iCode *ifx,int status_bit)
3751 if ( IC_TRUE(ifx) ) {
3752 switch(status_bit) {
3767 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3768 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3772 switch(status_bit) {
3786 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3787 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3794 /*-----------------------------------------------------------------*/
3796 /*-----------------------------------------------------------------*/
3797 static void genSkipc(resolvedIfx *rifx)
3808 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3809 emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3810 rifx->generated = 1;
3814 /*-----------------------------------------------------------------*/
3816 /*-----------------------------------------------------------------*/
3817 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3823 if( (rifx->condition ^ invert_condition) & 1)
3828 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3829 rifx->generated = 1;
3834 /*-----------------------------------------------------------------*/
3836 /*-----------------------------------------------------------------*/
3837 static void genSkipz(iCode *ifx, int condition)
3840 assert (ifx != NULL);
3848 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3850 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3853 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3855 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3861 /*-----------------------------------------------------------------*/
3863 /*-----------------------------------------------------------------*/
3864 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3871 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3873 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3876 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3877 rifx->generated = 1;
3882 /*-----------------------------------------------------------------*/
3883 /* genChkZeroes :- greater or less than comparison */
3884 /* For each byte in a literal that is zero, inclusive or the */
3885 /* the corresponding byte in the operand with W */
3886 /* returns true if any of the bytes are zero */
3887 /*-----------------------------------------------------------------*/
3888 static int genChkZeroes(operand *op, int lit, int size)
3895 i = (lit >> (size*8)) & 0xff;
3899 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3901 emitpcode(POC_IORFW, popGet(AOP(op),size));
3911 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3912 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
3913 #define DEBUGpc emitpComment
3915 /*-----------------------------------------------------------------*/
3916 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
3917 /* aop (if it's NOT a literal) or from lit (if */
3918 /* aop is a literal) */
3919 /*-----------------------------------------------------------------*/
3920 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3921 if (aop->type == AOP_LIT) {
3922 emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3924 emitpcode (POC_MOVFW, popGet (aop, offset));
3928 /* genCmp performs a left < right comparison, stores
3929 * the outcome in result (if != NULL) and generates
3930 * control flow code for the ifx (if != NULL).
3932 * This version leaves in sequences like
3933 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3934 * which should be optmized by the peephole
3935 * optimizer - RN 2005-01-01 */
3936 static void genCmp (operand *left,operand *right,
3937 operand *result, iCode *ifx, int sign)
3947 int invert_result = 0;
3951 assert (AOP_SIZE(left) == AOP_SIZE(right));
3952 assert (left && right);
3954 size = AOP_SIZE(right) - 1;
3955 mask = (0x100UL << (size*8)) - 1;
3956 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3961 resolveIfx (&rIfx, ifx);
3963 /**********************************************************************
3964 * handle bits - bit compares are promoted to int compares seemingly! *
3965 **********************************************************************/
3967 // THIS IS COMPLETELY UNTESTED!
3968 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3969 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3970 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3971 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3974 // 1 < {0,1} is false --> clear C by skipping the next instruction
3975 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3976 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3977 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3978 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3979 emitCLRC; // only skipped for left=0 && right=1
3981 goto correct_result_in_carry;
3985 /*************************************************
3986 * make sure that left is register (or the like) *
3987 *************************************************/
3988 if (!isAOP_REGlike(left)) {
3989 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
3990 assert (isAOP_LIT(left));
3991 assert (isAOP_REGlike(right));
3992 // swap left and right
3993 // left < right <==> right > left <==> (right >= left + 1)
3994 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3996 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
3997 // MAXVALUE < right? always false
3998 if (performedLt) emitCLRC; else emitSETC;
3999 goto correct_result_in_carry;
4002 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4003 // that's why we handled it above.
4010 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4011 } else if (isAOP_LIT(right)) {
4012 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4015 assert (isAOP_REGlike(left)); // left must be register or the like
4016 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4018 /*************************************************
4019 * special cases go here *
4020 *************************************************/
4022 if (isAOP_LIT(right)) {
4024 // unsigned comparison to a literal
4025 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4027 // unsigned left < 0? always false
4028 if (performedLt) emitCLRC; else emitSETC;
4029 goto correct_result_in_carry;
4032 // signed comparison to a literal
4033 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4034 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4035 // signed left < 0x80000000? always false
4036 if (performedLt) emitCLRC; else emitSETC;
4037 goto correct_result_in_carry;
4038 } else if (lit == 0) {
4039 // compare left < 0; set CARRY if SIGNBIT(left) is set
4040 if (performedLt) emitSETC; else emitCLRC;
4041 emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
4042 if (performedLt) emitCLRC; else emitSETC;
4043 goto correct_result_in_carry;
4046 } // right is literal
4048 /*************************************************
4049 * perform a general case comparison *
4050 * make sure we get CARRY==1 <==> left >= right *
4051 *************************************************/
4052 // compare most significant bytes
4053 //DEBUGpc ("comparing bytes at offset %d", size);
4055 // unsigned comparison
4056 pic14_mov2w_regOrLit (AOP(right), lit, size);
4057 emitpcode (POC_SUBFW, popGet (AOP(left), size));
4059 // signed comparison
4060 // (add 2^n to both operands then perform an unsigned comparison)
4061 if (isAOP_LIT(right)) {
4062 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4063 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4065 if (litbyte == 0x80) {
4066 // left >= 0x80 -- always true, but more bytes to come
4067 mov2w (AOP(left), size);
4068 emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
4071 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4072 mov2w (AOP(left), size);
4073 emitpcode (POC_ADDLW, popGetLit (0x80));
4074 emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4077 pCodeOp *pctemp = popGetTempReg();
4078 mov2w (AOP(left), size);
4079 emitpcode (POC_ADDLW, popGetLit (0x80));
4080 emitpcode (POC_MOVWF, pctemp);
4081 mov2w (AOP(right), size);
4082 emitpcode (POC_ADDLW, popGetLit (0x80));
4083 emitpcode (POC_SUBFW, pctemp);
4084 popReleaseTempReg(pctemp);
4088 // compare remaining bytes (treat as unsigned case from above)
4089 templbl = newiTempLabel ( NULL );
4092 //DEBUGpc ("comparing bytes at offset %d", offs);
4094 emitpcode (POC_GOTO, popGetLabel (templbl->key));
4095 pic14_mov2w_regOrLit (AOP(right), lit, offs);
4096 emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4098 emitpLabel (templbl->key);
4099 goto result_in_carry;
4103 /****************************************************
4104 * now CARRY contains the result of the comparison: *
4105 * SUBWF sets CARRY iff *
4106 * F-W >= 0 <==> F >= W <==> !(F < W) *
4107 * (F=left, W=right) *
4108 ****************************************************/
4112 // value will be used in the following genSkipc()
4113 rIfx.condition ^= 1;
4116 correct_result_in_carry:
4118 // assign result to variable (if neccessary)
4119 if (result && AOP_TYPE(result) != AOP_CRY) {
4120 //DEBUGpc ("assign result");
4121 size = AOP_SIZE(result);
4123 emitpcode (POC_CLRF, popGet (AOP(result), size));
4125 if (invert_result) {
4127 emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4129 emitpcode (POC_RLF, popGet (AOP(result), 0));
4133 // perform conditional jump
4135 //DEBUGpc ("generate control flow");
4143 /* OLD VERSION -- BUGGY, DO NOT USE */
4145 /*-----------------------------------------------------------------*/
4146 /* genCmp :- greater or less than comparison */
4147 /*-----------------------------------------------------------------*/
4148 static void genCmp (operand *left,operand *right,
4149 operand *result, iCode *ifx, int sign)
4151 int size; //, offset = 0 ;
4152 unsigned long lit = 0L,i = 0;
4153 resolvedIfx rFalseIfx;
4154 // resolvedIfx rTrueIfx;
4158 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4161 DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4162 DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4166 resolveIfx(&rFalseIfx,ifx);
4167 truelbl = newiTempLabel(NULL);
4168 size = max(AOP_SIZE(left),AOP_SIZE(right));
4170 DEBUGpic14_AopType(__LINE__,left,right,result);
4174 /* if literal is on the right then swap with left */
4175 if ((AOP_TYPE(right) == AOP_LIT)) {
4176 operand *tmp = right ;
4177 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4178 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4181 lit = (lit - 1) & mask;
4184 rFalseIfx.condition ^= 1;
4187 } else if ((AOP_TYPE(left) == AOP_LIT)) {
4188 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4192 //if(IC_TRUE(ifx) == NULL)
4193 /* if left & right are bit variables */
4194 if (AOP_TYPE(left) == AOP_CRY &&
4195 AOP_TYPE(right) == AOP_CRY ) {
4196 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4197 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4199 /* subtract right from left if at the
4200 end the carry flag is set then we know that
4201 left is greater than right */
4203 symbol *lbl = newiTempLabel(NULL);
4206 if(AOP_TYPE(right) == AOP_LIT) {
4208 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4210 DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4217 genSkipCond(&rFalseIfx,left,size-1,7);
4219 /* no need to compare to 0...*/
4220 /* NOTE: this is a de-generate compare that most certainly
4221 * creates some dead code. */
4222 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4224 if(ifx) ifx->generated = 1;
4231 //i = (lit >> (size*8)) & 0xff;
4232 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4234 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4236 i = ((0-lit) & 0xff);
4239 /* lit is 0x7f, all signed chars are less than
4240 * this except for 0x7f itself */
4241 emitpcode(POC_XORLW, popGetLit(0x7f));
4242 genSkipz2(&rFalseIfx,0);
4244 emitpcode(POC_ADDLW, popGetLit(0x80));
4245 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4246 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4251 genSkipz2(&rFalseIfx,1);
4253 emitpcode(POC_ADDLW, popGetLit(i));
4254 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4258 if(ifx) ifx->generated = 1;
4262 /* chars are out of the way. now do ints and longs */
4265 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4272 genSkipCond(&rFalseIfx,left,size,7);
4273 if(ifx) ifx->generated = 1;
4278 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4280 //rFalseIfx.condition ^= 1;
4281 //genSkipCond(&rFalseIfx,left,size,7);
4282 //rFalseIfx.condition ^= 1;
4284 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4285 if(rFalseIfx.condition)
4286 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4288 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4290 emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4291 emitpcode(POC_ADDFW, popGet(AOP(left),0));
4292 emitpcode(POC_MOVFW, popGet(AOP(left),1));
4295 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4297 if(rFalseIfx.condition) {
4299 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4305 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4306 emitpLabel(truelbl->key);
4307 if(ifx) ifx->generated = 1;
4314 if( (lit & 0xff) == 0) {
4315 /* lower byte is zero */
4316 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4317 i = ((lit >> 8) & 0xff) ^0x80;
4318 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4319 emitpcode(POC_ADDLW, popGetLit( 0x80));
4320 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4321 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4324 if(ifx) ifx->generated = 1;
4329 /* Special cases for signed longs */
4330 if( (lit & 0xffffff) == 0) {
4331 /* lower byte is zero */
4332 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4333 i = ((lit >> 8*3) & 0xff) ^0x80;
4334 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4335 emitpcode(POC_ADDLW, popGetLit( 0x80));
4336 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4337 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4340 if(ifx) ifx->generated = 1;
4348 if(lit & (0x80 << (size*8))) {
4349 /* lit is negative */
4350 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4352 //genSkipCond(&rFalseIfx,left,size,7);
4354 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4356 if(rFalseIfx.condition)
4357 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4359 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4363 /* lit is positive */
4364 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4365 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4366 if(rFalseIfx.condition)
4367 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4369 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4373 /* There are no more special cases, so perform a general compare */
4375 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4376 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4380 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4382 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4384 //rFalseIfx.condition ^= 1;
4385 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4387 emitpLabel(truelbl->key);
4389 if(ifx) ifx->generated = 1;
4396 /* sign is out of the way. So now do an unsigned compare */
4397 DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4400 /* General case - compare to an unsigned literal on the right.*/
4402 i = (lit >> (size*8)) & 0xff;
4403 emitpcode(POC_MOVLW, popGetLit(i));
4404 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4406 i = (lit >> (size*8)) & 0xff;
4409 emitpcode(POC_MOVLW, popGetLit(i));
4411 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4413 /* this byte of the lit is zero,
4414 *if it's not the last then OR in the variable */
4416 emitpcode(POC_IORFW, popGet(AOP(left),size));
4421 emitpLabel(lbl->key);
4422 //if(emitFinalCheck)
4423 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4425 emitpLabel(truelbl->key);
4427 if(ifx) ifx->generated = 1;
4434 if(AOP_TYPE(left) == AOP_LIT) {
4435 //symbol *lbl = newiTempLabel(NULL);
4437 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4440 DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4443 if((lit == 0) && (sign == 0)){
4446 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4448 emitpcode(POC_IORFW, popGet(AOP(right),--size));
4450 genSkipz2(&rFalseIfx,0);
4451 if(ifx) ifx->generated = 1;
4458 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4459 /* degenerate compare can never be true */
4460 if(rFalseIfx.condition == 0)
4461 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4463 if(ifx) ifx->generated = 1;
4468 /* signed comparisons to a literal byte */
4470 int lp1 = (lit+1) & 0xff;
4472 DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4475 rFalseIfx.condition ^= 1;
4476 genSkipCond(&rFalseIfx,right,0,7);
4479 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4480 emitpcode(POC_XORLW, popGetLit(0x7f));
4481 genSkipz2(&rFalseIfx,1);
4484 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4485 emitpcode(POC_ADDLW, popGetLit(0x80));
4486 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4487 rFalseIfx.condition ^= 1;
4488 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4491 if(ifx) ifx->generated = 1;
4493 /* unsigned comparisons to a literal byte */
4495 switch(lit & 0xff ) {
4497 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4498 genSkipz2(&rFalseIfx,0);
4499 if(ifx) ifx->generated = 1;
4502 genSkipCond(&rFalseIfx,right,0,7);
4503 if(ifx) ifx->generated = 1;
4507 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4508 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4509 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4510 rFalseIfx.condition ^= 1;
4511 if (AOP_TYPE(result) == AOP_CRY) {
4512 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4513 if(ifx) ifx->generated = 1;
4515 DEBUGpic14_emitcode ("; ***","%s %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4516 emitpcode(POC_CLRF, popGet(AOP(result),0));
4517 emitpcode(POC_RLF, popGet(AOP(result),0));
4518 emitpcode(POC_MOVLW, popGetLit(0x01));
4519 emitpcode(POC_XORWF, popGet(AOP(result),0));
4530 /* Size is greater than 1 */
4538 /* this means lit = 0xffffffff, or -1 */
4541 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4542 rFalseIfx.condition ^= 1;
4543 genSkipCond(&rFalseIfx,right,size,7);
4544 if(ifx) ifx->generated = 1;
4551 if(rFalseIfx.condition) {
4552 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4553 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4556 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4558 emitpcode(POC_IORFW, popGet(AOP(right),size));
4562 if(rFalseIfx.condition) {
4563 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4564 emitpLabel(truelbl->key);
4566 rFalseIfx.condition ^= 1;
4567 genSkipCond(&rFalseIfx,right,s,7);
4570 if(ifx) ifx->generated = 1;
4574 if((size == 1) && (0 == (lp1&0xff))) {
4575 /* lower byte of signed word is zero */
4576 DEBUGpic14_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
4577 i = ((lp1 >> 8) & 0xff) ^0x80;
4578 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4579 emitpcode(POC_ADDLW, popGetLit( 0x80));
4580 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4581 rFalseIfx.condition ^= 1;
4582 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4585 if(ifx) ifx->generated = 1;
4589 if(lit & (0x80 << (size*8))) {
4590 /* Lit is less than zero */
4591 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
4592 //rFalseIfx.condition ^= 1;
4593 //genSkipCond(&rFalseIfx,left,size,7);
4594 //rFalseIfx.condition ^= 1;
4595 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4596 //emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4598 if(rFalseIfx.condition)
4599 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4601 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4605 /* Lit is greater than or equal to zero */
4606 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
4607 //rFalseIfx.condition ^= 1;
4608 //genSkipCond(&rFalseIfx,right,size,7);
4609 //rFalseIfx.condition ^= 1;
4611 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4612 //emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4614 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4615 if(rFalseIfx.condition)
4616 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4618 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4623 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4624 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4628 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4630 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4632 rFalseIfx.condition ^= 1;
4633 //rFalseIfx.condition = 1;
4634 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4636 emitpLabel(truelbl->key);
4638 if(ifx) ifx->generated = 1;
4643 /* compare word or long to an unsigned literal on the right.*/
4648 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4651 break; /* handled above */
4654 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4656 emitpcode(POC_IORFW, popGet(AOP(right),size));
4657 genSkipz2(&rFalseIfx,0);
4661 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4663 emitpcode(POC_IORFW, popGet(AOP(right),size));
4666 if(rFalseIfx.condition)
4667 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4669 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4672 emitpcode(POC_MOVLW, popGetLit(lit+1));
4673 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4675 rFalseIfx.condition ^= 1;
4676 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4679 emitpLabel(truelbl->key);
4681 if(ifx) ifx->generated = 1;
4687 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4688 i = (lit >> (size*8)) & 0xff;
4690 emitpcode(POC_MOVLW, popGetLit(i));
4691 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4694 i = (lit >> (size*8)) & 0xff;
4697 emitpcode(POC_MOVLW, popGetLit(i));
4699 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4701 /* this byte of the lit is zero,
4702 *if it's not the last then OR in the variable */
4704 emitpcode(POC_IORFW, popGet(AOP(right),size));
4709 emitpLabel(lbl->key);
4711 rFalseIfx.condition ^= 1;
4712 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4716 emitpLabel(truelbl->key);
4717 if(ifx) ifx->generated = 1;
4721 /* Compare two variables */
4723 DEBUGpic14_emitcode(";sign","%d",sign);
4727 /* Sigh. thus sucks... */
4729 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4730 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4731 emitpcode(POC_MOVLW, popGetLit(0x80));
4732 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4733 emitpcode(POC_XORFW, popGet(AOP(right),size));
4734 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4736 /* Signed char comparison */
4737 /* Special thanks to Nikolai Golovchenko for this snippet */
4738 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4739 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4740 emitpcode(POC_RRFW, popGet(AOP(left),0)); /* could be any register */
4741 emitpcode(POC_XORFW, popGet(AOP(left),0));
4742 emitpcode(POC_XORFW, popGet(AOP(right),0));
4743 emitpcode(POC_ADDLW, popGetLit(0x80));
4745 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4746 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4748 if(ifx) ifx->generated = 1;
4754 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4755 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4759 /* The rest of the bytes of a multi-byte compare */
4763 emitpcode(POC_GOTO, popGetLabel(lbl->key));
4766 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4767 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4772 emitpLabel(lbl->key);
4774 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4775 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
4776 (AOP_TYPE(result) == AOP_REG)) {
4777 emitpcode(POC_CLRF, popGet(AOP(result),0));
4778 emitpcode(POC_RLF, popGet(AOP(result),0));
4780 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4782 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4783 if(ifx) ifx->generated = 1;
4790 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4791 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4792 pic14_outBitC(result);
4794 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4795 /* if the result is used in the next
4796 ifx conditional branch then generate
4797 code a little differently */
4799 genIfxJump (ifx,"c");
4801 pic14_outBitC(result);
4802 /* leave the result in acc */
4808 /*-----------------------------------------------------------------*/
4809 /* genCmpGt :- greater than comparison */
4810 /*-----------------------------------------------------------------*/
4811 static void genCmpGt (iCode *ic, iCode *ifx)
4813 operand *left, *right, *result;
4814 sym_link *letype , *retype;
4818 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4820 right= IC_RIGHT(ic);
4821 result = IC_RESULT(ic);
4823 letype = getSpec(operandType(left));
4824 retype =getSpec(operandType(right));
4825 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4826 /* assign the amsops */
4827 aopOp (left,ic,FALSE);
4828 aopOp (right,ic,FALSE);
4829 aopOp (result,ic,TRUE);
4831 genCmp(right, left, result, ifx, sign);
4833 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4834 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4835 freeAsmop(result,NULL,ic,TRUE);
4838 /*-----------------------------------------------------------------*/
4839 /* genCmpLt - less than comparisons */
4840 /*-----------------------------------------------------------------*/
4841 static void genCmpLt (iCode *ic, iCode *ifx)
4843 operand *left, *right, *result;
4844 sym_link *letype , *retype;
4848 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4850 right= IC_RIGHT(ic);
4851 result = IC_RESULT(ic);
4853 letype = getSpec(operandType(left));
4854 retype =getSpec(operandType(right));
4855 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4857 /* assign the amsops */
4858 aopOp (left,ic,FALSE);
4859 aopOp (right,ic,FALSE);
4860 aopOp (result,ic,TRUE);
4862 genCmp(left, right, result, ifx, sign);
4864 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4865 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4866 freeAsmop(result,NULL,ic,TRUE);
4870 /*-----------------------------------------------------------------*/
4871 /* genc16bit2lit - compare a 16 bit value to a literal */
4872 /*-----------------------------------------------------------------*/
4873 static void genc16bit2lit(operand *op, int lit, int offset)
4878 DEBUGpic14_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
4879 if( (lit&0xff) == 0)
4884 switch( BYTEofLONG(lit,i)) {
4886 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4889 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4892 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4895 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4896 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4901 switch( BYTEofLONG(lit,i)) {
4903 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4907 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4911 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4914 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4916 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4924 /*-----------------------------------------------------------------*/
4925 /* gencjneshort - compare and jump if not equal */
4926 /*-----------------------------------------------------------------*/
4927 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4929 int size = min(AOP_SIZE(left),AOP_SIZE(right));
4934 //unsigned long lit = 0L;
4936 if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4937 emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4940 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4941 DEBUGpic14_AopType(__LINE__,left,right,result);
4943 assert (!pic14_sameRegs (AOP(left), AOP(result)));
4944 assert (!pic14_sameRegs (AOP(right), AOP(result)));
4945 if (AOP_SIZE(result)) {
4946 for (offset = 0; offset < AOP_SIZE(result); offset++)
4947 emitpcode (POC_CLRF, popGet (AOP(result), offset));
4950 assert (AOP_SIZE(left) == AOP_SIZE(right));
4951 //resolveIfx(&rIfx,ifx);
4952 lbl = newiTempLabel (NULL);
4955 mov2w (AOP(right),size);
4956 emitpcode (POC_XORFW, popGet (AOP(left), size));
4960 emitpcode (POC_GOTO, popGetLabel (lbl->key));
4963 emitpLabel (lbl->key);
4964 if (AOP_SIZE(result)) {
4966 emitpcode (POC_INCF, popGet (AOP(result), 0));
4969 genSkipz (ifx, NULL != IC_TRUE(ifx));
4976 DEBUGpic14_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
4977 assert (!pic14_sameRegs (AOP(result), AOP(left)));
4978 assert (!pic14_sameRegs (AOP(result), AOP(right)));
4979 for (offset=0; offset < AOP_SIZE(result); offset++)
4981 emitpcode (POC_CLRF, popGet (AOP(result), offset));
4986 /* if the left side is a literal or
4987 if the right is in a pointer register and left
4989 if ((AOP_TYPE(left) == AOP_LIT) ||
4990 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4995 if(AOP_TYPE(right) == AOP_LIT)
4996 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4998 /* if the right side is a literal then anything goes */
4999 if (AOP_TYPE(right) == AOP_LIT &&
5000 AOP_TYPE(left) != AOP_DIR ) {
5003 genc16bit2lit(left, lit, 0);
5005 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5011 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5012 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5014 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5018 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5026 /* if the right side is in a register or in direct space or
5027 if the left is a pointer register & right is not */
5028 else if (AOP_TYPE(right) == AOP_REG ||
5029 AOP_TYPE(right) == AOP_DIR ||
5030 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5031 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5032 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5033 int lbl_key = lbl->key;
5036 DEBUGpic14_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
5037 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
5038 __FUNCTION__,__LINE__);
5042 /* switch(size) { */
5044 /* genc16bit2lit(left, lit, 0); */
5046 /* emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
5052 if((AOP_TYPE(left) == AOP_DIR) &&
5053 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5055 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5056 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5058 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5060 switch (lit & 0xff) {
5062 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5065 emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
5066 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5067 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5071 emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5072 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5073 //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5074 emitpcode(POC_GOTO,popGetLabel(lbl_key));
5078 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5079 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5084 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5087 if(AOP_TYPE(result) == AOP_CRY) {
5088 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5093 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5095 /* fix me. probably need to check result size too */
5096 //emitpcode(POC_CLRF,popGet(AOP(result),0));
5101 emitpcode(POC_GOTO,popGetLabel(lbl_key));
5111 } else if(AOP_TYPE(right) == AOP_REG &&
5112 AOP_TYPE(left) != AOP_DIR){
5116 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5117 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5118 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5123 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5128 /* right is a pointer reg need both a & b */
5131 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5133 pic14_emitcode("mov","b,%s",l);
5134 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5135 pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
5140 emitpcode(POC_INCF,popGet(AOP(result),0));
5142 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5144 emitpLabel(lbl->key);
5146 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5155 /*-----------------------------------------------------------------*/
5156 /* gencjne - compare and jump if not equal */
5157 /*-----------------------------------------------------------------*/
5158 static void gencjne(operand *left, operand *right, iCode *ifx)
5160 symbol *tlbl = newiTempLabel(NULL);
5162 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5163 gencjneshort(left, right, lbl);
5165 pic14_emitcode("mov","a,%s",one);
5166 pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5167 pic14_emitcode("","%05d_DS_:",lbl->key+100);
5168 pic14_emitcode("clr","a");
5169 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5171 emitpLabel(lbl->key);
5172 emitpLabel(tlbl->key);
5177 /*-----------------------------------------------------------------*/
5178 /* genCmpEq - generates code for equal to */
5179 /*-----------------------------------------------------------------*/
5180 static void genCmpEq (iCode *ic, iCode *ifx)
5182 operand *left, *right, *result;
5184 symbol *false_label;
5187 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5190 DEBUGpic14_emitcode ("; ifx is non-null","");
5192 DEBUGpic14_emitcode ("; ifx is null","");
5194 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5195 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5196 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5198 DEBUGpic14_AopType(__LINE__,left,right,result);
5200 /* if literal, move literal to right */
5201 if (op_isLitLike (IC_LEFT(ic))) {
5202 operand *tmp = right ;
5208 if (ifx && !IC_TRUE(ifx))
5210 assert (IC_FALSE(ifx));
5211 false_label = IC_FALSE(ifx);
5214 size = min(AOP_SIZE(left),AOP_SIZE(right));
5215 assert(!pic14_sameRegs(AOP(result),AOP(left)));
5216 assert(!pic14_sameRegs(AOP(result),AOP(right)));
5218 /* assume left != right */
5221 for (i=0; i < AOP_SIZE(result); i++)
5223 emitpcode(POC_CLRF, popGet(AOP(result),i));
5227 if (AOP_TYPE(right) == AOP_LIT)
5229 unsigned long lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
5231 size = AOP_SIZE(left);
5232 assert(!op_isLitLike(left));
5237 mov2w(AOP(left), 0);
5238 for (i=1; i < size; i++)
5239 emitpcode(POC_IORFW,popGet(AOP(left),i));
5240 /* now Z is set iff `left == right' */
5242 if (!false_label) false_label = newiTempLabel(NULL);
5243 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5247 for (i=0; i < size; i++)
5250 emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
5251 /* now Z is cleared if `left != right' */
5253 if (!false_label) false_label = newiTempLabel(NULL);
5254 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5261 /* right is no literal */
5264 for (i=0; i < size; i++)
5266 mov2w(AOP(right),i);
5267 emitpcode(POC_XORFW,popGet(AOP(left),i));
5268 /* now Z is cleared if `left != right' */
5270 if (!false_label) false_label = newiTempLabel(NULL);
5271 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5275 /* if we reach here, left == right */
5277 if (AOP_SIZE(result) > 0)
5279 emitpcode(POC_INCF, popGet(AOP(result),0));
5282 if (ifx && IC_TRUE(ifx))
5284 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5287 if (false_label && (!ifx || IC_TRUE(ifx)))
5288 emitpLabel(false_label->key);
5290 if (ifx) ifx->generated = 1;
5292 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5293 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5294 freeAsmop(result,NULL,ic,TRUE);
5297 /*-----------------------------------------------------------------*/
5298 /* ifxForOp - returns the icode containing the ifx for operand */
5299 /*-----------------------------------------------------------------*/
5300 static iCode *ifxForOp ( operand *op, iCode *ic )
5303 /* if true symbol then needs to be assigned */
5304 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5305 if (IS_TRUE_SYMOP(op))
5308 /* if this has register type condition and
5309 the next instruction is ifx with the same operand
5310 and live to of the operand is upto the ifx only then */
5312 ic->next->op == IFX &&
5313 IC_COND(ic->next)->key == op->key &&
5314 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5318 ic->next->op == IFX &&
5319 IC_COND(ic->next)->key == op->key) {
5320 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5324 DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5326 ic->next->op == IFX)
5327 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5330 ic->next->op == IFX &&
5331 IC_COND(ic->next)->key == op->key) {
5332 DEBUGpic14_emitcode ("; "," key is okay");
5333 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5334 OP_SYMBOL(op)->liveTo,
5341 /*-----------------------------------------------------------------*/
5342 /* genAndOp - for && operation */
5343 /*-----------------------------------------------------------------*/
5344 static void genAndOp (iCode *ic)
5346 operand *left,*right, *result;
5350 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5351 /* note here that && operations that are in an
5352 if statement are taken away by backPatchLabels
5353 only those used in arthmetic operations remain */
5354 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5355 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5356 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5358 DEBUGpic14_AopType(__LINE__,left,right,result);
5360 emitpcode(POC_MOVFW,popGet(AOP(left),0));
5361 emitpcode(POC_ANDFW,popGet(AOP(right),0));
5362 emitpcode(POC_MOVWF,popGet(AOP(result),0));
5364 /* if both are bit variables */
5365 /* if (AOP_TYPE(left) == AOP_CRY && */
5366 /* AOP_TYPE(right) == AOP_CRY ) { */
5367 /* pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5368 /* pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5369 /* pic14_outBitC(result); */
5371 /* tlbl = newiTempLabel(NULL); */
5372 /* pic14_toBoolean(left); */
5373 /* pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5374 /* pic14_toBoolean(right); */
5375 /* pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5376 /* pic14_outBitAcc(result); */
5379 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5380 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5381 freeAsmop(result,NULL,ic,TRUE);
5385 /*-----------------------------------------------------------------*/
5386 /* genOrOp - for || operation */
5387 /*-----------------------------------------------------------------*/
5390 modified this code, but it doesn't appear to ever get called
5393 static void genOrOp (iCode *ic)
5395 operand *left,*right, *result;
5399 /* note here that || operations that are in an
5400 if statement are taken away by backPatchLabels
5401 only those used in arthmetic operations remain */
5403 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5404 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5405 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5406 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5408 DEBUGpic14_AopType(__LINE__,left,right,result);
5410 for (i=0; i < AOP_SIZE(result); i++)
5412 emitpcode(POC_CLRF, popGet(AOP(result), i));
5415 tlbl = newiTempLabel(NULL);
5416 pic14_toBoolean(left);
5418 emitpcode(POC_GOTO, popGetLabel(tlbl->key));
5419 pic14_toBoolean(right);
5420 emitpLabel(tlbl->key);
5421 /* here Z is clear IFF `left || right' */
5423 emitpcode(POC_INCF, popGet(AOP(result), 0));
5425 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5426 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5427 freeAsmop(result,NULL,ic,TRUE);
5430 /*-----------------------------------------------------------------*/
5431 /* isLiteralBit - test if lit == 2^n */
5432 /*-----------------------------------------------------------------*/
5433 static int isLiteralBit(unsigned long lit)
5435 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5436 0x100L,0x200L,0x400L,0x800L,
5437 0x1000L,0x2000L,0x4000L,0x8000L,
5438 0x10000L,0x20000L,0x40000L,0x80000L,
5439 0x100000L,0x200000L,0x400000L,0x800000L,
5440 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5441 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5445 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5446 for(idx = 0; idx < 32; idx++)
5452 /*-----------------------------------------------------------------*/
5453 /* continueIfTrue - */
5454 /*-----------------------------------------------------------------*/
5455 static void continueIfTrue (iCode *ic)
5458 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5460 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5464 /*-----------------------------------------------------------------*/
5466 /*-----------------------------------------------------------------*/
5467 static void jumpIfTrue (iCode *ic)
5470 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5472 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5476 /*-----------------------------------------------------------------*/
5477 /* jmpTrueOrFalse - */
5478 /*-----------------------------------------------------------------*/
5479 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5482 // ugly but optimized by peephole
5483 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5485 symbol *nlbl = newiTempLabel(NULL);
5486 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5487 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5488 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5489 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5492 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5493 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5498 /*-----------------------------------------------------------------*/
5499 /* genAnd - code for and */
5500 /*-----------------------------------------------------------------*/
5501 static void genAnd (iCode *ic, iCode *ifx)
5503 operand *left, *right, *result;
5505 unsigned long lit = 0L;
5510 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5511 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5512 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5513 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5515 resolveIfx(&rIfx,ifx);
5517 /* if left is a literal & right is not then exchange them */
5518 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5519 AOP_NEEDSACC(left)) {
5520 operand *tmp = right ;
5525 /* if result = right then exchange them */
5526 if(pic14_sameRegs(AOP(result),AOP(right))){
5527 operand *tmp = right ;
5532 /* if right is bit then exchange them */
5533 if (AOP_TYPE(right) == AOP_CRY &&
5534 AOP_TYPE(left) != AOP_CRY){
5535 operand *tmp = right ;
5539 if(AOP_TYPE(right) == AOP_LIT)
5540 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5542 size = AOP_SIZE(result);
5544 DEBUGpic14_AopType(__LINE__,left,right,result);
5547 // result = bit & yy;
5548 if (AOP_TYPE(left) == AOP_CRY){
5549 // c = bit & literal;
5550 if(AOP_TYPE(right) == AOP_LIT){
5552 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5555 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5558 if(size && (AOP_TYPE(result) == AOP_CRY)){
5559 pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5562 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5566 pic14_emitcode("clr","c");
5569 if (AOP_TYPE(right) == AOP_CRY){
5571 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5572 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5575 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5577 pic14_emitcode("rrc","a");
5578 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5584 pic14_outBitC(result);
5586 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5587 genIfxJump(ifx, "c");
5591 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5592 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5593 if((AOP_TYPE(right) == AOP_LIT) &&
5594 (AOP_TYPE(result) == AOP_CRY) &&
5595 (AOP_TYPE(left) != AOP_CRY)){
5596 int posbit = isLiteralBit(lit);
5600 //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5603 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5608 while (posbit > 7) {
5612 emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5613 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5614 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5621 symbol *tlbl = newiTempLabel(NULL);
5622 int sizel = AOP_SIZE(left);
5624 pic14_emitcode("setb","c");
5626 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5627 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5629 if((posbit = isLiteralBit(bytelit)) != 0)
5630 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5632 if(bytelit != 0x0FFL)
5633 pic14_emitcode("anl","a,%s",
5634 aopGet(AOP(right),offset,FALSE,TRUE));
5635 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5640 // bit = left & literal
5642 pic14_emitcode("clr","c");
5643 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5645 // if(left & literal)
5648 jmpTrueOrFalse(ifx, tlbl);
5652 pic14_outBitC(result);
5656 /* if left is same as result */
5657 if(pic14_sameRegs(AOP(result),AOP(left))){
5659 for(;size--; offset++,lit>>=8) {
5660 if(AOP_TYPE(right) == AOP_LIT){
5661 switch(lit & 0xff) {
5663 /* and'ing with 0 has clears the result */
5664 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5667 /* and'ing with 0xff is a nop when the result and left are the same */
5672 int p = my_powof2( (~lit) & 0xff );
5674 /* only one bit is set in the literal, so use a bcf instruction */
5675 emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5678 if(know_W != (int)(lit&0xff))
5679 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5681 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5686 if (AOP_TYPE(left) == AOP_ACC) {
5687 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5689 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5690 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5697 // left & result in different registers
5698 if(AOP_TYPE(result) == AOP_CRY){
5700 // if(size), result in bit
5701 // if(!size && ifx), conditional oper: if(left & right)
5702 symbol *tlbl = newiTempLabel(NULL);
5703 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5705 pic14_emitcode("setb","c");
5707 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5708 pic14_emitcode("anl","a,%s",
5709 aopGet(AOP(left),offset,FALSE,FALSE));
5710 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5715 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5716 pic14_outBitC(result);
5718 jmpTrueOrFalse(ifx, tlbl);
5720 for(;(size--);offset++) {
5722 // result = left & right
5723 if(AOP_TYPE(right) == AOP_LIT){
5724 int t = (lit >> (offset*8)) & 0x0FFL;
5727 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5730 if(AOP_TYPE(left) != AOP_ACC) {
5731 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5733 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5736 if(AOP_TYPE(left) == AOP_ACC) {
5737 emitpcode(POC_ANDLW, popGetLit(t));
5739 emitpcode(POC_MOVLW, popGetLit(t));
5740 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5742 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5747 if (AOP_TYPE(left) == AOP_ACC) {
5748 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5750 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5751 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5753 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5759 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5760 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5761 freeAsmop(result,NULL,ic,TRUE);
5764 /*-----------------------------------------------------------------*/
5765 /* genOr - code for or */
5766 /*-----------------------------------------------------------------*/
5767 static void genOr (iCode *ic, iCode *ifx)
5769 operand *left, *right, *result;
5771 unsigned long lit = 0L;
5774 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5776 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5777 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5778 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5780 DEBUGpic14_AopType(__LINE__,left,right,result);
5782 /* if left is a literal & right is not then exchange them */
5783 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5784 AOP_NEEDSACC(left)) {
5785 operand *tmp = right ;
5790 /* if result = right then exchange them */
5791 if(pic14_sameRegs(AOP(result),AOP(right))){
5792 operand *tmp = right ;
5797 /* if right is bit then exchange them */
5798 if (AOP_TYPE(right) == AOP_CRY &&
5799 AOP_TYPE(left) != AOP_CRY){
5800 operand *tmp = right ;
5805 DEBUGpic14_AopType(__LINE__,left,right,result);
5807 if(AOP_TYPE(right) == AOP_LIT)
5808 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5810 size = AOP_SIZE(result);
5814 if (AOP_TYPE(left) == AOP_CRY){
5815 if(AOP_TYPE(right) == AOP_LIT){
5816 // c = bit & literal;
5818 // lit != 0 => result = 1
5819 if(AOP_TYPE(result) == AOP_CRY){
5821 emitpcode(POC_BSF, popGet(AOP(result),0));
5822 //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5823 // AOP(result)->aopu.aop_dir,
5824 // AOP(result)->aopu.aop_dir);
5826 continueIfTrue(ifx);
5830 // lit == 0 => result = left
5831 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5833 pic14_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5836 if (AOP_TYPE(right) == AOP_CRY){
5837 if(pic14_sameRegs(AOP(result),AOP(left))){
5839 emitpcode(POC_BCF, popGet(AOP(result),0));
5840 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5841 emitpcode(POC_BSF, popGet(AOP(result),0));
5843 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5844 AOP(result)->aopu.aop_dir,
5845 AOP(result)->aopu.aop_dir);
5846 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5847 AOP(right)->aopu.aop_dir,
5848 AOP(right)->aopu.aop_dir);
5849 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5850 AOP(result)->aopu.aop_dir,
5851 AOP(result)->aopu.aop_dir);
5853 if( AOP_TYPE(result) == AOP_ACC) {
5854 emitpcode(POC_MOVLW, popGetLit(0));
5855 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5856 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5857 emitpcode(POC_MOVLW, popGetLit(1));
5861 emitpcode(POC_BCF, popGet(AOP(result),0));
5862 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5863 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5864 emitpcode(POC_BSF, popGet(AOP(result),0));
5866 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5867 AOP(result)->aopu.aop_dir,
5868 AOP(result)->aopu.aop_dir);
5869 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5870 AOP(right)->aopu.aop_dir,
5871 AOP(right)->aopu.aop_dir);
5872 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5873 AOP(left)->aopu.aop_dir,
5874 AOP(left)->aopu.aop_dir);
5875 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5876 AOP(result)->aopu.aop_dir,
5877 AOP(result)->aopu.aop_dir);
5882 symbol *tlbl = newiTempLabel(NULL);
5883 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5886 emitpcode(POC_BCF, popGet(AOP(result),0));
5887 if( AOP_TYPE(right) == AOP_ACC) {
5888 emitpcode(POC_IORLW, popGetLit(0));
5890 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5891 emitpcode(POC_BSF, popGet(AOP(result),0));
5896 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5897 pic14_emitcode(";XXX setb","c");
5898 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5899 AOP(left)->aopu.aop_dir,tlbl->key+100);
5900 pic14_toBoolean(right);
5901 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5902 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5903 jmpTrueOrFalse(ifx, tlbl);
5907 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5914 pic14_outBitC(result);
5916 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5917 genIfxJump(ifx, "c");
5921 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5922 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5923 if((AOP_TYPE(right) == AOP_LIT) &&
5924 (AOP_TYPE(result) == AOP_CRY) &&
5925 (AOP_TYPE(left) != AOP_CRY)){
5927 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5930 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5932 continueIfTrue(ifx);
5935 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5936 // lit = 0, result = boolean(left)
5938 pic14_emitcode(";XXX setb","c");
5939 pic14_toBoolean(right);
5941 symbol *tlbl = newiTempLabel(NULL);
5942 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5944 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5946 genIfxJump (ifx,"a");
5950 pic14_outBitC(result);
5954 /* if left is same as result */
5955 if(pic14_sameRegs(AOP(result),AOP(left))){
5957 for(;size--; offset++,lit>>=8) {
5958 if(AOP_TYPE(right) == AOP_LIT){
5959 if((lit & 0xff) == 0)
5960 /* or'ing with 0 has no effect */
5963 int p = my_powof2(lit & 0xff);
5965 /* only one bit is set in the literal, so use a bsf instruction */
5967 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5969 if(know_W != (int)(lit & 0xff))
5970 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5971 know_W = lit & 0xff;
5972 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5977 if (AOP_TYPE(left) == AOP_ACC) {
5978 emitpcode(POC_IORFW, popGet(AOP(right),offset));
5979 pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5981 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
5982 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5984 pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5985 pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5991 // left & result in different registers
5992 if(AOP_TYPE(result) == AOP_CRY){
5994 // if(size), result in bit
5995 // if(!size && ifx), conditional oper: if(left | right)
5996 symbol *tlbl = newiTempLabel(NULL);
5997 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5998 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6002 pic14_emitcode(";XXX setb","c");
6004 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6005 pic14_emitcode(";XXX orl","a,%s",
6006 aopGet(AOP(left),offset,FALSE,FALSE));
6007 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6012 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6013 pic14_outBitC(result);
6015 jmpTrueOrFalse(ifx, tlbl);
6016 } else for(;(size--);offset++){
6018 // result = left | right
6019 if(AOP_TYPE(right) == AOP_LIT){
6020 int t = (lit >> (offset*8)) & 0x0FFL;
6023 if (AOP_TYPE(left) != AOP_ACC) {
6024 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
6026 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6030 if (AOP_TYPE(left) == AOP_ACC) {
6031 emitpcode(POC_IORLW, popGetLit(t));
6033 emitpcode(POC_MOVLW, popGetLit(t));
6034 emitpcode(POC_IORFW, popGet(AOP(left),offset));
6036 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6041 // faster than result <- left, anl result,right
6042 // and better if result is SFR
6043 if (AOP_TYPE(left) == AOP_ACC) {
6044 emitpcode(POC_IORFW,popGet(AOP(right),offset));
6046 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6047 emitpcode(POC_IORFW,popGet(AOP(left),offset));
6049 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6054 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6055 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6056 freeAsmop(result,NULL,ic,TRUE);
6059 /*-----------------------------------------------------------------*/
6060 /* genXor - code for xclusive or */
6061 /*-----------------------------------------------------------------*/
6062 static void genXor (iCode *ic, iCode *ifx)
6064 operand *left, *right, *result;
6066 unsigned long lit = 0L;
6069 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6071 aopOp((left = IC_LEFT(ic)),ic,FALSE);
6072 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6073 aopOp((result=IC_RESULT(ic)),ic,TRUE);
6075 /* if left is a literal & right is not ||
6076 if left needs acc & right does not */
6077 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6078 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6079 operand *tmp = right ;
6084 /* if result = right then exchange them */
6085 if(pic14_sameRegs(AOP(result),AOP(right))){
6086 operand *tmp = right ;
6091 /* if right is bit then exchange them */
6092 if (AOP_TYPE(right) == AOP_CRY &&
6093 AOP_TYPE(left) != AOP_CRY){
6094 operand *tmp = right ;
6098 if(AOP_TYPE(right) == AOP_LIT)
6099 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6101 size = AOP_SIZE(result);
6105 if (AOP_TYPE(left) == AOP_CRY){
6106 if(AOP_TYPE(right) == AOP_LIT){
6107 // c = bit & literal;
6109 // lit>>1 != 0 => result = 1
6110 if(AOP_TYPE(result) == AOP_CRY){
6112 {emitpcode(POC_BSF, popGet(AOP(result),offset));
6113 pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6115 continueIfTrue(ifx);
6118 pic14_emitcode("setb","c");
6122 // lit == 0, result = left
6123 if(size && pic14_sameRegs(AOP(result),AOP(left)))
6125 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6127 // lit == 1, result = not(left)
6128 if(size && pic14_sameRegs(AOP(result),AOP(left))){
6129 emitpcode(POC_MOVLW, popGet(AOP(result),offset));
6130 emitpcode(POC_XORWF, popGet(AOP(result),offset));
6131 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6134 assert ( !"incomplete genXor" );
6135 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6136 pic14_emitcode("cpl","c");
6143 symbol *tlbl = newiTempLabel(NULL);
6144 if (AOP_TYPE(right) == AOP_CRY){
6146 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6149 int sizer = AOP_SIZE(right);
6151 // if val>>1 != 0, result = 1
6152 pic14_emitcode("setb","c");
6154 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6156 // test the msb of the lsb
6157 pic14_emitcode("anl","a,#0xfe");
6158 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6162 pic14_emitcode("rrc","a");
6164 pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6165 pic14_emitcode("cpl","c");
6166 pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6171 pic14_outBitC(result);
6173 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6174 genIfxJump(ifx, "c");
6178 if(pic14_sameRegs(AOP(result),AOP(left))){
6179 /* if left is same as result */
6180 for(;size--; offset++) {
6181 if(AOP_TYPE(right) == AOP_LIT){
6182 int t = (lit >> (offset*8)) & 0x0FFL;
6186 if (IS_AOP_PREG(left)) {
6187 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6188 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6189 aopPut(AOP(result),"a",offset);
6191 emitpcode(POC_MOVLW, popGetLit(t));
6192 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6193 pic14_emitcode("xrl","%s,%s",
6194 aopGet(AOP(left),offset,FALSE,TRUE),
6195 aopGet(AOP(right),offset,FALSE,FALSE));
6198 if (AOP_TYPE(left) == AOP_ACC)
6199 pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6201 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6202 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6204 if (IS_AOP_PREG(left)) {
6205 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6206 aopPut(AOP(result),"a",offset);
6208 pic14_emitcode("xrl","%s,a",
6209 aopGet(AOP(left),offset,FALSE,TRUE));
6215 // left & result in different registers
6216 if(AOP_TYPE(result) == AOP_CRY){
6218 // if(size), result in bit
6219 // if(!size && ifx), conditional oper: if(left ^ right)
6220 symbol *tlbl = newiTempLabel(NULL);
6221 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6223 pic14_emitcode("setb","c");
6225 if((AOP_TYPE(right) == AOP_LIT) &&
6226 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6227 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6229 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6230 pic14_emitcode("xrl","a,%s",
6231 aopGet(AOP(left),offset,FALSE,FALSE));
6233 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6238 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6239 pic14_outBitC(result);
6241 jmpTrueOrFalse(ifx, tlbl);
6242 } else for(;(size--);offset++){
6244 // result = left & right
6245 if(AOP_TYPE(right) == AOP_LIT){
6246 int t = (lit >> (offset*8)) & 0x0FFL;
6249 if (AOP_TYPE(left) != AOP_ACC) {
6250 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6252 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6253 pic14_emitcode("movf","%s,w",
6254 aopGet(AOP(left),offset,FALSE,FALSE));
6255 pic14_emitcode("movwf","%s",
6256 aopGet(AOP(result),offset,FALSE,FALSE));
6259 if (AOP_TYPE(left) == AOP_ACC) {
6260 emitpcode(POC_XORLW, popGetLit(t));
6262 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6264 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6267 if (AOP_TYPE(left) == AOP_ACC) {
6268 emitpcode(POC_XORLW, popGetLit(t));
6270 emitpcode(POC_MOVLW, popGetLit(t));
6271 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6273 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6274 pic14_emitcode("movlw","0x%x",t);
6275 pic14_emitcode("xorwf","%s,w",
6276 aopGet(AOP(left),offset,FALSE,FALSE));
6277 pic14_emitcode("movwf","%s",
6278 aopGet(AOP(result),offset,FALSE,FALSE));
6284 // faster than result <- left, anl result,right
6285 // and better if result is SFR
6286 if (AOP_TYPE(left) == AOP_ACC) {
6287 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6289 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6290 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6292 if ( AOP_TYPE(result) != AOP_ACC){
6293 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6299 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6300 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6301 freeAsmop(result,NULL,ic,TRUE);
6304 /*-----------------------------------------------------------------*/
6305 /* genInline - write the inline code out */
6306 /*-----------------------------------------------------------------*/
6307 static void genInline (iCode *ic)
6309 char *buffer, *bp, *bp1;
6312 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6314 _G.inLine += (!options.asmpeep);
6316 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6317 strcpy(buffer,IC_INLINE(ic));
6319 /* emit each line as a code */
6325 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6333 /* print label, use this special format with NULL directive
6334 * to denote that the argument should not be indented with tab */
6335 addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6342 if ((bp1 != bp) && *bp1)
6343 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6347 _G.inLine -= (!options.asmpeep);
6350 /*-----------------------------------------------------------------*/
6351 /* genRRC - rotate right with carry */
6352 /*-----------------------------------------------------------------*/
6353 static void genRRC (iCode *ic)
6355 operand *left , *result ;
6356 int size, offset = 0, same;
6359 /* rotate right with carry */
6361 result=IC_RESULT(ic);
6362 aopOp (left,ic,FALSE);
6363 aopOp (result,ic,FALSE);
6365 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6367 same = pic14_sameRegs(AOP(result),AOP(left));
6369 size = AOP_SIZE(result);
6371 /* get the lsb and put it into the carry */
6372 emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6379 emitpcode(POC_RRF, popGet(AOP(left),offset));
6381 emitpcode(POC_RRFW, popGet(AOP(left),offset));
6382 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6388 freeAsmop(left,NULL,ic,TRUE);
6389 freeAsmop(result,NULL,ic,TRUE);
6392 /*-----------------------------------------------------------------*/
6393 /* genRLC - generate code for rotate left with carry */
6394 /*-----------------------------------------------------------------*/
6395 static void genRLC (iCode *ic)
6397 operand *left , *result ;
6398 int size, offset = 0;
6402 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6403 /* rotate right with carry */
6405 result=IC_RESULT(ic);
6406 aopOp (left,ic,FALSE);
6407 aopOp (result,ic,FALSE);
6409 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6411 same = pic14_sameRegs(AOP(result),AOP(left));
6413 /* move it to the result */
6414 size = AOP_SIZE(result);
6416 /* get the msb and put it into the carry */
6417 emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6424 emitpcode(POC_RLF, popGet(AOP(left),offset));
6426 emitpcode(POC_RLFW, popGet(AOP(left),offset));
6427 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6434 freeAsmop(left,NULL,ic,TRUE);
6435 freeAsmop(result,NULL,ic,TRUE);
6438 /*-----------------------------------------------------------------*/
6439 /* genGetHbit - generates code get highest order bit */
6440 /*-----------------------------------------------------------------*/
6441 static void genGetHbit (iCode *ic)
6443 operand *left, *result;
6445 result=IC_RESULT(ic);
6446 aopOp (left,ic,FALSE);
6447 aopOp (result,ic,FALSE);
6450 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6451 /* get the highest order byte into a */
6452 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6453 if(AOP_TYPE(result) == AOP_CRY){
6454 pic14_emitcode("rlc","a");
6455 pic14_outBitC(result);
6458 pic14_emitcode("rl","a");
6459 pic14_emitcode("anl","a,#0x01");
6460 pic14_outAcc(result);
6464 freeAsmop(left,NULL,ic,TRUE);
6465 freeAsmop(result,NULL,ic,TRUE);
6468 /*-----------------------------------------------------------------*/
6469 /* AccLsh - shift left accumulator by known count */
6470 /* MARK: pic14 always rotates through CARRY! */
6471 /*-----------------------------------------------------------------*/
6472 static void AccLsh (pCodeOp *pcop,int shCount)
6475 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6476 shCount &= 0x0007; // shCount : 0..7
6483 emitpcode(POC_RLF,pcop);
6487 emitpcode(POC_RLF,pcop);
6488 emitpcode(POC_RLF,pcop);
6491 emitpcode(POC_RLF,pcop);
6492 emitpcode(POC_RLF,pcop);
6493 emitpcode(POC_RLF,pcop);
6496 emitpcode(POC_SWAPF,pcop);
6499 emitpcode(POC_SWAPF,pcop);
6500 emitpcode(POC_RLF,pcop);
6503 emitpcode(POC_SWAPF,pcop);
6504 emitpcode(POC_RLF,pcop);
6505 emitpcode(POC_RLF,pcop);
6508 emitpcode(POC_RRFW,pcop);
6509 emitpcode(POC_RRF,pcop);
6512 /* clear invalid bits */
6513 emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6514 emitpcode(POC_ANDWF, pcop);
6517 /*-----------------------------------------------------------------*/
6518 /* AccRsh - shift right accumulator by known count */
6519 /* MARK: pic14 always rotates through CARRY! */
6520 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6521 /* 1: mask out invalid bits (zero-extend) */
6522 /* 2: sign-extend result (pretty slow) */
6523 /*-----------------------------------------------------------------*/
6524 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6527 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6528 shCount &= 0x0007; // shCount : 0..7
6534 /* load sign if needed */
6535 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6536 else if (mask_mode == 1) emitCLRC;
6537 emitpcode(POC_RRF,pcop);
6541 /* load sign if needed */
6542 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6543 emitpcode(POC_RRF,pcop);
6544 /* load sign if needed */
6545 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6546 emitpcode(POC_RRF,pcop);
6547 if (mask_mode == 2) return;
6550 /* load sign if needed */
6551 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6552 emitpcode(POC_RRF,pcop);
6553 /* load sign if needed */
6554 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6555 emitpcode(POC_RRF,pcop);
6556 /* load sign if needed */
6557 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6558 emitpcode(POC_RRF,pcop);
6559 if (mask_mode == 2) return;
6562 emitpcode(POC_SWAPF,pcop);
6565 emitpcode(POC_SWAPF,pcop);
6566 emitpcode(POC_RRF,pcop);
6569 emitpcode(POC_SWAPF,pcop);
6570 emitpcode(POC_RRF,pcop);
6571 emitpcode(POC_RRF,pcop);
6577 emitpcode(POC_RLFW,pcop);
6578 emitpcode(POC_CLRF,pcop);
6580 emitpcode(POC_COMF,pcop);
6583 emitpcode(POC_RLFW,pcop);
6584 emitpcode(POC_RLF,pcop);
6591 /* leave invalid bits undefined */
6595 /* clear invalid bits -- zero-extend */
6596 emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6597 emitpcode(POC_ANDWF, pcop);
6599 if (mask_mode == 2) {
6601 emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6602 emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6603 emitpcode(POC_IORWF, pcop);
6608 /*-----------------------------------------------------------------*/
6609 /* AccSRsh - signed right shift accumulator by known count */
6610 /*-----------------------------------------------------------------*/
6611 static void AccSRsh (int shCount)
6614 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6617 pic14_emitcode("mov","c,acc.7");
6618 pic14_emitcode("rrc","a");
6619 } else if(shCount == 2){
6620 pic14_emitcode("mov","c,acc.7");
6621 pic14_emitcode("rrc","a");
6622 pic14_emitcode("mov","c,acc.7");
6623 pic14_emitcode("rrc","a");
6625 tlbl = newiTempLabel(NULL);
6626 /* rotate right accumulator */
6627 AccRol(8 - shCount);
6628 /* and kill the higher order bits */
6629 pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6630 pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6631 pic14_emitcode("orl","a,#0x%02x",
6632 (unsigned char)~SRMask[shCount]);
6633 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6638 /*-----------------------------------------------------------------*/
6639 /* shiftR1Left2Result - shift right one byte from left to result */
6640 /*-----------------------------------------------------------------*/
6641 static void shiftR1Left2ResultSigned (operand *left, int offl,
6642 operand *result, int offr,
6648 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6650 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6654 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6656 emitpcode(POC_RRF, popGet(AOP(result),offr));
6658 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6659 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6665 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6667 emitpcode(POC_RRF, popGet(AOP(result),offr));
6669 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6670 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6672 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6673 emitpcode(POC_RRF, popGet(AOP(result),offr));
6679 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6681 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6682 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6685 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6686 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6687 emitpcode(POC_ANDLW, popGetLit(0x1f));
6689 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6690 emitpcode(POC_IORLW, popGetLit(0xe0));
6692 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6696 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6697 emitpcode(POC_ANDLW, popGetLit(0x0f));
6698 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6699 emitpcode(POC_IORLW, popGetLit(0xf0));
6700 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6704 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6706 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6707 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6709 emitpcode(POC_RRFW, popGet(AOP(result),offr));
6710 emitpcode(POC_ANDLW, popGetLit(0x07));
6711 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6712 emitpcode(POC_IORLW, popGetLit(0xf8));
6713 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6718 emitpcode(POC_MOVLW, popGetLit(0x00));
6719 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6720 emitpcode(POC_MOVLW, popGetLit(0xfe));
6721 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6722 emitpcode(POC_IORLW, popGetLit(0x01));
6723 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6725 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6726 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6727 emitpcode(POC_DECF, popGet(AOP(result),offr));
6728 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6729 emitpcode(POC_BCF, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6735 emitpcode(POC_MOVLW, popGetLit(0x00));
6736 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6737 emitpcode(POC_MOVLW, popGetLit(0xff));
6738 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6740 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6741 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6742 emitpcode(POC_DECF, popGet(AOP(result),offr));
6750 /*-----------------------------------------------------------------*/
6751 /* shiftR1Left2Result - shift right one byte from left to result */
6752 /*-----------------------------------------------------------------*/
6753 static void shiftR1Left2Result (operand *left, int offl,
6754 operand *result, int offr,
6755 int shCount, int sign)
6760 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6762 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6764 /* Copy the msb into the carry if signed. */
6766 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6776 emitpcode(POC_RRF, popGet(AOP(result),offr));
6778 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6779 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6785 emitpcode(POC_RRF, popGet(AOP(result),offr));
6787 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6788 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6791 emitpcode(POC_RRF, popGet(AOP(result),offr));
6796 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6798 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6799 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6802 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6803 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6804 emitpcode(POC_ANDLW, popGetLit(0x1f));
6805 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6809 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6810 emitpcode(POC_ANDLW, popGetLit(0x0f));
6811 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6815 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6816 emitpcode(POC_ANDLW, popGetLit(0x0f));
6817 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6819 emitpcode(POC_RRF, popGet(AOP(result),offr));
6824 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6825 emitpcode(POC_ANDLW, popGetLit(0x80));
6826 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6827 emitpcode(POC_RLF, popGet(AOP(result),offr));
6828 emitpcode(POC_RLF, popGet(AOP(result),offr));
6833 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6834 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6835 emitpcode(POC_RLF, popGet(AOP(result),offr));
6844 /*-----------------------------------------------------------------*/
6845 /* shiftL1Left2Result - shift left one byte from left to result */
6846 /*-----------------------------------------------------------------*/
6847 static void shiftL1Left2Result (operand *left, int offl,
6848 operand *result, int offr, int shCount)
6854 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6856 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6857 DEBUGpic14_emitcode ("; ***","same = %d",same);
6858 // l = aopGet(AOP(left),offl,FALSE,FALSE);
6860 /* shift left accumulator */
6861 //AccLsh(shCount); // don't comment out just yet...
6862 // aopPut(AOP(result),"a",offr);
6866 /* Shift left 1 bit position */
6867 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6869 emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6871 emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6872 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6876 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6877 emitpcode(POC_ANDLW,popGetLit(0x7e));
6878 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6879 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6882 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6883 emitpcode(POC_ANDLW,popGetLit(0x3e));
6884 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6885 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6886 emitpcode(POC_RLF, popGet(AOP(result),offr));
6889 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6890 emitpcode(POC_ANDLW, popGetLit(0xf0));
6891 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6894 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6895 emitpcode(POC_ANDLW, popGetLit(0xf0));
6896 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6897 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6900 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6901 emitpcode(POC_ANDLW, popGetLit(0x30));
6902 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6903 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6904 emitpcode(POC_RLF, popGet(AOP(result),offr));
6907 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6908 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6909 emitpcode(POC_RRF, popGet(AOP(result),offr));
6913 DEBUGpic14_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6919 /*-----------------------------------------------------------------*/
6920 /* movLeft2Result - move byte from left to result */
6921 /*-----------------------------------------------------------------*/
6922 static void movLeft2Result (operand *left, int offl,
6923 operand *result, int offr)
6927 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6928 if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6929 l = aopGet(AOP(left),offl,FALSE,FALSE);
6931 if (*l == '@' && (IS_AOP_PREG(result))) {
6932 pic14_emitcode("mov","a,%s",l);
6933 aopPut(AOP(result),"a",offr);
6935 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6936 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6941 /*-----------------------------------------------------------------*/
6942 /* shiftLeft_Left2ResultLit - shift left by known count */
6943 /*-----------------------------------------------------------------*/
6945 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6947 int size, same, offr, i;
6949 size = AOP_SIZE(left);
6950 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6952 same = pic14_sameRegs (AOP(left), AOP(result));
6955 shCount = shCount & 0x07;
6961 case 0: /* takes 0 or 2N cycles (for offr==0) */
6962 if (!same || offr) {
6963 for (i=size-1; i >= 0; i--)
6964 movLeft2Result (left, i, result, offr + i);
6968 case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6970 shiftLeft_Left2ResultLit (left, result, 8 * offr);
6971 shiftLeft_Left2ResultLit (result, result, shCount);
6972 return; /* prevent clearing result again */
6975 for (i=0; i < size; i++) {
6976 if (same && !offr) {
6977 emitpcode (POC_RLF, popGet (AOP(left), i));
6979 emitpcode (POC_RLFW, popGet (AOP(left), i));
6980 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6986 case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
6987 /* works in-place/with offr as well */
6988 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
6989 emitpcode (POC_ANDLW, popGetLit (0xF0));
6990 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
6992 for (i = size - 2; i >= 0; i--)
6994 emitpcode (POC_SWAPFW, popGet (AOP(left), i));
6995 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6996 emitpcode (POC_ANDLW, popGetLit (0x0F));
6997 emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
6998 emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
7002 case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
7003 /* works in-place/with offr as well */
7004 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
7005 for (i = size-2; i >= 0; i--) {
7006 emitpcode (POC_RRFW, popGet (AOP(left), i));
7007 emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
7009 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7010 emitpcode (POC_RRF, popGet (AOP(result), offr));
7014 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
7015 shiftLeft_Left2ResultLit (result, result, 1);
7016 return; /* prevent clearing result again */
7022 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7026 /*-----------------------------------------------------------------*/
7027 /* shiftRight_Left2ResultLit - shift right by known count */
7028 /*-----------------------------------------------------------------*/
7030 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
7032 int size, same, offr, i;
7034 size = AOP_SIZE(left);
7035 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7037 same = pic14_sameRegs (AOP(left), AOP(result));
7040 shCount = shCount & 0x07;
7048 case 0: /* takes 0 or 2N cycles (for offr==0) */
7049 if (!same || offr) {
7050 for (i=0; i < size; i++)
7051 movLeft2Result (left, i + offr, result, i);
7055 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7056 emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7058 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7059 shiftRight_Left2ResultLit (result, result, shCount, sign);
7060 return; /* prevent sign-extending result again */
7064 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7067 for (i = size-1; i >= 0; i--) {
7068 if (same && !offr) {
7069 emitpcode (POC_RRF, popGet (AOP(left), i));
7071 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7072 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7078 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7079 /* works in-place/with offr as well */
7080 emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7081 emitpcode (POC_ANDLW, popGetLit (0x0F));
7082 emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7084 for (i = 1; i < size; i++)
7086 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7087 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7088 emitpcode (POC_ANDLW, popGetLit (0xF0));
7089 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7090 emitpcode (POC_XORWF, popGet (AOP(result), i));
7095 emitpcode (POC_MOVLW, popGetLit (0xF0));
7096 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7097 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7101 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7102 /* works in-place/with offr as well */
7103 emitpcode (POC_RLFW, popGet (AOP(left), offr));
7104 for (i = 0; i < size-1; i++) {
7105 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7106 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7108 emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7110 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7113 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7118 shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7119 shiftRight_Left2ResultLit (result, result, 1, sign);
7120 return; /* prevent sign extending result again */
7125 addSign (result, size, sign);
7129 /*-----------------------------------------------------------------*/
7130 /* shiftL2Left2Result - shift left two bytes from left to result */
7131 /*-----------------------------------------------------------------*/
7132 static void shiftL2Left2Result (operand *left, int offl,
7133 operand *result, int offr, int shCount)
7137 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7139 if(pic14_sameRegs(AOP(result), AOP(left))) {
7147 emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7148 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7149 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7153 emitpcode(POC_RLF, popGet(AOP(result),offr));
7154 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7160 emitpcode(POC_MOVLW, popGetLit(0x0f));
7161 emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7162 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7163 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7164 emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7165 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7166 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7168 emitpcode(POC_RLF, popGet(AOP(result),offr));
7169 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7173 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7174 emitpcode(POC_RRF, popGet(AOP(result),offr));
7175 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7176 emitpcode(POC_RRF, popGet(AOP(result),offr));
7177 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7178 emitpcode(POC_ANDLW,popGetLit(0xc0));
7179 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7180 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7181 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7182 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7185 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7186 emitpcode(POC_RRFW, popGet(AOP(result),offr));
7187 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7188 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7189 emitpcode(POC_RRF, popGet(AOP(result),offr));
7199 /* note, use a mov/add for the shift since the mov has a
7200 chance of getting optimized out */
7201 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7202 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7203 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7204 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7205 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7209 emitpcode(POC_RLF, popGet(AOP(result),offr));
7210 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7216 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7217 emitpcode(POC_ANDLW, popGetLit(0xF0));
7218 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7219 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7220 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7221 emitpcode(POC_ANDLW, popGetLit(0xF0));
7222 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7223 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7227 emitpcode(POC_RLF, popGet(AOP(result),offr));
7228 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7232 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7233 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7234 emitpcode(POC_RRFW, popGet(AOP(result),offl));
7235 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7237 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7238 emitpcode(POC_RRF, popGet(AOP(result),offr));
7239 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7240 emitpcode(POC_ANDLW,popGetLit(0xc0));
7241 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7242 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7243 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7244 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7247 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7248 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7249 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7250 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7251 emitpcode(POC_RRF, popGet(AOP(result),offr));
7257 /*-----------------------------------------------------------------*/
7258 /* shiftR2Left2Result - shift right two bytes from left to result */
7259 /*-----------------------------------------------------------------*/
7260 static void shiftR2Left2Result (operand *left, int offl,
7261 operand *result, int offr,
7262 int shCount, int sign)
7267 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7268 same = pic14_sameRegs(AOP(result), AOP(left));
7270 if(same && ((offl + MSB16) == offr)){
7272 /* don't crash result[offr] */
7273 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7274 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7277 movLeft2Result(left,offl, result, offr);
7278 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7281 /* a:x >> shCount (x = lsb(result))*/
7284 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7286 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7295 emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7300 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7301 emitpcode(POC_RRF,popGet(AOP(result),offr));
7303 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7304 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7305 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7306 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7311 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7314 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7315 emitpcode(POC_RRF,popGet(AOP(result),offr));
7322 emitpcode(POC_MOVLW, popGetLit(0xf0));
7323 emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7324 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7326 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7327 emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7328 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7329 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7331 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7332 emitpcode(POC_ANDLW, popGetLit(0x0f));
7333 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7335 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7336 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7337 emitpcode(POC_ANDLW, popGetLit(0xf0));
7338 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7339 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7343 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7344 emitpcode(POC_RRF, popGet(AOP(result),offr));
7348 emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7349 emitpcode(POC_BTFSC,
7350 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7351 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7359 emitpcode(POC_RLF, popGet(AOP(result),offr));
7360 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7362 emitpcode(POC_RLF, popGet(AOP(result),offr));
7363 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7364 emitpcode(POC_RLFW, popGet(AOP(result),offr));
7365 emitpcode(POC_ANDLW,popGetLit(0x03));
7367 emitpcode(POC_BTFSC,
7368 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7369 emitpcode(POC_IORLW,popGetLit(0xfc));
7371 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7372 emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7373 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7374 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7376 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7377 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7378 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7379 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7380 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7381 emitpcode(POC_RLF, popGet(AOP(result),offr));
7382 emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7383 emitpcode(POC_ANDLW,popGetLit(0x03));
7385 emitpcode(POC_BTFSC,
7386 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7387 emitpcode(POC_IORLW,popGetLit(0xfc));
7389 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7390 //emitpcode(POC_RLF, popGet(AOP(result),offr));
7397 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7398 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7399 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7400 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7403 emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7405 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7409 /*-----------------------------------------------------------------*/
7410 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7411 /*-----------------------------------------------------------------*/
7412 static void shiftLLeftOrResult (operand *left, int offl,
7413 operand *result, int offr, int shCount)
7416 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7418 /* shift left accumulator */
7419 AccLsh(left,offl,shCount);
7420 /* or with result */
7421 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7422 assert ( !"broken (modifies left, fails for left==result))" );
7425 /*-----------------------------------------------------------------*/
7426 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7427 /*-----------------------------------------------------------------*/
7428 static void shiftRLeftOrResult (operand *left, int offl,
7429 operand *result, int offr, int shCount)
7432 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7434 /* shift right accumulator */
7435 AccRsh(left,offl,shCount);
7436 /* or with result */
7437 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7438 assert ( !"broken (modifies left, fails for left==result))" );
7441 /*-----------------------------------------------------------------*/
7442 /* genlshOne - left shift a one byte quantity by known count */
7443 /*-----------------------------------------------------------------*/
7444 static void genlshOne (operand *result, operand *left, int shCount)
7447 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7448 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7451 /*-----------------------------------------------------------------*/
7452 /* genlshTwo - left shift two bytes by known amount != 0 */
7453 /*-----------------------------------------------------------------*/
7454 static void genlshTwo (operand *result,operand *left, int shCount)
7459 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7460 size = pic14_getDataSize(result);
7462 /* if shCount >= 8 */
7468 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7470 movLeft2Result(left, LSB, result, MSB16);
7472 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7475 /* 1 <= shCount <= 7 */
7478 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7480 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7484 /*-----------------------------------------------------------------*/
7485 /* shiftLLong - shift left one long from left to result */
7486 /* offl = LSB or MSB16 */
7487 /*-----------------------------------------------------------------*/
7488 static void shiftLLong (operand *left, operand *result, int offr )
7491 int size = AOP_SIZE(result);
7494 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7495 if(size >= LSB+offr){
7496 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7498 pic14_emitcode("add","a,acc");
7499 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7500 size >= MSB16+offr && offr != LSB )
7501 pic14_emitcode("xch","a,%s",
7502 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7504 aopPut(AOP(result),"a",LSB+offr);
7507 if(size >= MSB16+offr){
7508 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7509 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7512 pic14_emitcode("rlc","a");
7513 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7514 size >= MSB24+offr && offr != LSB)
7515 pic14_emitcode("xch","a,%s",
7516 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7518 aopPut(AOP(result),"a",MSB16+offr);
7521 if(size >= MSB24+offr){
7522 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7523 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7526 pic14_emitcode("rlc","a");
7527 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7528 size >= MSB32+offr && offr != LSB )
7529 pic14_emitcode("xch","a,%s",
7530 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7532 aopPut(AOP(result),"a",MSB24+offr);
7535 if(size > MSB32+offr){
7536 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7537 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7540 pic14_emitcode("rlc","a");
7541 aopPut(AOP(result),"a",MSB32+offr);
7544 aopPut(AOP(result),zero,LSB);
7547 /*-----------------------------------------------------------------*/
7548 /* genlshFour - shift four byte by a known amount != 0 */
7549 /*-----------------------------------------------------------------*/
7550 static void genlshFour (operand *result, operand *left, int shCount)
7555 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7556 size = AOP_SIZE(result);
7558 /* if shifting more that 3 bytes */
7559 if (shCount >= 24 ) {
7562 /* lowest order of left goes to the highest
7563 order of the destination */
7564 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7566 movLeft2Result(left, LSB, result, MSB32);
7567 aopPut(AOP(result),zero,LSB);
7568 aopPut(AOP(result),zero,MSB16);
7569 aopPut(AOP(result),zero,MSB32);
7573 /* more than two bytes */
7574 else if ( shCount >= 16 ) {
7575 /* lower order two bytes goes to higher order two bytes */
7577 /* if some more remaining */
7579 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7581 movLeft2Result(left, MSB16, result, MSB32);
7582 movLeft2Result(left, LSB, result, MSB24);
7584 aopPut(AOP(result),zero,MSB16);
7585 aopPut(AOP(result),zero,LSB);
7589 /* if more than 1 byte */
7590 else if ( shCount >= 8 ) {
7591 /* lower order three bytes goes to higher order three bytes */
7595 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7597 movLeft2Result(left, LSB, result, MSB16);
7599 else{ /* size = 4 */
7601 movLeft2Result(left, MSB24, result, MSB32);
7602 movLeft2Result(left, MSB16, result, MSB24);
7603 movLeft2Result(left, LSB, result, MSB16);
7604 aopPut(AOP(result),zero,LSB);
7606 else if(shCount == 1)
7607 shiftLLong(left, result, MSB16);
7609 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7610 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7611 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7612 aopPut(AOP(result),zero,LSB);
7617 /* 1 <= shCount <= 7 */
7618 else if(shCount <= 2){
7619 shiftLLong(left, result, LSB);
7621 shiftLLong(result, result, LSB);
7623 /* 3 <= shCount <= 7, optimize */
7625 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7626 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7627 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7633 /*-----------------------------------------------------------------*/
7634 /* genLeftShiftLiteral - left shifting by known count */
7635 /*-----------------------------------------------------------------*/
7636 static void genLeftShiftLiteral (operand *left,
7641 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7645 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7646 freeAsmop(right,NULL,ic,TRUE);
7648 aopOp(left,ic,FALSE);
7649 aopOp(result,ic,FALSE);
7651 size = getSize(operandType(result));
7654 pic14_emitcode("; shift left ","result %d, left %d",size,
7658 /* I suppose that the left size >= result size */
7661 movLeft2Result(left, size, result, size);
7665 else if(shCount >= (size * 8))
7667 aopPut(AOP(result),zero,size);
7671 genlshOne (result,left,shCount);
7676 genlshTwo (result,left,shCount);
7680 genlshFour (result,left,shCount);
7684 freeAsmop(left,NULL,ic,TRUE);
7685 freeAsmop(result,NULL,ic,TRUE);
7689 /*-----------------------------------------------------------------*
7690 * genMultiAsm - repeat assembly instruction for size of register.
7691 * if endian == 1, then the high byte (i.e base address + size of
7692 * register) is used first else the low byte is used first;
7693 *-----------------------------------------------------------------*/
7694 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7700 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7713 emitpcode(poc, popGet(AOP(reg),offset));
7720 /*-----------------------------------------------------------------*/
7721 /* genLeftShift - generates code for left shifting */
7722 /*-----------------------------------------------------------------*/
7723 static void genLeftShift (iCode *ic)
7725 operand *left,*right, *result;
7727 unsigned long lit = 0L;
7729 symbol *tlbl , *tlbl1;
7733 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7735 right = IC_RIGHT(ic);
7737 result = IC_RESULT(ic);
7739 aopOp(right,ic,FALSE);
7740 aopOp(left,ic,FALSE);
7741 aopOp(result,ic,FALSE);
7744 /* if the shift count is known then do it
7745 as efficiently as possible */
7746 if (AOP_TYPE(right) == AOP_LIT) {
7747 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7751 /* shift count is unknown then we have to form
7752 a loop get the loop count in B : Note: we take
7753 only the lower order byte since shifting
7754 more that 32 bits make no sense anyway, ( the
7755 largest size of an object can be only 32 bits ) */
7757 /* this code fails for RIGHT == RESULT */
7758 assert (!pic14_sameRegs (AOP(right), AOP(result)));
7760 /* now move the left to the result if they are not the
7762 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
7763 AOP_SIZE(result) > 1) {
7765 size = AOP_SIZE(result);
7768 l = aopGet(AOP(left),offset,FALSE,TRUE);
7769 if (*l == '@' && (IS_AOP_PREG(result))) {
7771 pic14_emitcode("mov","a,%s",l);
7772 aopPut(AOP(result),"a",offset);
7774 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
7775 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7776 //aopPut(AOP(result),l,offset);
7782 if(AOP_TYPE(left) == AOP_LIT)
7783 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7785 size = AOP_SIZE(result);
7787 /* if it is only one byte then */
7789 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7790 emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7791 emitpcode(POC_ANDLW, popGetLit(0xf0));
7792 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7793 emitpcode(POC_MOVFW, popGet(AOP(left),0));
7794 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7795 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7796 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7797 emitpcode(POC_RLFW, popGet(AOP(result),0));
7798 emitpcode(POC_ANDLW, popGetLit(0xfe));
7799 emitpcode(POC_ADDFW, popGet(AOP(result),0));
7800 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7801 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7804 tlbl = newiTempLabel(NULL);
7805 if (!pic14_sameRegs(AOP(left),AOP(result))) {
7806 mov2w (AOP(left), 0);
7807 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7810 emitpcode(POC_COMFW, popGet(AOP(right),0));
7811 emitpcode(POC_RRF, popGet(AOP(result),0));
7812 emitpLabel(tlbl->key);
7813 emitpcode(POC_RLF, popGet(AOP(result),0));
7814 emitpcode(POC_ADDLW, popGetLit(1));
7816 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7821 if (pic14_sameRegs(AOP(left),AOP(result))) {
7823 tlbl = newiTempLabel(NULL);
7824 emitpcode(POC_COMFW, popGet(AOP(right),0));
7825 genMultiAsm(POC_RRF, result, size,1);
7826 emitpLabel(tlbl->key);
7827 genMultiAsm(POC_RLF, result, size,0);
7828 emitpcode(POC_ADDLW, popGetLit(1));
7830 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7834 //tlbl = newiTempLabel(NULL);
7836 //tlbl1 = newiTempLabel(NULL);
7838 //reAdjustPreg(AOP(result));
7840 //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7841 //pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7842 //l = aopGet(AOP(result),offset,FALSE,FALSE);
7844 //pic14_emitcode("add","a,acc");
7845 //aopPut(AOP(result),"a",offset++);
7847 // l = aopGet(AOP(result),offset,FALSE,FALSE);
7849 // pic14_emitcode("rlc","a");
7850 // aopPut(AOP(result),"a",offset++);
7852 //reAdjustPreg(AOP(result));
7854 //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7855 //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7858 tlbl = newiTempLabel(NULL);
7859 tlbl1= newiTempLabel(NULL);
7861 size = AOP_SIZE(result);
7864 pctemp = popGetTempReg(); /* grab a temporary working register. */
7866 emitpcode(POC_MOVFW, popGet(AOP(right),0));
7868 /* offset should be 0, 1 or 3 */
7869 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7871 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
7873 emitpcode(POC_MOVWF, pctemp);
7876 emitpLabel(tlbl->key);
7879 emitpcode(POC_RLF, popGet(AOP(result),0));
7881 emitpcode(POC_RLF, popGet(AOP(result),offset++));
7883 emitpcode(POC_DECFSZ, pctemp);
7884 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7885 emitpLabel(tlbl1->key);
7887 popReleaseTempReg(pctemp);
7891 freeAsmop (right,NULL,ic,TRUE);
7892 freeAsmop(left,NULL,ic,TRUE);
7893 freeAsmop(result,NULL,ic,TRUE);
7898 /*-----------------------------------------------------------------*/
7899 /* genrshOne - right shift a one byte quantity by known count */
7900 /*-----------------------------------------------------------------*/
7901 static void genrshOne (operand *result, operand *left,
7902 int shCount, int sign)
7905 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7906 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7909 /*-----------------------------------------------------------------*/
7910 /* genrshTwo - right shift two bytes by known amount != 0 */
7911 /*-----------------------------------------------------------------*/
7912 static void genrshTwo (operand *result,operand *left,
7913 int shCount, int sign)
7916 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7917 /* if shCount >= 8 */
7921 shiftR1Left2Result(left, MSB16, result, LSB,
7924 movLeft2Result(left, MSB16, result, LSB);
7926 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7929 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7930 emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7934 /* 1 <= shCount <= 7 */
7936 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
7939 /*-----------------------------------------------------------------*/
7940 /* shiftRLong - shift right one long from left to result */
7941 /* offl = LSB or MSB16 */
7942 /*-----------------------------------------------------------------*/
7943 static void shiftRLong (operand *left, int offl,
7944 operand *result, int sign)
7949 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7951 size = AOP_SIZE(left);
7952 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7955 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7959 assert (offl >= 0 && offl < size);
7961 same = pic14_sameRegs (AOP(left), AOP(result));
7963 /* perform the shift */
7966 if (same && !offl) {
7967 emitpcode (POC_RRF, popGet (AOP(result), size));
7969 emitpcode (POC_RRFW, popGet (AOP(left), size));
7970 emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7974 addSign (result, AOP_SIZE(left) - offl, sign);
7977 /*-----------------------------------------------------------------*/
7978 /* genrshFour - shift four byte by a known amount != 0 */
7979 /*-----------------------------------------------------------------*/
7980 static void genrshFour (operand *result, operand *left,
7981 int shCount, int sign)
7984 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7985 /* if shifting more that 3 bytes */
7986 if(shCount >= 24 ) {
7989 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7991 movLeft2Result(left, MSB32, result, LSB);
7993 addSign(result, MSB16, sign);
7995 else if(shCount >= 16){
7998 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8000 movLeft2Result(left, MSB24, result, LSB);
8001 movLeft2Result(left, MSB32, result, MSB16);
8003 addSign(result, MSB24, sign);
8005 else if(shCount >= 8){
8008 shiftRLong(left, MSB16, result, sign);
8009 else if(shCount == 0){
8010 movLeft2Result(left, MSB16, result, LSB);
8011 movLeft2Result(left, MSB24, result, MSB16);
8012 movLeft2Result(left, MSB32, result, MSB24);
8013 addSign(result, MSB32, sign);
8016 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8017 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8018 /* the last shift is signed */
8019 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8020 addSign(result, MSB32, sign);
8023 else{ /* 1 <= shCount <= 7 */
8025 shiftRLong(left, LSB, result, sign);
8027 shiftRLong(result, LSB, result, sign);
8030 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8031 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8032 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8037 /*-----------------------------------------------------------------*/
8038 /* genRightShiftLiteral - right shifting by known count */
8039 /*-----------------------------------------------------------------*/
8040 static void genRightShiftLiteral (operand *left,
8046 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8050 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8051 freeAsmop(right,NULL,ic,TRUE);
8053 aopOp(left,ic,FALSE);
8054 aopOp(result,ic,FALSE);
8057 pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8061 lsize = pic14_getDataSize(left);
8062 res_size = pic14_getDataSize(result);
8063 /* test the LEFT size !!! */
8065 /* I suppose that the left size >= result size */
8068 movLeft2Result(left, res_size, result, res_size);
8071 else if(shCount >= (lsize * 8)){
8074 emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8076 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8077 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8082 emitpcode(POC_MOVLW, popGetLit(0));
8083 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8084 emitpcode(POC_MOVLW, popGetLit(0xff));
8086 emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8091 emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8098 genrshOne (result,left,shCount,sign);
8102 genrshTwo (result,left,shCount,sign);
8106 genrshFour (result,left,shCount,sign);
8114 freeAsmop(left,NULL,ic,TRUE);
8115 freeAsmop(result,NULL,ic,TRUE);
8120 /*-----------------------------------------------------------------*/
8121 /* genSignedRightShift - right shift of signed number */
8122 /*-----------------------------------------------------------------*/
8123 static void genSignedRightShift (iCode *ic)
8125 operand *right, *left, *result;
8128 symbol *tlbl, *tlbl1 ;
8131 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8133 /* we do it the hard way put the shift count in b
8134 and loop thru preserving the sign */
8136 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8138 right = IC_RIGHT(ic);
8140 result = IC_RESULT(ic);
8142 aopOp(right,ic,FALSE);
8143 aopOp(left,ic,FALSE);
8144 aopOp(result,ic,FALSE);
8147 if ( AOP_TYPE(right) == AOP_LIT) {
8148 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8149 //genRightShiftLiteral (left,right,result,ic,1);
8152 /* shift count is unknown then we have to form
8153 a loop get the loop count in B : Note: we take
8154 only the lower order byte since shifting
8155 more that 32 bits make no sense anyway, ( the
8156 largest size of an object can be only 32 bits ) */
8158 //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8159 //pic14_emitcode("inc","b");
8160 //freeAsmop (right,NULL,ic,TRUE);
8161 //aopOp(left,ic,FALSE);
8162 //aopOp(result,ic,FALSE);
8164 /* now move the left to the result if they are not the
8166 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
8167 AOP_SIZE(result) > 1) {
8169 size = AOP_SIZE(result);
8173 l = aopGet(AOP(left),offset,FALSE,TRUE);
8174 if (*l == '@' && IS_AOP_PREG(result)) {
8175 pic14_emitcode("mov","a,%s",l);
8176 aopPut(AOP(result),"a",offset);
8178 aopPut(AOP(result),l,offset);
8180 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8181 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8187 /* mov the highest order bit to OVR */
8188 tlbl = newiTempLabel(NULL);
8189 tlbl1= newiTempLabel(NULL);
8191 size = AOP_SIZE(result);
8194 pctemp = popGetTempReg(); /* grab a temporary working register. */
8196 emitpcode(POC_MOVFW, popGet(AOP(right),0));
8198 /* offset should be 0, 1 or 3 */
8199 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8201 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8203 emitpcode(POC_MOVWF, pctemp);
8206 emitpLabel(tlbl->key);
8208 emitpcode(POC_RLFW, popGet(AOP(result),offset));
8209 emitpcode(POC_RRF, popGet(AOP(result),offset));
8212 emitpcode(POC_RRF, popGet(AOP(result),--offset));
8215 emitpcode(POC_DECFSZ, pctemp);
8216 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8217 emitpLabel(tlbl1->key);
8219 popReleaseTempReg(pctemp);
8221 size = AOP_SIZE(result);
8223 pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8224 pic14_emitcode("rlc","a");
8225 pic14_emitcode("mov","ov,c");
8226 /* if it is only one byte then */
8228 l = aopGet(AOP(left),0,FALSE,FALSE);
8230 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8231 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8232 pic14_emitcode("mov","c,ov");
8233 pic14_emitcode("rrc","a");
8234 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8235 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8236 aopPut(AOP(result),"a",0);
8240 reAdjustPreg(AOP(result));
8241 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8242 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8243 pic14_emitcode("mov","c,ov");
8245 l = aopGet(AOP(result),offset,FALSE,FALSE);
8247 pic14_emitcode("rrc","a");
8248 aopPut(AOP(result),"a",offset--);
8250 reAdjustPreg(AOP(result));
8251 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8252 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8257 freeAsmop(left,NULL,ic,TRUE);
8258 freeAsmop(result,NULL,ic,TRUE);
8259 freeAsmop(right,NULL,ic,TRUE);
8263 /*-----------------------------------------------------------------*/
8264 /* loadSignToC - load the operand's sign bit into CARRY */
8265 /*-----------------------------------------------------------------*/
8267 static void loadSignToC (operand *op)
8270 assert (op && AOP(op) && AOP_SIZE(op));
8273 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8277 /*-----------------------------------------------------------------*/
8278 /* genRightShift - generate code for right shifting */
8279 /*-----------------------------------------------------------------*/
8280 static void genGenericShift (iCode *ic, int shiftRight)
8282 operand *right, *left, *result;
8285 symbol *tlbl, *tlbl1, *inverselbl;
8288 /* if signed then we do it the hard way preserve the
8289 sign bit moving it inwards */
8290 retype = getSpec(operandType(IC_RESULT(ic)));
8291 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8293 /* signed & unsigned types are treated the same : i.e. the
8294 signed is NOT propagated inwards : quoting from the
8295 ANSI - standard : "for E1 >> E2, is equivalent to division
8296 by 2**E2 if unsigned or if it has a non-negative value,
8297 otherwise the result is implementation defined ", MY definition
8298 is that the sign does not get propagated */
8300 right = IC_RIGHT(ic);
8302 result = IC_RESULT(ic);
8304 aopOp(right,ic,FALSE);
8305 aopOp(left,ic,FALSE);
8306 aopOp(result,ic,FALSE);
8308 /* if the shift count is known then do it
8309 as efficiently as possible */
8310 if (AOP_TYPE(right) == AOP_LIT) {
8311 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8315 shiftRight = !shiftRight;
8319 shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8321 shiftLeft_Left2ResultLit (left, result, lit);
8322 //genRightShiftLiteral (left,right,result,ic, 0);
8326 /* shift count is unknown then we have to form
8327 a loop get the loop count in B : Note: we take
8328 only the lower order byte since shifting
8329 more that 32 bits make no sense anyway, ( the
8330 largest size of an object can be only 32 bits ) */
8332 /* we must not overwrite the shift counter */
8333 assert (!pic14_sameRegs(AOP(right),AOP(result)));
8335 /* now move the left to the result if they are not the
8337 if (!pic14_sameRegs(AOP(left),AOP(result)))
8339 size = min(AOP_SIZE(result), AOP_SIZE(left));
8341 mov2w(AOP(left), size);
8342 movwf(AOP(result), size);
8344 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8347 tlbl = newiTempLabel(NULL);
8348 tlbl1= newiTempLabel(NULL);
8350 size = AOP_SIZE(result);
8352 mov2w(AOP(right),0);
8353 if (!SPEC_USIGN(operandType(right)))
8355 inverselbl = newiTempLabel(NULL);
8356 /* signed shift count -- invert shift direction for c<0 */
8357 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8358 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8360 emitpcode(POC_SUBLW, popGetLit(0)); /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8361 /* check for `a = b >> c' with `-c == 0' */
8363 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8364 emitpLabel(tlbl->key);
8365 /* propagate the sign bit inwards for SIGNED result */
8366 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8367 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8368 emitpcode(POC_ADDLW, popGetLit(1)); /* clears CARRY (unless W==0 afterwards) */
8370 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8372 if (!SPEC_USIGN(operandType(right)))
8374 symbol *inv_loop = newiTempLabel(NULL);
8376 shiftRight = !shiftRight; /* invert shift direction */
8378 /* we came here from the code above -- we are done */
8379 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8381 /* emit code for shifting N<0 steps, count is already in W */
8382 emitpLabel(inverselbl->key);
8383 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8384 emitpLabel(inv_loop->key);
8385 /* propagate the sign bit inwards for SIGNED result */
8386 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8387 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8388 emitpcode(POC_ADDLW, popGetLit(1));
8390 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8393 emitpLabel(tlbl1->key);
8395 freeAsmop(left,NULL,ic,TRUE);
8396 freeAsmop (right,NULL,ic,TRUE);
8397 freeAsmop(result,NULL,ic,TRUE);
8400 static void genRightShift (iCode *ic)
8402 genGenericShift(ic, 1);
8405 static void genLeftShift (iCode *ic)
8407 genGenericShift(ic, 0);
8410 /*-----------------------------------------------------------------*/
8411 /* SetIrp - Set IRP bit */
8412 /*-----------------------------------------------------------------*/
8413 void SetIrp(operand *result) {
8415 if (AOP_TYPE(result) == AOP_LIT) {
8416 unsigned lit = (unsigned)operandLitValue(result);
8422 if (PCOP(AOP(result))->type == PO_LITERAL) {
8423 int addrs = PCOL(AOP(result))->lit;
8429 emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8430 if(AOP_SIZE(result) > 1) {
8431 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8439 setup_fsr (operand *ptr)
8442 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8444 /* also setup-up IRP */
8448 /*-----------------------------------------------------------------*/
8449 /* emitPtrByteGet - emits code to get a byte into WREG from an */
8450 /* arbitrary pointer (__code, __data, generic) */
8451 /*-----------------------------------------------------------------*/
8453 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8460 if (!alreadyAddressed) setup_fsr (src);
8461 emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8465 assert( AOP_SIZE(src) == 2 );
8467 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8469 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8470 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
8471 call_libraryfunc ("__gptrget1");
8475 assert( AOP_SIZE(src) == 3 );
8477 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8479 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8481 call_libraryfunc ("__gptrget1");
8485 assert( !"unhandled pointer type" );
8490 /*-----------------------------------------------------------------*/
8491 /* emitPtrByteSet - emits code to set a byte from src through a */
8492 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR). */
8493 /*-----------------------------------------------------------------*/
8495 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8502 if (!alreadyAddressed) setup_fsr (dst);
8503 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8507 assert( !"trying to assign to __code pointer" );
8511 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8513 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8515 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8517 call_libraryfunc ("__gptrput1");
8521 assert( !"unhandled pointer type" );
8526 /*-----------------------------------------------------------------*/
8527 /* genUnpackBits - generates code for unpacking bits */
8528 /*-----------------------------------------------------------------*/
8529 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8531 int rsize; /* result size */
8532 sym_link *etype; /* bitfield type information */
8533 int blen; /* bitfield length */
8534 int bstr; /* bitfield starting bit within byte */
8537 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8538 etype = getSpec(operandType(result));
8539 rsize = getSize (operandType (result));
8540 blen = SPEC_BLEN (etype);
8541 bstr = SPEC_BSTR (etype);
8543 /* single bit field case */
8545 if (ifx) { /* that is for an if statement */
8548 resolveIfx(&rIfx,ifx);
8549 if (ptype == -1) /* direct */
8550 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8552 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8553 emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8554 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8558 assert (!pic14_sameRegs (AOP(result), AOP(left)));
8559 for (i=0; i < AOP_SIZE(result); i++)
8560 emitpcode (POC_CLRF, popGet (AOP(result), i));
8565 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8566 /* adjust result below */
8573 emitPtrByteGet (left, ptype, FALSE);
8574 emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8576 /* adjust result below */
8580 assert( !"unhandled pointer type" );
8583 /* move sign-/zero extended bit to result */
8584 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8585 emitpcode (POC_INCF, popGet (AOP(result), 0));
8587 emitpcode (POC_DECF, popGet (AOP(result), 0));
8589 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8593 else if (blen <= 8 && ((blen + bstr) <= 8))
8598 for (i=0; i < AOP_SIZE(result); i++)
8599 emitpcode (POC_CLRF, popGet (AOP(result), i));
8604 mov2w(AOP(left), 0);
8611 emitPtrByteGet (left, ptype, FALSE);
8615 assert( !"unhandled pointer type" );
8619 emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8620 movwf(AOP(result), 0);
8621 AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8623 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8625 /* signed bitfield */
8626 assert (bstr + blen > 0);
8627 emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8628 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8629 emitpcode(POC_IORWF, popGet(AOP(result),0));
8631 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8635 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8639 /*-----------------------------------------------------------------*/
8640 /* genDataPointerGet - generates code when ptr offset is known */
8641 /*-----------------------------------------------------------------*/
8642 static void genDataPointerGet (operand *left,
8646 int size , offset = 0;
8649 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8652 /* optimization - most of the time, left and result are the same
8653 * address, but different types. for the pic code, we could omit
8656 aopOp(result,ic,TRUE);
8658 if (pic14_sameRegs (AOP(left), AOP(result)))
8661 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8663 //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8665 size = AOP_SIZE(result);
8666 if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8670 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8671 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8675 freeAsmop(left,NULL,ic,TRUE);
8676 freeAsmop(result,NULL,ic,TRUE);
8680 /*-----------------------------------------------------------------*/
8681 /* genNearPointerGet - pic14_emitcode for near pointer fetch */
8682 /*-----------------------------------------------------------------*/
8683 static void genNearPointerGet (operand *left,
8688 sym_link *ltype = operandType(left);
8689 sym_link *rtype = operandType(result);
8690 sym_link *retype= getSpec(rtype); /* bitfield type information */
8694 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8697 aopOp(left,ic,FALSE);
8699 /* if left is rematerialisable and
8700 result is not bit variable type and
8701 the left is pointer to data space i.e
8702 lower 128 bytes of space */
8703 if (AOP_TYPE(left) == AOP_PCODE && //AOP_TYPE(left) == AOP_IMMD &&
8704 !IS_BITVAR(retype) &&
8705 PIC_IS_DATA_PTR(ltype)) {
8706 genDataPointerGet (left,result,ic);
8710 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8711 aopOp (result,ic,FALSE);
8713 /* Check if can access directly instead of via a pointer */
8714 if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8715 && AOP_SIZE(result) == 1)
8720 if (IS_BITFIELD(getSpec(operandType(result))))
8722 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8726 /* If the pointer value is not in a the FSR then need to put it in */
8727 /* Must set/reset IRP bit for use with FSR. */
8732 /* if bitfield then unpack the bits */
8734 /* we have can just get the values */
8735 int size = AOP_SIZE(result);
8738 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8742 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8744 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8745 if (AOP_TYPE(result) == AOP_LIT) {
8746 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8748 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8750 if (size && !direct)
8751 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8756 /* now some housekeeping stuff */
8758 /* we had to allocate for this iCode */
8759 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8760 freeAsmop(NULL,aop,ic,TRUE);
8762 /* we did not allocate which means left
8763 already in a pointer register, then
8764 if size > 0 && this could be used again
8765 we have to point it back to where it
8767 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8768 if (AOP_SIZE(result) > 1 &&
8769 !OP_SYMBOL(left)->remat &&
8770 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8772 int size = AOP_SIZE(result) - 1;
8774 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8780 freeAsmop(left,NULL,ic,TRUE);
8781 freeAsmop(result,NULL,ic,TRUE);
8786 /*-----------------------------------------------------------------*/
8787 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch */
8788 /*-----------------------------------------------------------------*/
8789 static void genPagedPointerGet (operand *left,
8796 sym_link *rtype, *retype;
8799 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8801 rtype = operandType(result);
8802 retype= getSpec(rtype);
8804 aopOp(left,ic,FALSE);
8806 /* if the value is already in a pointer register
8807 then don't need anything more */
8808 if (!AOP_INPREG(AOP(left))) {
8809 /* otherwise get a free pointer register */
8811 preg = getFreePtr(ic,&aop,FALSE);
8812 pic14_emitcode("mov","%s,%s",
8814 aopGet(AOP(left),0,FALSE,TRUE));
8815 rname = preg->name ;
8817 rname = aopGet(AOP(left),0,FALSE,FALSE);
8819 freeAsmop(left,NULL,ic,TRUE);
8820 aopOp (result,ic,FALSE);
8822 /* if bitfield then unpack the bits */
8823 if (IS_BITFIELD(retype))
8824 genUnpackBits (result,left,rname,PPOINTER,0);
8826 /* we have can just get the values */
8827 int size = AOP_SIZE(result);
8832 pic14_emitcode("movx","a,@%s",rname);
8833 aopPut(AOP(result),"a",offset);
8838 pic14_emitcode("inc","%s",rname);
8842 /* now some housekeeping stuff */
8844 /* we had to allocate for this iCode */
8845 freeAsmop(NULL,aop,ic,TRUE);
8847 /* we did not allocate which means left
8848 already in a pointer register, then
8849 if size > 0 && this could be used again
8850 we have to point it back to where it
8852 if (AOP_SIZE(result) > 1 &&
8853 !OP_SYMBOL(left)->remat &&
8854 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8856 int size = AOP_SIZE(result) - 1;
8858 pic14_emitcode("dec","%s",rname);
8863 freeAsmop(result,NULL,ic,TRUE);
8868 /*-----------------------------------------------------------------*/
8869 /* genFarPointerGet - gget value from far space */
8870 /*-----------------------------------------------------------------*/
8871 static void genFarPointerGet (operand *left,
8872 operand *result, iCode *ic)
8875 sym_link *retype = getSpec(operandType(result));
8878 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8880 aopOp(left,ic,FALSE);
8882 /* if the operand is already in dptr
8883 then we do nothing else we move the value to dptr */
8884 if (AOP_TYPE(left) != AOP_STR) {
8885 /* if this is remateriazable */
8886 if (AOP_TYPE(left) == AOP_IMMD)
8887 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8888 else { /* we need to get it byte by byte */
8889 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8890 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8891 if (options.model == MODEL_FLAT24)
8893 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8897 /* so dptr know contains the address */
8898 freeAsmop(left,NULL,ic,TRUE);
8899 aopOp(result,ic,FALSE);
8901 /* if bit then unpack */
8902 if (IS_BITFIELD(retype))
8903 genUnpackBits(result,left,"dptr",FPOINTER,0);
8905 size = AOP_SIZE(result);
8909 pic14_emitcode("movx","a,@dptr");
8910 aopPut(AOP(result),"a",offset++);
8912 pic14_emitcode("inc","dptr");
8916 freeAsmop(result,NULL,ic,TRUE);
8921 /*-----------------------------------------------------------------*/
8922 /* genCodePointerGet - get value from code space */
8923 /*-----------------------------------------------------------------*/
8924 static void genCodePointerGet (operand *left,
8925 operand *result, iCode *ic)
8928 sym_link *retype = getSpec(operandType(result));
8930 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8932 aopOp(left,ic,FALSE);
8934 /* if the operand is already in dptr
8935 then we do nothing else we move the value to dptr */
8936 if (AOP_TYPE(left) != AOP_STR) {
8937 /* if this is remateriazable */
8938 if (AOP_TYPE(left) == AOP_IMMD)
8939 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8940 else { /* we need to get it byte by byte */
8941 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8942 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8943 if (options.model == MODEL_FLAT24)
8945 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8949 /* so dptr know contains the address */
8950 freeAsmop(left,NULL,ic,TRUE);
8951 aopOp(result,ic,FALSE);
8953 /* if bit then unpack */
8954 if (IS_BITFIELD(retype))
8955 genUnpackBits(result,left,"dptr",CPOINTER,0);
8957 size = AOP_SIZE(result);
8961 pic14_emitcode("clr","a");
8962 pic14_emitcode("movc","a,@a+dptr");
8963 aopPut(AOP(result),"a",offset++);
8965 pic14_emitcode("inc","dptr");
8969 freeAsmop(result,NULL,ic,TRUE);
8972 /*-----------------------------------------------------------------*/
8973 /* genGenPointerGet - gget value from generic pointer space */
8974 /*-----------------------------------------------------------------*/
8975 static void genGenPointerGet (operand *left,
8976 operand *result, iCode *ic)
8979 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8980 aopOp(left,ic,FALSE);
8981 aopOp(result,ic,FALSE);
8984 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8986 if (IS_BITFIELD(getSpec(operandType(result))))
8988 genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
8993 /* emit call to __gptrget */
8994 char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
8995 int size = AOP_SIZE(result);
8998 assert (size > 0 && size <= 4);
9000 /* pass arguments */
9001 assert (AOP_SIZE(left) == 3);
9002 mov2w(AOP(left), 0);
9003 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9004 mov2w(AOP(left), 1);
9005 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9006 mov2w(AOP(left), 2);
9007 call_libraryfunc (func[size]);
9010 movwf (AOP(result), --size);
9012 emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
9013 movwf (AOP(result), size);
9017 freeAsmop(left,NULL,ic,TRUE);
9018 freeAsmop(result,NULL,ic,TRUE);
9022 /*-----------------------------------------------------------------*/
9023 /* genConstPointerGet - get value from const generic pointer space */
9024 /*-----------------------------------------------------------------*/
9025 static void genConstPointerGet (operand *left,
9026 operand *result, iCode *ic)
9028 //sym_link *retype = getSpec(operandType(result));
9030 symbol *albl, *blbl;//, *clbl;
9037 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9038 aopOp(left,ic,FALSE);
9039 aopOp(result,ic,FALSE);
9041 size = AOP_SIZE(result);
9043 DEBUGpic14_AopType(__LINE__,left,NULL,result);
9045 DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
9047 lit = op_isLitLike (left);
9048 poc = lit ? POC_MOVLW : POC_MOVFW;
9050 if (IS_BITFIELD(getSpec(operandType(result))))
9052 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
9057 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
9058 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
9059 assert (size > 0 && size <= 4);
9062 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9064 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9065 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
9066 call_libraryfunc (func[size]);
9068 movwf(AOP(result),size-1);
9069 for (i = 1; i < size; i++)
9071 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
9072 movwf(AOP(result),size - 1 - i);
9077 freeAsmop(left,NULL,ic,TRUE);
9078 freeAsmop(result,NULL,ic,TRUE);
9081 /*-----------------------------------------------------------------*/
9082 /* genPointerGet - generate code for pointer get */
9083 /*-----------------------------------------------------------------*/
9084 static void genPointerGet (iCode *ic)
9086 operand *left, *result ;
9087 sym_link *type, *etype;
9091 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9094 result = IC_RESULT(ic) ;
9096 /* depending on the type of pointer we need to
9097 move it to the correct pointer register */
9098 type = operandType(left);
9099 etype = getSpec(type);
9101 if (IS_PTR_CONST(type))
9102 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9104 /* if left is of type of pointer then it is simple */
9105 if (IS_PTR(type) && !IS_FUNC(type->next))
9106 p_type = DCL_TYPE(type);
9108 /* we have to go by the storage class */
9109 p_type = PTR_TYPE(SPEC_OCLS(etype));
9111 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9113 if (SPEC_OCLS(etype)->codesp ) {
9114 DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9115 //p_type = CPOINTER ;
9118 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9119 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9120 /*p_type = FPOINTER ;*/
9122 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9123 DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9124 /* p_type = PPOINTER; */
9126 if (SPEC_OCLS(etype) == idata )
9127 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9128 /* p_type = IPOINTER; */
9130 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9131 /* p_type = POINTER ; */
9134 /* now that we have the pointer type we assign
9135 the pointer values */
9141 genNearPointerGet (left,result,ic);
9145 genPagedPointerGet(left,result,ic);
9149 genFarPointerGet (left,result,ic);
9153 genConstPointerGet (left,result,ic);
9157 genGenPointerGet (left,result,ic);
9160 assert ( !"unhandled pointer type" );
9166 /*-----------------------------------------------------------------*/
9167 /* genPackBits - generates code for packed bit storage */
9168 /*-----------------------------------------------------------------*/
9169 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9171 int blen; /* bitfield length */
9172 int bstr; /* bitfield starting bit within byte */
9173 int litval; /* source literal value (if AOP_LIT) */
9174 unsigned char mask; /* bitmask within current byte */
9177 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9179 blen = SPEC_BLEN (etype);
9180 bstr = SPEC_BSTR (etype);
9182 /* If the bitfield length is less than a byte and does not cross byte boundaries */
9183 if ((blen <= 8) && ((bstr + blen) <= 8))
9185 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9186 (unsigned char) (0xFF >> (8 - bstr)));
9188 if (AOP_TYPE (right) == AOP_LIT)
9190 /* Case with a bitfield length <8 and literal source */
9191 int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9198 if (AOP(result)->type == AOP_PCODE)
9199 pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9201 pcop = popGet(AOP(result),0);
9202 emitpcode(lit?POC_BSF:POC_BCF,pcop);
9208 emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9212 assert( !"trying to assign to bitfield via pointer to __code space" );
9216 emitPtrByteGet(result, p_type, FALSE);
9218 emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9220 emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9222 emitPtrByteSet(result, p_type, TRUE);
9226 assert( !"unhandled pointer type" );
9228 } // switch (p_type)
9231 litval = lit << bstr;
9232 litval &= (~mask) & 0x00ff;
9237 mov2w (AOP(result), 0);
9238 if ((litval|mask) != 0x00ff)
9239 emitpcode(POC_ANDLW, popGetLit (mask));
9241 emitpcode(POC_IORLW, popGetLit (litval));
9242 movwf (AOP(result), 0);
9248 emitPtrByteGet(result, p_type, FALSE);
9249 if ((litval|mask) != 0x00ff)
9250 emitpcode(POC_ANDLW, popGetLit (mask));
9252 emitpcode(POC_IORLW, popGetLit (litval));
9253 emitPtrByteSet(result, p_type, TRUE);
9257 assert( !"trying to assign to bitfield via pointer to __code space" );
9261 assert( !"unhandled pointer type" );
9268 /* right is no literal */
9273 /* Note more efficient code, of pre clearing bit then only setting it if required,
9274 * can only be done if it is known that the result is not a SFR */
9275 emitpcode(POC_RRFW,popGet(AOP(right),0));
9277 emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9279 emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9285 emitPtrByteGet (result, p_type, FALSE);
9286 emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9287 emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9288 emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9289 emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9290 emitPtrByteSet (result, p_type, TRUE);
9294 assert( !"trying to assign to bitfield via pointer to __code space" );
9298 assert( !"unhandled pointer type" );
9303 /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9304 pCodeOp *temp = popGetTempReg ();
9306 mov2w (AOP(right), 0);
9308 emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9310 emitpcode(POC_MOVWF, temp);
9312 AccLsh (temp, bstr);
9318 mov2w (AOP(result), 0);
9319 emitpcode(POC_ANDLW, popGetLit (mask));
9320 emitpcode(POC_IORFW, temp);
9321 movwf (AOP(result), 0);
9327 emitPtrByteGet (result, p_type, FALSE);
9328 emitpcode(POC_ANDLW, popGetLit (mask));
9329 emitpcode(POC_IORFW, temp);
9330 emitPtrByteSet (result, p_type, TRUE);
9334 assert( !"trying to assign to bitfield via pointer to __code space" );
9338 assert( !"unhandled pointer type" );
9342 popReleaseTempReg (temp);
9344 } // if (AOP(right)->type != AOP_LIT)
9346 } // if (blen <= 8 && ((blen + bstr) <= 8))
9348 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9352 bitpatternFromVal (value *val)
9359 assert (sizeof (float) == sizeof (long));
9361 //fprintf (stderr, "%s:%u(%s): val=%lf, type: %d, etype: %d\n", __FILE__, __LINE__, __FUNCTION__, floatFromVal(val), SPEC_NOUN(val->type), SPEC_NOUN(val->etype));
9363 switch (SPEC_NOUN(val->type))
9367 return (unsigned long)floatFromVal (val);
9371 float_long.d = floatFromVal (val);
9372 return float_long.l;
9375 assert( !"unhandled value type" );
9379 float_long.d = floatFromVal (val);
9380 return float_long.l;
9383 /*-----------------------------------------------------------------*/
9384 /* genDataPointerSet - remat pointer to data space */
9385 /*-----------------------------------------------------------------*/
9386 static void genDataPointerSet(operand *right,
9390 int size, offset = 0 ;
9394 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9395 aopOp(right,ic,FALSE);
9396 aopOp(result,ic,FALSE);
9398 assert (IS_SYMOP(result));
9399 assert (IS_PTR(OP_SYM_TYPE(result)));
9401 size = AOP_SIZE(right);
9402 ressize = getSize(OP_SYM_ETYPE(result));
9403 if (size > ressize) size = ressize;
9404 //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9406 //assert( !"what's going on here?" );
9409 if ( AOP_TYPE(result) == AOP_PCODE) {
9410 fprintf(stderr,"genDataPointerSet %s, %d\n",
9411 AOP(result)->aopu.pcop->name,
9412 PCOI(AOP(result)->aopu.pcop)->offset);
9416 // tsd, was l+1 - the underline `_' prefix was being stripped
9418 emitpComment ("%s:%u: size=%d/%d, offset=%i", __FILE__,__LINE__, size, ressize, offset);
9420 if (AOP_TYPE(right) == AOP_LIT) {
9421 /* XXX: might be float... */
9422 unsigned int lit = bitpatternFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9423 lit = lit >> (8*offset);
9424 //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9426 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9427 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9429 emitpcode(POC_CLRF, popGet(AOP(result),offset));
9432 //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9433 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9434 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9440 freeAsmop(right,NULL,ic,TRUE);
9441 freeAsmop(result,NULL,ic,TRUE);
9444 /*-----------------------------------------------------------------*/
9445 /* genNearPointerSet - pic14_emitcode for near pointer put */
9446 /*-----------------------------------------------------------------*/
9447 static void genNearPointerSet (operand *right,
9452 sym_link *ptype = operandType(result);
9453 sym_link *retype = getSpec(operandType(right));
9454 sym_link *letype = getSpec(ptype);
9459 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9460 aopOp(result,ic,FALSE);
9463 /* if the result is rematerializable &
9464 in data space & not a bit variable */
9465 //if (AOP_TYPE(result) == AOP_IMMD &&
9466 if (AOP_TYPE(result) == AOP_PCODE &&
9467 PIC_IS_DATA_PTR(ptype) &&
9468 !IS_BITVAR (retype) &&
9469 !IS_BITVAR (letype)) {
9470 genDataPointerSet (right,result,ic);
9471 freeAsmop(result,NULL,ic,TRUE);
9476 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9477 aopOp(right,ic,FALSE);
9478 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9480 /* Check if can access directly instead of via a pointer */
9481 if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9485 if (IS_BITFIELD (letype))
9487 genPackBits (letype, result, right, direct?-1:POINTER);
9491 /* If the pointer value is not in a the FSR then need to put it in */
9492 /* Must set/reset IRP bit for use with FSR. */
9493 /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9498 /* we have can just get the values */
9499 int size = AOP_SIZE(right);
9502 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9504 char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9506 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9508 if (AOP_TYPE(right) == AOP_LIT) {
9509 emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9511 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9514 emitpcode(POC_MOVWF,popGet(AOP(result),0));
9516 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9518 if (size && !direct)
9519 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9524 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9525 /* now some housekeeping stuff */
9527 /* we had to allocate for this iCode */
9528 freeAsmop(NULL,aop,ic,TRUE);
9530 /* we did not allocate which means left
9531 already in a pointer register, then
9532 if size > 0 && this could be used again
9533 we have to point it back to where it
9535 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9536 if (AOP_SIZE(right) > 1 &&
9537 !OP_SYMBOL(result)->remat &&
9538 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9540 int size = AOP_SIZE(right) - 1;
9542 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9546 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9549 freeAsmop(right,NULL,ic,TRUE);
9550 freeAsmop(result,NULL,ic,TRUE);
9554 /*-----------------------------------------------------------------*/
9555 /* genPagedPointerSet - pic14_emitcode for Paged pointer put */
9556 /*-----------------------------------------------------------------*/
9557 static void genPagedPointerSet (operand *right,
9567 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9569 retype= getSpec(operandType(right));
9571 aopOp(result,ic,FALSE);
9573 /* if the value is already in a pointer register
9574 then don't need anything more */
9575 if (!AOP_INPREG(AOP(result))) {
9576 /* otherwise get a free pointer register */
9578 preg = getFreePtr(ic,&aop,FALSE);
9579 pic14_emitcode("mov","%s,%s",
9581 aopGet(AOP(result),0,FALSE,TRUE));
9582 rname = preg->name ;
9584 rname = aopGet(AOP(result),0,FALSE,FALSE);
9586 freeAsmop(result,NULL,ic,TRUE);
9587 aopOp (right,ic,FALSE);
9589 /* if bitfield then unpack the bits */
9590 if (IS_BITFIELD(retype))
9591 genPackBits (retype,result,right,rname,PPOINTER);
9593 /* we have can just get the values */
9594 int size = AOP_SIZE(right);
9598 l = aopGet(AOP(right),offset,FALSE,TRUE);
9601 pic14_emitcode("movx","@%s,a",rname);
9604 pic14_emitcode("inc","%s",rname);
9610 /* now some housekeeping stuff */
9612 /* we had to allocate for this iCode */
9613 freeAsmop(NULL,aop,ic,TRUE);
9615 /* we did not allocate which means left
9616 already in a pointer register, then
9617 if size > 0 && this could be used again
9618 we have to point it back to where it
9620 if (AOP_SIZE(right) > 1 &&
9621 !OP_SYMBOL(result)->remat &&
9622 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9624 int size = AOP_SIZE(right) - 1;
9626 pic14_emitcode("dec","%s",rname);
9631 freeAsmop(right,NULL,ic,TRUE);
9636 /*-----------------------------------------------------------------*/
9637 /* genFarPointerSet - set value from far space */
9638 /*-----------------------------------------------------------------*/
9639 static void genFarPointerSet (operand *right,
9640 operand *result, iCode *ic)
9643 sym_link *retype = getSpec(operandType(right));
9646 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9647 aopOp(result,ic,FALSE);
9649 /* if the operand is already in dptr
9650 then we do nothing else we move the value to dptr */
9651 if (AOP_TYPE(result) != AOP_STR) {
9652 /* if this is remateriazable */
9653 if (AOP_TYPE(result) == AOP_IMMD)
9654 pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9655 else { /* we need to get it byte by byte */
9656 pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9657 pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9658 if (options.model == MODEL_FLAT24)
9660 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9664 /* so dptr know contains the address */
9665 freeAsmop(result,NULL,ic,TRUE);
9666 aopOp(right,ic,FALSE);
9668 /* if bit then unpack */
9669 if (IS_BITFIELD(retype))
9670 genPackBits(retype,result,right,"dptr",FPOINTER);
9672 size = AOP_SIZE(right);
9676 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9678 pic14_emitcode("movx","@dptr,a");
9680 pic14_emitcode("inc","dptr");
9684 freeAsmop(right,NULL,ic,TRUE);
9688 /*-----------------------------------------------------------------*/
9689 /* genGenPointerSet - set value from generic pointer space */
9690 /*-----------------------------------------------------------------*/
9691 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9693 sym_link *retype = getSpec(operandType(result));
9696 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9697 aopOp(right,ic,FALSE);
9698 aopOp(result,ic,FALSE);
9701 DEBUGpic14_AopType(__LINE__,right,NULL,result);
9703 if (IS_BITFIELD(retype))
9705 genPackBits (retype, result, right, GPOINTER);
9710 /* emit call to __gptrput */
9711 char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9712 int size = AOP_SIZE(right);
9715 assert (size == getSize(OP_SYM_ETYPE(result)));
9716 assert (size > 0 && size <= 4);
9718 /* pass arguments */
9719 /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9725 mov2w_op (right, off);
9726 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9731 assert (AOP_SIZE(result) == 3);
9732 mov2w(AOP(result), 0);
9733 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9734 mov2w(AOP(result), 1);
9735 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9736 mov2w(AOP(result), 2);
9737 call_libraryfunc (func[size]);
9740 freeAsmop(right,NULL,ic,TRUE);
9741 freeAsmop(result,NULL,ic,TRUE);
9744 /*-----------------------------------------------------------------*/
9745 /* genPointerSet - stores the value into a pointer location */
9746 /*-----------------------------------------------------------------*/
9747 static void genPointerSet (iCode *ic)
9749 operand *right, *result ;
9750 sym_link *type, *etype;
9754 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9756 right = IC_RIGHT(ic);
9757 result = IC_RESULT(ic) ;
9759 /* depending on the type of pointer we need to
9760 move it to the correct pointer register */
9761 type = operandType(result);
9762 etype = getSpec(type);
9763 /* if left is of type of pointer then it is simple */
9764 if (IS_PTR(type) && !IS_FUNC(type->next)) {
9765 p_type = DCL_TYPE(type);
9768 /* we have to go by the storage class */
9769 p_type = PTR_TYPE(SPEC_OCLS(etype));
9771 /* if (SPEC_OCLS(etype)->codesp ) { */
9772 /* p_type = CPOINTER ; */
9775 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9776 /* p_type = FPOINTER ; */
9778 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9779 /* p_type = PPOINTER ; */
9781 /* if (SPEC_OCLS(etype) == idata ) */
9782 /* p_type = IPOINTER ; */
9784 /* p_type = POINTER ; */
9787 /* now that we have the pointer type we assign
9788 the pointer values */
9794 genNearPointerSet (right,result,ic);
9798 genPagedPointerSet (right,result,ic);
9802 genFarPointerSet (right,result,ic);
9806 genGenPointerSet (right,result,ic);
9810 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9811 "genPointerSet: illegal pointer type");
9815 /*-----------------------------------------------------------------*/
9816 /* genIfx - generate code for Ifx statement */
9817 /*-----------------------------------------------------------------*/
9818 static void genIfx (iCode *ic, iCode *popIc)
9820 operand *cond = IC_COND(ic);
9824 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9826 aopOp(cond,ic,FALSE);
9828 /* get the value into acc */
9829 if (AOP_TYPE(cond) != AOP_CRY)
9830 pic14_toBoolean(cond);
9834 /* if there was something to be popped then do it */
9840 /* This assumes that CARRY is set iff cond is true */
9843 assert (!IC_FALSE(ic));
9844 emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
9846 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9848 assert (IC_FALSE(ic));
9849 emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
9851 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9855 static int hasWarned = 0;
9858 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
9865 /* now Z is set iff !cond */
9868 assert (!IC_FALSE(ic));
9870 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9873 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9879 /* the result is now in the accumulator */
9880 freeAsmop(cond,NULL,ic,TRUE);
9883 /*-----------------------------------------------------------------*/
9884 /* genAddrOf - generates code for address of */
9885 /*-----------------------------------------------------------------*/
9886 static void genAddrOf (iCode *ic)
9888 operand *right, *result, *left;
9892 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9895 //aopOp(IC_RESULT(ic),ic,FALSE);
9897 aopOp((left=IC_LEFT(ic)),ic,FALSE);
9898 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9899 aopOp((result=IC_RESULT(ic)),ic,TRUE);
9901 DEBUGpic14_AopType(__LINE__,left,right,result);
9902 assert (IS_SYMOP (left));
9904 /* sanity check: generic pointers to code space are not yet supported,
9905 * pionters to codespace must not be assigned addresses of __data values. */
9907 fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9908 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)));
9909 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)));
9910 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)));
9911 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)));
9914 if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9915 fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9916 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9917 OP_SYMBOL(left)->name);
9918 } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9919 fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9920 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9921 OP_SYMBOL(left)->name);
9924 size = AOP_SIZE(IC_RESULT(ic));
9925 if (IS_GENPTR(OP_SYM_TYPE(result))) {
9927 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9932 /* fixing bug #863624, reported from (errolv) */
9933 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9934 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9937 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9938 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9943 if (IS_GENPTR(OP_SYM_TYPE(result)))
9945 /* provide correct tag */
9946 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9947 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9948 movwf (AOP(result), 2);
9951 freeAsmop(left,NULL,ic,FALSE);
9952 freeAsmop(result,NULL,ic,TRUE);
9957 /*-----------------------------------------------------------------*/
9958 /* genFarFarAssign - assignment when both are in far space */
9959 /*-----------------------------------------------------------------*/
9960 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9962 int size = AOP_SIZE(right);
9965 /* first push the right side on to the stack */
9967 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9969 pic14_emitcode ("push","acc");
9972 freeAsmop(right,NULL,ic,FALSE);
9973 /* now assign DPTR to result */
9974 aopOp(result,ic,FALSE);
9975 size = AOP_SIZE(result);
9977 pic14_emitcode ("pop","acc");
9978 aopPut(AOP(result),"a",--offset);
9980 freeAsmop(result,NULL,ic,FALSE);
9985 /*-----------------------------------------------------------------*/
9986 /* genAssign - generate code for assignment */
9987 /*-----------------------------------------------------------------*/
9988 static void genAssign (iCode *ic)
9990 operand *result, *right;
9991 int size, offset,know_W;
9992 unsigned long lit = 0L;
9994 result = IC_RESULT(ic);
9995 right = IC_RIGHT(ic) ;
9998 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10000 /* if they are the same */
10001 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10004 aopOp(right,ic,FALSE);
10005 aopOp(result,ic,TRUE);
10007 DEBUGpic14_AopType(__LINE__,NULL,right,result);
10009 /* if they are the same registers */
10010 if (pic14_sameRegs(AOP(right),AOP(result)))
10013 /* special case: assign from __code */
10014 if (!IS_ITEMP(right) /* --> iTemps never reside in __code */
10015 && IS_SYMOP (right) /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
10016 && !IS_FUNC(OP_SYM_TYPE(right)) /* --> we would want its address instead of the first instruction */
10017 && !IS_CODEPTR(OP_SYM_TYPE(right)) /* --> get symbols address instread */
10018 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
10020 emitpComment ("genAssign from CODESPACE");
10021 genConstPointerGet (right, result, ic);
10025 /* just for symmetry reasons... */
10026 if (!IS_ITEMP(result)
10027 && IS_SYMOP (result)
10028 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
10030 assert ( !"cannot write to CODESPACE" );
10033 /* if the result is a bit */
10034 if (AOP_TYPE(result) == AOP_CRY) {
10036 /* if the right size is a literal then
10037 we know what the value is */
10038 if (AOP_TYPE(right) == AOP_LIT) {
10040 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10041 popGet(AOP(result),0));
10043 if (((int) operandLitValue(right)))
10044 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10045 AOP(result)->aopu.aop_dir,
10046 AOP(result)->aopu.aop_dir);
10048 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10049 AOP(result)->aopu.aop_dir,
10050 AOP(result)->aopu.aop_dir);
10054 /* the right is also a bit variable */
10055 if (AOP_TYPE(right) == AOP_CRY) {
10056 emitpcode(POC_BCF, popGet(AOP(result),0));
10057 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10058 emitpcode(POC_BSF, popGet(AOP(result),0));
10060 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10061 AOP(result)->aopu.aop_dir,
10062 AOP(result)->aopu.aop_dir);
10063 pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
10064 AOP(right)->aopu.aop_dir,
10065 AOP(right)->aopu.aop_dir);
10066 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10067 AOP(result)->aopu.aop_dir,
10068 AOP(result)->aopu.aop_dir);
10072 /* we need to or */
10073 emitpcode(POC_BCF, popGet(AOP(result),0));
10074 pic14_toBoolean(right);
10076 emitpcode(POC_BSF, popGet(AOP(result),0));
10077 //aopPut(AOP(result),"a",0);
10081 /* bit variables done */
10083 size = AOP_SIZE(result);
10085 if(AOP_TYPE(right) == AOP_LIT)
10086 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10088 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
10089 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10090 if(aopIdx(AOP(result),0) == 4) {
10091 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10092 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10093 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10096 DEBUGpic14_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
10101 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10102 if(AOP_TYPE(right) == AOP_LIT) {
10104 if(know_W != (int)(lit&0xff))
10105 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10107 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10109 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10113 } else if (AOP_TYPE(right) == AOP_CRY) {
10114 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10116 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10117 emitpcode(POC_INCF, popGet(AOP(result),0));
10120 mov2w_op (right, offset);
10121 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10129 freeAsmop (right,NULL,ic,FALSE);
10130 freeAsmop (result,NULL,ic,TRUE);
10133 /*-----------------------------------------------------------------*/
10134 /* genJumpTab - genrates code for jump table */
10135 /*-----------------------------------------------------------------*/
10136 static void genJumpTab (iCode *ic)
10142 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10144 aopOp(IC_JTCOND(ic),ic,FALSE);
10145 /* get the condition into accumulator */
10146 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10148 /* multiply by three */
10149 pic14_emitcode("add","a,acc");
10150 pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10152 jtab = newiTempLabel(NULL);
10153 pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10154 pic14_emitcode("jmp","@a+dptr");
10155 pic14_emitcode("","%05d_DS_:",jtab->key+100);
10157 emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10158 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10159 emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10160 emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10162 emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10163 emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10164 emitpLabel(jtab->key);
10166 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10168 /* now generate the jump labels */
10169 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10170 jtab = setNextItem(IC_JTLABELS(ic))) {
10171 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10172 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10178 /*-----------------------------------------------------------------*/
10179 /* genMixedOperation - gen code for operators between mixed types */
10180 /*-----------------------------------------------------------------*/
10182 TSD - Written for the PIC port - but this unfortunately is buggy.
10183 This routine is good in that it is able to efficiently promote
10184 types to different (larger) sizes. Unfortunately, the temporary
10185 variables that are optimized out by this routine are sometimes
10186 used in other places. So until I know how to really parse the
10187 iCode tree, I'm going to not be using this routine :(.
10189 static int genMixedOperation (iCode *ic)
10193 operand *result = IC_RESULT(ic);
10194 sym_link *ctype = operandType(IC_LEFT(ic));
10195 operand *right = IC_RIGHT(ic);
10201 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10203 pic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10209 nextright = IC_RIGHT(nextic);
10210 nextleft = IC_LEFT(nextic);
10211 nextresult = IC_RESULT(nextic);
10213 aopOp(right,ic,FALSE);
10214 aopOp(result,ic,FALSE);
10215 aopOp(nextright, nextic, FALSE);
10216 aopOp(nextleft, nextic, FALSE);
10217 aopOp(nextresult, nextic, FALSE);
10219 if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10221 operand *t = right;
10225 pic14_emitcode(";remove right +","");
10227 } else if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10229 operand *t = right;
10233 pic14_emitcode(";remove left +","");
10237 big = AOP_SIZE(nextleft);
10238 small = AOP_SIZE(nextright);
10240 switch(nextic->op) {
10243 pic14_emitcode(";optimize a +","");
10244 /* if unsigned or not an integral type */
10245 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10246 pic14_emitcode(";add a bit to something","");
10249 pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10251 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10252 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10253 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10255 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10263 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10264 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10265 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10268 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10270 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10271 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10272 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10273 pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10274 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10277 pic14_emitcode("rlf","known_zero,w");
10284 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10285 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10286 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10288 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10298 freeAsmop(right,NULL,ic,TRUE);
10299 freeAsmop(result,NULL,ic,TRUE);
10300 freeAsmop(nextright,NULL,ic,TRUE);
10301 freeAsmop(nextleft,NULL,ic,TRUE);
10303 nextic->generated = 1;
10310 /*-----------------------------------------------------------------*/
10311 /* genCast - gen code for casting */
10312 /*-----------------------------------------------------------------*/
10313 static void genCast (iCode *ic)
10315 operand *result = IC_RESULT(ic);
10316 sym_link *restype = operandType(result);
10317 sym_link *rtype = operandType(IC_RIGHT(ic));
10318 operand *right = IC_RIGHT(ic);
10322 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10323 /* if they are equivalent then do nothing */
10324 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10327 aopOp(right,ic,FALSE) ;
10328 aopOp(result,ic,FALSE);
10330 DEBUGpic14_AopType(__LINE__,NULL,right,result);
10332 /* if the result is a bit */
10333 if (AOP_TYPE(result) == AOP_CRY) {
10334 assert(!"assigning to bit variables is not supported");
10337 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10339 size = AOP_SIZE(result);
10341 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10343 emitpcode(POC_CLRF, popGet(AOP(result),0));
10344 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10345 emitpcode(POC_INCF, popGet(AOP(result),0));
10348 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
10353 if (IS_PTR(restype))
10355 operand *result = IC_RESULT(ic);
10356 //operand *left = IC_LEFT(ic);
10357 operand *right = IC_RIGHT(ic);
10360 /* copy common part */
10361 int max, size = AOP_SIZE(result);
10362 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10363 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10365 /* warn if we discard generic opinter tag */
10366 if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10368 //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10374 mov2w_op (right, size);
10375 movwf (AOP(result), size);
10378 /* upcast into generic pointer type? */
10379 if (IS_GENPTR(restype)
10380 && (size < AOP_SIZE(result))
10381 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10383 //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10386 switch (DCL_TYPE(rtype))
10388 case POINTER: /* __data */
10389 case FPOINTER: /* __data */
10390 assert (AOP_SIZE(right) == 2);
10391 tag = GPTRTAG_DATA;
10394 case CPOINTER: /* __code */
10395 assert (AOP_SIZE(right) == 2);
10396 tag = GPTRTAG_CODE;
10399 case GPOINTER: /* unknown destination, __data or __code */
10400 /* assume __data space (address of immediate) */
10401 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10402 if (AOP(right)->code)
10403 tag = GPTRTAG_CODE;
10405 tag = GPTRTAG_DATA;
10409 assert (!"unhandled pointer type");
10412 /* convert other values into pointers to __data space */
10413 tag = GPTRTAG_DATA;
10416 assert (AOP_SIZE(result) == 3);
10418 emitpcode(POC_CLRF, popGet(AOP(result), 2));
10420 emitpcode(POC_MOVLW, popGetLit(tag));
10421 movwf(AOP(result), 2);
10424 addSign(result, max, 0);
10429 /* if they are the same size : or less */
10430 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10432 /* if they are in the same place */
10433 if (pic14_sameRegs(AOP(right),AOP(result)))
10436 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10437 if (IS_PTR_CONST(rtype))
10438 DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10439 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10440 DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10442 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10443 emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10444 emitpcode(POC_MOVWF, popGet(AOP(result),0));
10445 emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10446 emitpcode(POC_MOVWF, popGet(AOP(result),1));
10447 if(AOP_SIZE(result) <2)
10448 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10452 /* if they in different places then copy */
10453 size = AOP_SIZE(result);
10456 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10457 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10459 //aopPut(AOP(result),
10460 // aopGet(AOP(right),offset,FALSE,FALSE),
10469 /* so we now know that the size of destination is greater
10470 than the size of the source.
10471 Now, if the next iCode is an operator then we might be
10472 able to optimize the operation without performing a cast.
10474 if(0 && genMixedOperation(ic)) {
10475 /* XXX: cannot optimize: must copy regs! */
10479 /* we move to result for the size of source */
10480 size = AOP_SIZE(right);
10483 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10484 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10488 addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10491 freeAsmop(right,NULL,ic,TRUE);
10492 freeAsmop(result,NULL,ic,TRUE);
10496 /*-----------------------------------------------------------------*/
10497 /* genDjnz - generate decrement & jump if not zero instrucion */
10498 /*-----------------------------------------------------------------*/
10499 static int genDjnz (iCode *ic, iCode *ifx)
10501 symbol *lbl, *lbl1;
10503 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10508 /* if the if condition has a false label
10509 then we cannot save */
10513 /* if the minus is not of the form
10515 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10516 !IS_OP_LITERAL(IC_RIGHT(ic)))
10519 if (operandLitValue(IC_RIGHT(ic)) != 1)
10522 /* if the size of this greater than one then no
10524 if (getSize(operandType(IC_RESULT(ic))) > 1)
10527 /* otherwise we can save BIG */
10528 lbl = newiTempLabel(NULL);
10529 lbl1= newiTempLabel(NULL);
10531 aopOp(IC_RESULT(ic),ic,FALSE);
10533 if (IS_AOP_PREG(IC_RESULT(ic))) {
10534 pic14_emitcode("dec","%s",
10535 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10536 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10537 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10541 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10542 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10544 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10545 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10548 /* pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10549 /* pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10550 /* pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10551 /* pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10554 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10555 ifx->generated = 1;
10559 /*-----------------------------------------------------------------*/
10560 /* genReceive - generate code for a receive iCode */
10561 /*-----------------------------------------------------------------*/
10562 static void genReceive (iCode *ic)
10565 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10567 if (isOperandInFarSpace(IC_RESULT(ic)) &&
10568 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10569 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10571 int size = getSize(operandType(IC_RESULT(ic)));
10572 int offset = fReturnSizePic - size;
10574 pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10575 fReturn[fReturnSizePic - offset - 1] : "acc"));
10578 aopOp(IC_RESULT(ic),ic,FALSE);
10579 size = AOP_SIZE(IC_RESULT(ic));
10582 pic14_emitcode ("pop","acc");
10583 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10588 aopOp(IC_RESULT(ic),ic,FALSE);
10590 assignResultValue(IC_RESULT(ic));
10593 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10596 /*-----------------------------------------------------------------*/
10597 /* genDummyRead - generate code for dummy read of volatiles */
10598 /*-----------------------------------------------------------------*/
10600 genDummyRead (iCode * ic)
10603 pic14_emitcode ("; genDummyRead","");
10604 pic14_emitcode ("; not implemented","");
10609 /*-----------------------------------------------------------------*/
10610 /* genpic14Code - generate code for pic14 based controllers */
10611 /*-----------------------------------------------------------------*/
10613 * At this point, ralloc.c has gone through the iCode and attempted
10614 * to optimize in a way suitable for a PIC. Now we've got to generate
10615 * PIC instructions that correspond to the iCode.
10617 * Once the instructions are generated, we'll pass through both the
10618 * peep hole optimizer and the pCode optimizer.
10619 *-----------------------------------------------------------------*/
10621 void genpic14Code (iCode *lic)
10628 lineHead = lineCurr = NULL;
10630 pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10633 /* if debug information required */
10634 if (options.debug && currFunc) {
10636 debugFile->writeFunction (currFunc, lic);
10641 for (ic = lic ; ic ; ic = ic->next ) {
10643 //DEBUGpic14_emitcode(";ic","");
10644 //fprintf (stderr, "in ic loop\n");
10645 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10646 //ic->lineno, printCLine(ic->filename, ic->lineno));
10648 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10650 //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10651 cline = printCLine (ic->filename, ic->lineno);
10652 if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10653 addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10654 //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10657 if (options.iCodeInAsm) {
10658 emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10660 /* if the result is marked as
10661 spilt and rematerializable or code for
10662 this has already been generated then
10664 if (resultRemat(ic) || ic->generated )
10667 /* depending on the operation */
10686 /* IPOP happens only when trying to restore a
10687 spilt live range, if there is an ifx statement
10688 following this pop then the if statement might
10689 be using some of the registers being popped which
10690 would destory the contents of the register so
10691 we need to check for this condition and handle it */
10693 ic->next->op == IFX &&
10694 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10695 genIfx (ic->next,ic);
10713 genEndFunction (ic);
10733 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10750 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
10754 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10761 /* note these two are xlated by algebraic equivalence
10762 during parsing SDCC.y */
10763 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10764 "got '>=' or '<=' shouldn't have come here");
10768 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10780 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10784 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10788 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10812 genRightShift (ic);
10815 case GET_VALUE_AT_ADDRESS:
10820 if (POINTER_SET(ic))
10847 addSet(&_G.sendSet,ic);
10850 case DUMMY_READ_VOLATILE:
10855 fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10862 /* now we are ready to call the
10863 peep hole optimizer */
10864 if (!options.nopeep) {
10865 peepHole (&lineHead);
10867 /* now do the actual printing */
10868 printLine (lineHead,codeOutFile);
10871 DFPRINTF((stderr,"printing pBlock\n\n"));
10872 printpBlock(stdout,pb);
10878 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10879 * (meaning: representing its own address) or not (referencing its contents).
10880 * This can only be decided based on the operand's type. */
10882 aop_isLitLike (asmop *aop)
10885 if (aop->type == AOP_LIT) return 1;
10886 if (aop->type == AOP_IMMD) return 1;
10887 if ((aop->type == AOP_PCODE) &&
10888 ((aop->aopu.pcop->type == PO_LITERAL)))
10890 /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10891 * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10898 op_isLitLike (operand *op)
10901 if (aop_isLitLike (AOP(op))) return 1;
10902 if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10903 if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;