1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for pic
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 PIC port - Scott Dattalo scott@dattalo.com (2000)
8 cont'd - Raphael Neider <rneider AT web.de> (2005)
10 This program is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the
12 Free Software Foundation; either version 2, or (at your option) any
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 In other words, you are welcome to use, share and improve this program.
25 You are forbidden to forbid anyone else to use, share and improve
26 what you give them. Help stamp out software-hoarding!
29 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
30 Made everything static
31 -------------------------------------------------------------------------*/
37 #include "SDCCglobl.h"
41 #include "SDCCpeeph.h"
47 /* When changing these, you must also update the assembler template
48 * in device/lib/libsdcc/macros.inc */
49 #define GPTRTAG_DATA 0x00
50 #define GPTRTAG_CODE 0x80
52 /* The PIC port(s) need not differentiate between POINTER and FPOINTER. */
53 #define PIC_IS_DATA_PTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
54 #define PIC_IS_FARPTR(x) (PIC_IS_DATA_PTR(x))
56 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
57 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
58 void genMult8X8_8 (operand *, operand *,operand *);
59 extern void printpBlock(FILE *of, pBlock *pb);
61 static int labelOffset=0;
62 extern int debug_verbose;
63 extern int pic14_hasInterrupt;
64 //static int optimized_for_speed = 0;
66 /* max_key keeps track of the largest label number used in
67 a function. This is then used to adjust the label offset
68 for the next function.
71 static int GpsuedoStkPtr=0;
72 static int pic14_inISR = 0;
74 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
75 extern char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
76 const char *AopType(short type);
78 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0x00ff)
80 /* this is the down and dirty file with all kinds of
81 kludgy & hacky stuff. This is what it is all about
82 CODE GENERATION for a specific MCU . some of the
83 routines may be reusable, will have to see */
85 static char *zero = "#0x00";
86 static char *one = "#0x01";
87 static char *spname = "sp";
89 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
90 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
91 static char **fReturn = fReturnpic14;
93 //static char *accUse[] = {"a","b"};
95 //static short rbank = -1;
107 /* Resolved ifx structure. This structure stores information
108 about an iCode ifx that makes it easier to generate code.
110 typedef struct resolvedIfx {
111 symbol *lbl; /* pointer to a label */
112 int condition; /* true or false ifx */
113 int generated; /* set true when the code associated with the ifx
117 extern int pic14_ptrRegReq ;
118 extern int pic14_nRegs;
119 extern FILE *codeOutFile;
120 static void saverbank (int, iCode *,bool);
122 static lineNode *lineHead = NULL;
123 static lineNode *lineCurr = NULL;
126 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
127 0xE0, 0xC0, 0x80, 0x00};
128 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
129 0x07, 0x03, 0x01, 0x00};
134 /*-----------------------------------------------------------------*/
135 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
136 /* exponent of 2 is returned, otherwise -1 is */
138 /* note that this is similar to the function `powof2' in SDCCsymt */
142 /*-----------------------------------------------------------------*/
143 static int my_powof2 (unsigned long num)
146 if( (num & (num-1)) == 0) {
159 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
162 DEBUGpic14_emitcode ("; ","line = %d result %s=%s, size=%d, left %s=%s, size=%d, right %s=%s, size=%d",
164 ((result) ? AopType(AOP_TYPE(result)) : "-"),
165 ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
166 ((result) ? AOP_SIZE(result) : 0),
167 ((left) ? AopType(AOP_TYPE(left)) : "-"),
168 ((left) ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
169 ((left) ? AOP_SIZE(left) : 0),
170 ((right) ? AopType(AOP_TYPE(right)) : "-"),
171 ((right) ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
172 ((right) ? AOP_SIZE(right) : 0));
176 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
179 DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
181 ((result) ? AopType(AOP_TYPE(result)) : "-"),
182 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
183 ((left) ? AopType(AOP_TYPE(left)) : "-"),
184 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
185 ((right) ? AopType(AOP_TYPE(right)) : "-"),
186 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
190 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
193 char lb[INITIAL_INLINEASM];
194 unsigned char *lbp = (unsigned char *)lb;
196 if(!debug_verbose && !options.debug)
203 sprintf(lb,"%s\t",inst);
205 sprintf(lb,"%s",inst);
206 vsprintf(lb+(strlen(lb)),fmt,ap);
210 while (isspace(*lbp)) lbp++;
213 lineCurr = (lineCurr ?
214 connectLine(lineCurr,newLineNode(lb)) :
215 (lineHead = newLineNode(lb)));
216 lineCurr->isInline = _G.inLine;
217 lineCurr->isDebug = _G.debugLine;
219 addpCode2pBlock(pb,newpCodeCharP(lb));
224 static void Safe_vsnprintf (char *buf, size_t size, const char *fmt, va_list ap)
226 #if defined (HAVE_VSNPRINTF)
227 vsnprintf (buf, size, fmt, ap);
228 #elif defined (HAVE_VSPRINTF)
229 vsprintf (buf, size, fmt, ap);
230 if (strlen (buf) >= size)
232 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
234 #elif defined (HAVE_SNPRINTF)
235 snprintf (buf, size, "vs(n)printf required");
236 #elif defined (HAVE_SRINTF)
237 sprintf (buf, "vs(n)printf required");
238 if (strlen (buf) >= size)
240 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
243 assert ( !"neither vsnprintf nor vsprintf is present -- unable to proceed" );
247 void emitpComment (const char *fmt, ...)
254 Safe_vsnprintf (buffer, 4096, fmt, va);
255 //fprintf (stderr, "%s\n" ,buffer);
256 addpCode2pBlock (pb, newpCodeCharP (buffer));
259 Safe_vsnprintf (buffer, 4096, fmt, va);
260 fprintf (stderr, "No current pBlock -- discarding comment [%s]\n", buffer);
266 void emitpLabel(int key)
268 addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
271 /* gen.h defines a macro emitpcode that should be used to call emitpcode
272 * as this allows for easy debugging (ever asked the question: where was
273 * this instruction geenrated? Here is the answer... */
274 void emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
277 addpCode2pBlock(pb,newpCode(poc,pcop));
279 static int has_warned = 0;
281 DEBUGpic14_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
284 fprintf( stderr, "WARNING: encountered NULL pcop--this is probably a compiler bug...\n" );
289 void emitpcodeNULLop(PIC_OPCODE poc)
292 addpCode2pBlock(pb,newpCode(poc,NULL));
297 /*-----------------------------------------------------------------*/
298 /* pic14_emitcode - writes the code into a file : for now it is simple */
299 /*-----------------------------------------------------------------*/
300 void pic14_emitcode (char *inst,char *fmt, ...)
303 char lb[INITIAL_INLINEASM];
304 unsigned char *lbp = (unsigned char *)lb;
310 sprintf(lb,"%s\t",inst);
312 sprintf(lb,"%s",inst);
313 vsprintf(lb+(strlen(lb)),fmt,ap);
317 while (isspace(*lbp)) lbp++;
320 lineCurr = (lineCurr ?
321 connectLine(lineCurr,newLineNode(lb)) :
322 (lineHead = newLineNode(lb)));
323 lineCurr->isInline = _G.inLine;
324 lineCurr->isDebug = _G.debugLine;
327 addpCode2pBlock(pb,newpCodeCharP(lb));
332 /*-----------------------------------------------------------------*/
333 /* pic14_emitDebuggerSymbol - associate the current code location */
334 /* with a debugger symbol */
335 /*-----------------------------------------------------------------*/
337 pic14_emitDebuggerSymbol (char * debugSym)
340 pic14_emitcode ("", ";%s ==.", debugSym);
345 /*-----------------------------------------------------------------*/
346 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
347 /*-----------------------------------------------------------------*/
348 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
350 bool r0iu = FALSE , r1iu = FALSE;
351 bool r0ou = FALSE , r1ou = FALSE;
353 /* the logic: if r0 & r1 used in the instruction
354 then we are in trouble otherwise */
356 /* first check if r0 & r1 are used by this
357 instruction, in which case we are in trouble */
358 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
359 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
364 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
365 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
367 /* if no usage of r0 then return it */
368 if (!r0iu && !r0ou) {
369 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
370 (*aopp)->type = AOP_R0;
372 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
375 /* if no usage of r1 then return it */
376 if (!r1iu && !r1ou) {
377 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
378 (*aopp)->type = AOP_R1;
380 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
383 /* now we know they both have usage */
384 /* if r0 not used in this instruction */
386 /* push it if not already pushed */
388 //pic14_emitcode ("push","%s",
389 // pic14_regWithIdx(R0_IDX)->dname);
393 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
394 (*aopp)->type = AOP_R0;
396 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
399 /* if r1 not used then */
402 /* push it if not already pushed */
404 //pic14_emitcode ("push","%s",
405 // pic14_regWithIdx(R1_IDX)->dname);
409 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
410 (*aopp)->type = AOP_R1;
411 return pic14_regWithIdx(R1_IDX);
415 /* I said end of world but not quite end of world yet */
416 /* if this is a result then we can push it on the stack*/
418 (*aopp)->type = AOP_STK;
422 /* other wise this is true end of the world */
423 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
424 "getFreePtr should never reach here");
429 /*-----------------------------------------------------------------*/
430 /* newAsmop - creates a new asmOp */
431 /*-----------------------------------------------------------------*/
432 asmop *newAsmop (short type)
436 aop = Safe_calloc(1,sizeof(asmop));
441 static void genSetDPTR(int n)
445 pic14_emitcode(";", "Select standard DPTR");
446 pic14_emitcode("mov", "dps, #0x00");
450 pic14_emitcode(";", "Select alternate DPTR");
451 pic14_emitcode("mov", "dps, #0x01");
455 /*-----------------------------------------------------------------*/
456 /* resolveIfx - converts an iCode ifx into a form more useful for */
457 /* generating code */
458 /*-----------------------------------------------------------------*/
459 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
464 // DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
466 resIfx->condition = 1; /* assume that the ifx is true */
467 resIfx->generated = 0; /* indicate that the ifx has not been used */
470 resIfx->lbl = NULL; /* this is wrong: newiTempLabel(NULL); / * oops, there is no ifx. so create a label */
472 DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
473 __FUNCTION__,__LINE__,resIfx->lbl->key);
477 resIfx->lbl = IC_TRUE(ifx);
479 resIfx->lbl = IC_FALSE(ifx);
480 resIfx->condition = 0;
484 DEBUGpic14_emitcode("; ***","ifx true is non-null");
486 DEBUGpic14_emitcode("; ***","ifx false is non-null");
490 // DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
493 /*-----------------------------------------------------------------*/
494 /* pointerCode - returns the code for a pointer type */
495 /*-----------------------------------------------------------------*/
497 static int pointerCode (sym_link *etype)
500 return PTR_TYPE(SPEC_OCLS(etype));
505 /*-----------------------------------------------------------------*/
506 /* aopForSym - for a true symbol */
507 /*-----------------------------------------------------------------*/
508 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
511 memmap *space= SPEC_OCLS(sym->etype);
513 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
514 /* if already has one */
519 /* assign depending on the storage class */
520 /* if it is on the stack or indirectly addressable */
521 /* space we need to assign either r0 or r1 to it */
522 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
523 sym->aop = aop = newAsmop(0);
524 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
525 aop->size = getSize(sym->type);
527 /* now assign the address of the variable to
528 the pointer register */
529 if (aop->type != AOP_STK) {
533 pic14_emitcode("push","acc");
535 pic14_emitcode("mov","a,_bp");
536 pic14_emitcode("add","a,#0x%02x",
538 ((char)(sym->stack - _G.nRegsSaved )) :
539 ((char)sym->stack)) & 0xff);
540 pic14_emitcode("mov","%s,a",
541 aop->aopu.aop_ptr->name);
544 pic14_emitcode("pop","acc");
546 pic14_emitcode("mov","%s,#%s",
547 aop->aopu.aop_ptr->name,
549 aop->paged = space->paged;
551 aop->aopu.aop_stk = sym->stack;
555 if (sym->onStack && options.stack10bit)
557 /* It's on the 10 bit stack, which is located in
561 //DEBUGpic14_emitcode(";","%d",__LINE__);
564 pic14_emitcode("push","acc");
566 pic14_emitcode("mov","a,_bp");
567 pic14_emitcode("add","a,#0x%02x",
569 ((char)(sym->stack - _G.nRegsSaved )) :
570 ((char)sym->stack)) & 0xff);
573 pic14_emitcode ("mov","dpx1,#0x40");
574 pic14_emitcode ("mov","dph1,#0x00");
575 pic14_emitcode ("mov","dpl1, a");
579 pic14_emitcode("pop","acc");
581 sym->aop = aop = newAsmop(AOP_DPTR2);
582 aop->size = getSize(sym->type);
587 //DEBUGpic14_emitcode(";","%d",__LINE__);
588 /* if in bit space */
589 if (IN_BITSPACE(space)) {
590 sym->aop = aop = newAsmop (AOP_CRY);
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);
596 /* if it is in direct space */
597 if (IN_DIRSPACE(space)) {
598 sym->aop = aop = newAsmop (AOP_DIR);
599 aop->aopu.aop_dir = sym->rname ;
600 aop->size = getSize(sym->type);
601 DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
605 /* special case for a function */
606 if (IS_FUNC(sym->type)) {
608 sym->aop = aop = newAsmop(AOP_PCODE);
609 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
610 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
611 PCOI(aop->aopu.pcop)->_function = 1;
612 PCOI(aop->aopu.pcop)->index = 0;
613 aop->size = FPTRSIZE;
615 sym->aop = aop = newAsmop(AOP_IMMD);
616 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
617 strcpy(aop->aopu.aop_immd,sym->rname);
618 aop->size = FPTRSIZE;
620 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
624 if (IS_ARRAY(sym->type)) {
625 sym->aop = aop = newAsmop(AOP_PCODE);
626 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
627 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
628 PCOI(aop->aopu.pcop)->_function = 0;
629 PCOI(aop->aopu.pcop)->index = 0;
630 aop->size = getSize(sym->etype) * DCL_ELEM(sym->type);
632 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
636 /* only remaining is far space */
637 /* in which case DPTR gets the address */
638 sym->aop = aop = newAsmop(AOP_PCODE);
640 aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
641 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
642 PCOI(aop->aopu.pcop)->index = 0;
644 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
645 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
647 allocDirReg (IC_LEFT(ic));
649 aop->size = FPTRSIZE;
651 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
652 sym->aop = aop = newAsmop(AOP_DPTR);
653 pic14_emitcode ("mov","dptr,#%s", sym->rname);
654 aop->size = getSize(sym->type);
656 DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
659 /* if it is in code space */
660 if (IN_CODESPACE(space))
666 /*-----------------------------------------------------------------*/
667 /* aopForRemat - rematerialzes an object */
668 /*-----------------------------------------------------------------*/
669 static asmop *aopForRemat (operand *op) // x symbol *sym)
671 symbol *sym = OP_SYMBOL(op);
673 asmop *aop = newAsmop(AOP_PCODE);
677 ic = sym->rematiCode;
679 DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
680 if(IS_OP_POINTER(op)) {
681 DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
685 val += (int) operandLitValue(IC_RIGHT(ic));
686 } else if (ic->op == '-') {
687 val -= (int) operandLitValue(IC_RIGHT(ic));
691 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
694 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
695 aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
696 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
697 PCOI(aop->aopu.pcop)->index = val;
699 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
700 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
701 val, IS_PTR_CONST(operandType(op)));
703 // DEBUGpic14_emitcode(";","aop type %s",AopType(AOP_TYPE(IC_LEFT(ic))));
705 allocDirReg (IC_LEFT(ic));
710 int aopIdx (asmop *aop, int offset)
715 if(aop->type != AOP_REG)
718 return aop->aopu.aop_reg[offset]->rIdx;
721 /*-----------------------------------------------------------------*/
722 /* regsInCommon - two operands have some registers in common */
723 /*-----------------------------------------------------------------*/
724 static bool regsInCommon (operand *op1, operand *op2)
729 /* if they have registers in common */
730 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
733 sym1 = OP_SYMBOL(op1);
734 sym2 = OP_SYMBOL(op2);
736 if (sym1->nRegs == 0 || sym2->nRegs == 0)
739 for (i = 0 ; i < sym1->nRegs ; i++) {
744 for (j = 0 ; j < sym2->nRegs ;j++ ) {
748 if (sym2->regs[j] == sym1->regs[i])
756 /*-----------------------------------------------------------------*/
757 /* operandsEqu - equivalent */
758 /*-----------------------------------------------------------------*/
759 static bool operandsEqu ( operand *op1, operand *op2)
763 /* if they not symbols */
764 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
767 sym1 = OP_SYMBOL(op1);
768 sym2 = OP_SYMBOL(op2);
770 /* if both are itemps & one is spilt
771 and the other is not then false */
772 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
773 sym1->isspilt != sym2->isspilt )
776 /* if they are the same */
780 if (sym1->rname[0] && sym2->rname[0]
781 && strcmp (sym1->rname, sym2->rname) == 0)
785 /* if left is a tmp & right is not */
789 (sym1->usl.spillLoc == sym2))
796 (sym2->usl.spillLoc == sym1))
802 /*-----------------------------------------------------------------*/
803 /* pic14_sameRegs - two asmops have the same registers */
804 /*-----------------------------------------------------------------*/
805 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
812 if (aop1->type != AOP_REG ||
813 aop2->type != AOP_REG )
816 if (aop1->size != aop2->size )
819 for (i = 0 ; i < aop1->size ; i++ )
820 if (aop1->aopu.aop_reg[i] !=
821 aop2->aopu.aop_reg[i] )
827 /*-----------------------------------------------------------------*/
828 /* aopOp - allocates an asmop for an operand : */
829 /*-----------------------------------------------------------------*/
830 void aopOp (operand *op, iCode *ic, bool result)
839 /* if this a literal */
840 if (IS_OP_LITERAL(op)) {
841 op->aop = aop = newAsmop(AOP_LIT);
842 aop->aopu.aop_lit = op->operand.valOperand;
843 aop->size = getSize(operandType(op));
848 sym_link *type = operandType(op);
849 if(IS_PTR_CONST(type))
850 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
853 /* if already has a asmop then continue */
857 /* if the underlying symbol has a aop */
858 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
859 DEBUGpic14_emitcode(";","%d",__LINE__);
860 op->aop = OP_SYMBOL(op)->aop;
864 /* if this is a true symbol */
865 if (IS_TRUE_SYMOP(op)) {
866 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
867 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
871 /* this is a temporary : this has
877 e) can be a return use only */
882 /* if the type is a conditional */
883 if (sym->regType == REG_CND) {
884 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
889 /* if it is spilt then two situations
891 b) has a spill location */
892 if (sym->isspilt || sym->nRegs == 0) {
894 DEBUGpic14_emitcode(";","%d",__LINE__);
895 /* rematerialize it NOW */
898 sym->aop = op->aop = aop = aopForRemat (op);
899 aop->size = getSize(sym->type);
900 //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
905 /* WREG is not usable as an ordinary operand with PIC architecture,
906 * one might introduce a scratch register that can be used to make
907 * WREG accesible as an operand... disable WREG for now */
910 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
911 aop->size = getSize(sym->type);
912 for ( i = 0 ; i < 2 ; i++ )
913 aop->aopu.aop_str[i] = accUse[i];
914 DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
920 if(sym->isptr) { // && sym->uptr
921 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
922 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
924 //PCOI(aop->aopu.pcop)->_const = 0;
925 //PCOI(aop->aopu.pcop)->index = 0;
927 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
928 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
930 //allocDirReg (IC_LEFT(ic));
932 aop->size = getSize(sym->type);
933 DEBUGpic14_emitcode(";","%d",__LINE__);
940 aop = op->aop = sym->aop = newAsmop(AOP_STR);
941 aop->size = getSize(sym->type);
942 for ( i = 0 ; i < fReturnSizePic ; i++ )
943 aop->aopu.aop_str[i] = fReturn[i];
945 DEBUGpic14_emitcode(";","%d",__LINE__);
950 /* else spill location */
951 if (sym->usl.spillLoc)
953 asmop *oldAsmOp = NULL;
955 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
957 /* force a new aop if sizes differ */
958 oldAsmOp = sym->usl.spillLoc->aop;
959 sym->usl.spillLoc->aop = NULL;
961 DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
962 __FUNCTION__,__LINE__,
963 sym->usl.spillLoc->rname,
964 sym->rname, sym->usl.spillLoc->offset);
966 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
967 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
969 /* Don't reuse the new aop, go with the last one */
970 sym->usl.spillLoc->aop = oldAsmOp;
972 //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
973 aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname,
975 sym->usl.spillLoc->offset);
976 aop->size = getSize(sym->type);
983 sym_link *type = operandType(op);
984 if(IS_PTR_CONST(type))
985 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
988 /* must be in a register */
989 DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
990 sym->aop = op->aop = aop = newAsmop(AOP_REG);
991 aop->size = sym->nRegs;
992 for ( i = 0 ; i < sym->nRegs ;i++)
993 aop->aopu.aop_reg[i] = sym->regs[i];
996 /*-----------------------------------------------------------------*/
997 /* freeAsmop - free up the asmop given to an operand */
998 /*----------------------------------------------------------------*/
999 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1016 /* depending on the asmop type only three cases need work AOP_RO
1017 , AOP_R1 && AOP_STK */
1019 switch (aop->type) {
1023 pic14_emitcode ("pop","ar0");
1027 bitVectUnSetBit(ic->rUsed,R0_IDX);
1033 pic14_emitcode ("pop","ar1");
1037 bitVectUnSetBit(ic->rUsed,R1_IDX);
1043 int stk = aop->aopu.aop_stk + aop->size;
1044 bitVectUnSetBit(ic->rUsed,R0_IDX);
1045 bitVectUnSetBit(ic->rUsed,R1_IDX);
1047 getFreePtr(ic,&aop,FALSE);
1049 if (options.stack10bit)
1051 /* I'm not sure what to do here yet... */
1054 "*** Warning: probably generating bad code for "
1055 "10 bit stack mode.\n");
1059 pic14_emitcode ("mov","a,_bp");
1060 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1061 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1063 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1067 pic14_emitcode("pop","acc");
1068 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1070 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1073 freeAsmop(op,NULL,ic,TRUE);
1075 pic14_emitcode("pop","ar0");
1080 pic14_emitcode("pop","ar1");
1088 /* all other cases just dealloc */
1092 OP_SYMBOL(op)->aop = NULL;
1093 /* if the symbol has a spill */
1095 SPIL_LOC(op)->aop = NULL;
1100 /*-----------------------------------------------------------------*/
1101 /* aopGet - for fetching value of the aop */
1102 /*-----------------------------------------------------------------*/
1103 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1108 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1109 /* offset is greater than
1111 if (offset > (aop->size - 1) &&
1112 aop->type != AOP_LIT)
1115 /* depending on type */
1116 switch (aop->type) {
1120 DEBUGpic14_emitcode(";","%d",__LINE__);
1121 /* if we need to increment it */
1122 while (offset > aop->coff) {
1123 pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);
1127 while (offset < aop->coff) {
1128 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1132 aop->coff = offset ;
1134 pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1135 return (dname ? "acc" : "a");
1137 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1138 rs = Safe_calloc(1,strlen(s)+1);
1144 DEBUGpic14_emitcode(";","%d",__LINE__);
1145 if (aop->type == AOP_DPTR2)
1150 while (offset > aop->coff) {
1151 pic14_emitcode ("inc","dptr");
1155 while (offset < aop->coff) {
1156 pic14_emitcode("lcall","__decdptr");
1162 pic14_emitcode("clr","a");
1163 pic14_emitcode("movc","a,@a+dptr");
1166 pic14_emitcode("movx","a,@dptr");
1169 if (aop->type == AOP_DPTR2)
1174 return (dname ? "acc" : "a");
1179 sprintf (s,"%s",aop->aopu.aop_immd);
1182 sprintf(s,"(%s >> %d)",
1187 aop->aopu.aop_immd);
1188 DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1189 rs = Safe_calloc(1,strlen(s)+1);
1195 sprintf(s,"(%s + %d)",
1198 DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1200 sprintf(s,"%s",aop->aopu.aop_dir);
1201 rs = Safe_calloc(1,strlen(s)+1);
1207 // return aop->aopu.aop_reg[offset]->dname;
1209 return aop->aopu.aop_reg[offset]->name;
1212 //pic14_emitcode(";","%d",__LINE__);
1213 return aop->aopu.aop_dir;
1216 DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1217 return "AOP_accumulator_bug";
1220 sprintf(s, "0x%02x", pic14aopLiteral (aop->aopu.aop_lit, offset));
1221 rs = Safe_strdup(s);
1225 aop->coff = offset ;
1226 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1229 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1231 return aop->aopu.aop_str[offset];
1235 pCodeOp *pcop = aop->aopu.pcop;
1236 DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1239 DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
1240 sprintf(s,"(%s+%d)", pcop->name,offset);
1242 DEBUGpic14_emitcode(";","%s",pcop->name);
1243 sprintf(s,"%s", pcop->name);
1246 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1249 rs = Safe_calloc(1,strlen(s)+1);
1255 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1256 "aopget got unsupported aop->type");
1261 /*-----------------------------------------------------------------*/
1262 /* popGetTempReg - create a new temporary pCodeOp */
1263 /*-----------------------------------------------------------------*/
1264 pCodeOp *popGetTempReg(void)
1269 pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1270 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1271 PCOR(pcop)->r->wasUsed=1;
1272 PCOR(pcop)->r->isFree=0;
1278 /*-----------------------------------------------------------------*/
1279 /* popReleaseTempReg - create a new temporary pCodeOp */
1280 /*-----------------------------------------------------------------*/
1281 void popReleaseTempReg(pCodeOp *pcop)
1284 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1285 PCOR(pcop)->r->isFree = 1;
1288 /*-----------------------------------------------------------------*/
1289 /* popGetLabel - create a new pCodeOp of type PO_LABEL */
1290 /*-----------------------------------------------------------------*/
1291 pCodeOp *popGetLabel(unsigned int key)
1294 DEBUGpic14_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1296 if(key>(unsigned int)max_key)
1299 return newpCodeOpLabel(NULL,key+100+labelOffset);
1302 /*-------------------------------------------------------------------*/
1303 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1304 /*-------------------------------------------------------------------*/
1305 pCodeOp *popGetHighLabel(unsigned int key)
1308 pcop = popGetLabel(key);
1309 PCOLAB(pcop)->offset = 1;
1313 /*-----------------------------------------------------------------*/
1314 /* popGetLit - asm operator to pcode operator conversion */
1315 /*-----------------------------------------------------------------*/
1316 pCodeOp *popGetLit(unsigned int lit)
1319 return newpCodeOpLit((unsigned char)lit);
1322 /*-----------------------------------------------------------------*/
1323 /* popGetImmd - asm operator to pcode immediate conversion */
1324 /*-----------------------------------------------------------------*/
1325 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1328 return newpCodeOpImmd(name, offset,index, 0, is_func);
1331 extern set *externs;
1333 /*-----------------------------------------------------------------*/
1334 /* popGetWithString - asm operator to pcode operator conversion */
1335 /*-----------------------------------------------------------------*/
1336 pCodeOp *popGetWithString(char *str, int isExtern)
1342 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1346 pcop = newpCodeOp(str,PO_STR);
1347 PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1352 pCodeOp *popGetExternal (char *str)
1354 pCodeOp *pcop = popGetWithString (str, 1);
1360 for (sym = setFirstItem (externs); !found && sym; sym = setNextItem (externs))
1362 if (!strcmp (str, sym->rname))
1368 sym = newSymbol(str, 0);
1369 strncpy(sym->rname, str, SDCC_NAME_MAX);
1370 addSet (&externs, sym);
1376 /*-----------------------------------------------------------------*/
1377 /* popRegFromString - */
1378 /*-----------------------------------------------------------------*/
1379 pCodeOp *popRegFromString(char *str, int size, int offset)
1382 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1383 pcop->type = PO_DIR;
1385 DEBUGpic14_emitcode(";","%d",__LINE__);
1390 pcop->name = Safe_calloc(1,strlen(str)+1);
1391 strcpy(pcop->name,str);
1393 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1395 PCOR(pcop)->r = dirregWithName(pcop->name);
1396 if(PCOR(pcop)->r == NULL) {
1397 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1398 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1399 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1401 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1403 PCOR(pcop)->instance = offset;
1408 /*-----------------------------------------------------------------*/
1409 /*-----------------------------------------------------------------*/
1410 pCodeOp *popRegFromIdx(int rIdx)
1414 DEBUGpic14_emitcode ("; ***","%s,%d , rIdx=0x%x",
1415 __FUNCTION__,__LINE__,rIdx);
1417 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1419 PCOR(pcop)->rIdx = rIdx;
1420 PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1421 PCOR(pcop)->r->isFree = 0;
1422 PCOR(pcop)->r->wasUsed = 1;
1424 pcop->type = PCOR(pcop)->r->pc_type;
1430 /*-----------------------------------------------------------------*/
1431 /* popGet - asm operator to pcode operator conversion */
1432 /*-----------------------------------------------------------------*/
1433 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1435 //char *s = buffer ;
1440 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1441 /* offset is greater than
1447 /* XXX: still needed for BIT operands (AOP_CRY) */
1448 if (offset > (aop->size - 1) &&
1449 aop->type != AOP_LIT &&
1450 aop->type != AOP_PCODE)
1452 printf( "%s: (offset[%d] > AOP_SIZE(op)[%d]-1) && AOP_TYPE(op) != AOP_LIT)\n", __FUNCTION__, offset, aop->size);
1453 return NULL; //zero;
1456 /* depending on type */
1457 switch (aop->type) {
1464 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1468 DEBUGpic14_emitcode(";","%d",__LINE__);
1469 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1472 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1474 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1475 pcop->type = PO_DIR;
1477 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1478 strcpy(pcop->name,aop->aopu.aop_dir);
1479 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1480 if(PCOR(pcop)->r == NULL) {
1481 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1482 PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1483 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1485 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1487 PCOR(pcop)->instance = offset;
1495 assert (offset < aop->size);
1496 rIdx = aop->aopu.aop_reg[offset]->rIdx;
1498 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1499 PCOR(pcop)->rIdx = rIdx;
1500 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1501 PCOR(pcop)->r->wasUsed=1;
1502 PCOR(pcop)->r->isFree=0;
1504 PCOR(pcop)->instance = offset;
1505 pcop->type = PCOR(pcop)->r->pc_type;
1506 //rs = aop->aopu.aop_reg[offset]->name;
1507 DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1512 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1513 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1514 //if(PCOR(pcop)->r == NULL)
1515 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1519 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1522 DEBUGpic14_emitcode(";","%d %s",__LINE__,aop->aopu.aop_str[offset]);
1523 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1525 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1526 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1527 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1528 pcop->type = PCOR(pcop)->r->pc_type;
1529 pcop->name = PCOR(pcop)->r->name;
1536 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1538 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1539 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1540 switch (aop->aopu.pcop->type)
1543 pcop = pCodeOpCopy (aop->aopu.pcop);
1544 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1545 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1546 PCOI(pcop)->index += offset;
1547 //PCOI(pcop)->offset = 0;
1550 pcop = pCodeOpCopy (aop->aopu.pcop);
1551 PCOR(pcop)->instance = offset;
1554 assert ( !"unhandled pCode type" );
1560 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1561 "popGet got unsupported aop->type");
1565 /*-----------------------------------------------------------------*/
1566 /* popGetAddr - access the low/high word of a symbol (immediate) */
1567 /* (for non-PO_IMMEDIATEs this is the same as popGet) */
1568 /*-----------------------------------------------------------------*/
1569 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1571 if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1573 pCodeOp *pcop = aop->aopu.pcop;
1574 assert (offset <= GPTRSIZE);
1576 /* special case: index >= 2 should return GPOINTER-style values */
1579 pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1583 pcop = pCodeOpCopy (pcop);
1584 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1585 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1586 PCOI(pcop)->offset += offset;
1587 PCOI(pcop)->index += index;
1588 //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);
1591 return popGet (aop, offset + index);
1595 /*-----------------------------------------------------------------*/
1596 /* aopPut - puts a string for a aop */
1597 /*-----------------------------------------------------------------*/
1598 void aopPut (asmop *aop, char *s, int offset)
1603 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1605 if (aop->size && offset > ( aop->size - 1)) {
1606 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1607 "aopPut got offset > aop->size");
1611 /* will assign value to value */
1612 /* depending on where it is ofcourse */
1613 switch (aop->type) {
1616 sprintf(d,"(%s + %d)",
1617 aop->aopu.aop_dir,offset);
1618 fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1621 sprintf(d,"%s",aop->aopu.aop_dir);
1624 DEBUGpic14_emitcode(";","%d",__LINE__);
1626 pic14_emitcode("movf","%s,w",s);
1627 pic14_emitcode("movwf","%s",d);
1630 pic14_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
1631 if(offset >= aop->size) {
1632 emitpcode(POC_CLRF,popGet(aop,offset));
1635 emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
1638 emitpcode(POC_MOVWF,popGet(aop,offset));
1644 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1645 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1648 strcmp(s,"r0") == 0 ||
1649 strcmp(s,"r1") == 0 ||
1650 strcmp(s,"r2") == 0 ||
1651 strcmp(s,"r3") == 0 ||
1652 strcmp(s,"r4") == 0 ||
1653 strcmp(s,"r5") == 0 ||
1654 strcmp(s,"r6") == 0 ||
1655 strcmp(s,"r7") == 0 )
1656 pic14_emitcode("mov","%s,%s ; %d",
1657 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1661 if(strcmp(s,"W")==0 )
1662 pic14_emitcode("movf","%s,w ; %d",s,__LINE__);
1664 pic14_emitcode("movwf","%s",
1665 aop->aopu.aop_reg[offset]->name);
1667 if(strcmp(s,zero)==0) {
1668 emitpcode(POC_CLRF,popGet(aop,offset));
1670 } else if(strcmp(s,"W")==0) {
1671 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1672 pcop->type = PO_GPR_REGISTER;
1674 PCOR(pcop)->rIdx = -1;
1675 PCOR(pcop)->r = NULL;
1677 DEBUGpic14_emitcode(";","%d",__LINE__);
1678 pcop->name = Safe_strdup(s);
1679 emitpcode(POC_MOVFW,pcop);
1680 emitpcode(POC_MOVWF,popGet(aop,offset));
1681 } else if(strcmp(s,one)==0) {
1682 emitpcode(POC_CLRF,popGet(aop,offset));
1683 emitpcode(POC_INCF,popGet(aop,offset));
1685 emitpcode(POC_MOVWF,popGet(aop,offset));
1693 if (aop->type == AOP_DPTR2)
1699 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1700 "aopPut writting to code space");
1704 while (offset > aop->coff) {
1706 pic14_emitcode ("inc","dptr");
1709 while (offset < aop->coff) {
1711 pic14_emitcode("lcall","__decdptr");
1716 /* if not in accumulater */
1719 pic14_emitcode ("movx","@dptr,a");
1721 if (aop->type == AOP_DPTR2)
1729 while (offset > aop->coff) {
1731 pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1733 while (offset < aop->coff) {
1735 pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1741 pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1746 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1748 if (strcmp(s,"r0") == 0 ||
1749 strcmp(s,"r1") == 0 ||
1750 strcmp(s,"r2") == 0 ||
1751 strcmp(s,"r3") == 0 ||
1752 strcmp(s,"r4") == 0 ||
1753 strcmp(s,"r5") == 0 ||
1754 strcmp(s,"r6") == 0 ||
1755 strcmp(s,"r7") == 0 ) {
1757 sprintf(buffer,"a%s",s);
1758 pic14_emitcode("mov","@%s,%s",
1759 aop->aopu.aop_ptr->name,buffer);
1761 pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1766 if (strcmp(s,"a") == 0)
1767 pic14_emitcode("push","acc");
1769 pic14_emitcode("push","%s",s);
1774 /* if bit variable */
1775 if (!aop->aopu.aop_dir) {
1776 pic14_emitcode("clr","a");
1777 pic14_emitcode("rlc","a");
1780 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1783 pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1786 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1788 lbl = newiTempLabel(NULL);
1790 if (strcmp(s,"a")) {
1793 pic14_emitcode("clr","c");
1794 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1795 pic14_emitcode("cpl","c");
1796 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1797 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1804 if (strcmp(aop->aopu.aop_str[offset],s))
1805 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1810 if (!offset && (strcmp(s,"acc") == 0))
1813 if (strcmp(aop->aopu.aop_str[offset],s))
1814 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1818 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1819 "aopPut got unsupported aop->type");
1825 /*-----------------------------------------------------------------*/
1826 /* mov2w_op - generate either a MOVLW or MOVFW based operand type */
1827 /*-----------------------------------------------------------------*/
1828 static void mov2w_op (operand *op, int offset)
1833 /* for PO_IMMEDIATEs: use address or value? */
1834 if (op_isLitLike (op))
1836 /* access address of op */
1837 if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
1838 if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
1840 if (offset == GPTRSIZE-1)
1841 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1843 emitpcode (POC_MOVLW, popGetLit (0));
1846 emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
1848 /* access value stored in op */
1849 mov2w (AOP(op), offset);
1854 /*-----------------------------------------------------------------*/
1855 /* mov2w - generate either a MOVLW or MOVFW based operand type */
1856 /*-----------------------------------------------------------------*/
1857 void mov2w (asmop *aop, int offset)
1863 DEBUGpic14_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
1865 if ( aop_isLitLike (aop) )
1866 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1868 emitpcode(POC_MOVFW,popGet(aop,offset));
1872 static void movwf (asmop *op, int offset)
1874 emitpcode (POC_MOVWF, popGet(op, offset));
1877 static pCodeOp *get_argument_pcop (int idx)
1879 assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1880 return popRegFromIdx (Gstack_base_addr - (idx - 1));
1883 static pCodeOp *get_return_val_pcop (int offset)
1885 assert (offset > 0 && "the most significant byte is returned via WREG");
1886 return popRegFromIdx (Gstack_base_addr - (offset - 1));
1889 static void pass_argument (operand *op, int offset, int idx)
1892 mov2w_op (op, offset);
1894 emitpcode(POC_MOVWF, get_argument_pcop (idx));
1897 static void get_returnvalue (operand *op, int offset, int idx)
1900 emitpcode(POC_MOVFW, get_return_val_pcop (idx));
1901 movwf(AOP(op), offset);
1904 static void call_libraryfunc (char *name)
1906 /* library code might reside in different page... */
1907 emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1908 /* call the library function */
1909 emitpcode (POC_CALL, popGetExternal (name));
1910 /* might return from different page... */
1911 emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1914 /*-----------------------------------------------------------------*/
1915 /* reAdjustPreg - points a register back to where it should */
1916 /*-----------------------------------------------------------------*/
1917 static void reAdjustPreg (asmop *aop)
1921 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1923 if ((size = aop->size) <= 1)
1926 switch (aop->type) {
1930 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1934 if (aop->type == AOP_DPTR2)
1940 pic14_emitcode("lcall","__decdptr");
1943 if (aop->type == AOP_DPTR2)
1956 /*-----------------------------------------------------------------*/
1957 /* opIsGptr: returns non-zero if the passed operand is */
1958 /* a generic pointer type. */
1959 /*-----------------------------------------------------------------*/
1960 static int opIsGptr(operand *op)
1962 sym_link *type = operandType(op);
1964 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1965 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1973 /*-----------------------------------------------------------------*/
1974 /* pic14_getDataSize - get the operand data size */
1975 /*-----------------------------------------------------------------*/
1976 int pic14_getDataSize(operand *op)
1980 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1983 size = getSize(OP_SYM_ETYPE(op));
1985 //return AOP_SIZE(op);
1987 // tsd- in the pic port, the genptr size is 1, so this code here
1988 // fails. ( in the 8051 port, the size was 4).
1990 size = AOP_SIZE(op);
1991 if (IS_GENPTR(OP_SYM_TYPE(op)))
1993 sym_link *type = operandType(op);
1994 if (IS_GENPTR(type))
1996 /* generic pointer; arithmetic operations
1997 * should ignore the high byte (pointer type).
2000 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2007 /*-----------------------------------------------------------------*/
2008 /* pic14_outAcc - output Acc */
2009 /*-----------------------------------------------------------------*/
2010 void pic14_outAcc(operand *result)
2013 DEBUGpic14_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2014 DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
2017 size = pic14_getDataSize(result);
2019 emitpcode(POC_MOVWF,popGet(AOP(result),0));
2022 /* unsigned or positive */
2024 emitpcode(POC_CLRF,popGet(AOP(result),offset++));
2029 /*-----------------------------------------------------------------*/
2030 /* pic14_outBitC - output a bit C */
2031 /*-----------------------------------------------------------------*/
2032 void pic14_outBitC(operand *result)
2035 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2036 /* if the result is bit */
2037 if (AOP_TYPE(result) == AOP_CRY)
2038 aopPut(AOP(result),"c",0);
2040 pic14_emitcode("clr","a ; %d", __LINE__);
2041 pic14_emitcode("rlc","a");
2042 pic14_outAcc(result);
2046 /*-----------------------------------------------------------------*/
2047 /* pic14_toBoolean - emit code for orl a,operator(sizeop) */
2048 /*-----------------------------------------------------------------*/
2049 void pic14_toBoolean(operand *oper)
2051 int size = AOP_SIZE(oper);
2054 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2059 /* MOVFW does not load the flags... */
2060 if (AOP_TYPE(oper) == AOP_ACC) {
2061 emitpcode(POC_IORLW, popGetLit(0));
2064 emitpcode(POC_MOVLW, popGetLit(0));
2068 if ( AOP_TYPE(oper) != AOP_ACC) {
2069 emitpcode(POC_MOVFW,popGet(AOP(oper),0));
2074 while (offset < size) {
2075 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
2077 /* Z is set iff (oper == 0) */
2081 /*-----------------------------------------------------------------*/
2082 /* genNot - generate code for ! operation */
2083 /*-----------------------------------------------------------------*/
2084 static void genNot (iCode *ic)
2091 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2092 /* assign asmOps to operand & result */
2093 aopOp (IC_LEFT(ic),ic,FALSE);
2094 aopOp (IC_RESULT(ic),ic,TRUE);
2096 DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2097 /* if in bit space then a special case */
2098 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2099 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2100 emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
2101 emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
2103 emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
2104 emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
2105 emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
2110 size = AOP_SIZE(IC_LEFT(ic));
2111 mov2w (AOP(IC_LEFT(ic)),0);
2114 if (op_isLitLike (IC_LEFT(ic)))
2115 emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
2117 emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
2119 emitpcode(POC_MOVLW, popGetLit (0));
2121 emitpcode(POC_MOVLW, popGetLit (1));
2122 movwf(AOP(IC_RESULT(ic)), 0);
2124 for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
2126 emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
2131 /* release the aops */
2132 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2133 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2137 /*-----------------------------------------------------------------*/
2138 /* genCpl - generate code for complement */
2139 /*-----------------------------------------------------------------*/
2140 static void genCpl (iCode *ic)
2142 operand *left, *result;
2147 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2148 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2149 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2151 /* if both are in bit space then
2153 if (AOP_TYPE(result) == AOP_CRY &&
2154 AOP_TYPE(left) == AOP_CRY ) {
2156 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir);
2157 pic14_emitcode("cpl","c");
2158 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir);
2162 size = AOP_SIZE(result);
2163 if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
2166 if(AOP_TYPE(left) == AOP_ACC)
2167 emitpcode(POC_XORLW, popGetLit(0xff));
2169 emitpcode(POC_COMFW,popGet(AOP(left),offset));
2171 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
2174 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2178 /* release the aops */
2179 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2180 freeAsmop(result,NULL,ic,TRUE);
2183 /*-----------------------------------------------------------------*/
2184 /* genUminusFloat - unary minus for floating points */
2185 /*-----------------------------------------------------------------*/
2186 static void genUminusFloat(operand *op,operand *result)
2188 int size ,offset =0 ;
2193 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2194 /* for this we just need to flip the
2195 first it then copy the rest in place */
2196 size = AOP_SIZE(op) - 1;
2197 l = aopGet(AOP(op),3,FALSE,FALSE);
2201 pic14_emitcode("cpl","acc.7");
2202 aopPut(AOP(result),"a",3);
2206 aopGet(AOP(op),offset,FALSE,FALSE),
2212 /*-----------------------------------------------------------------*/
2213 /* genUminus - unary minus code generation */
2214 /*-----------------------------------------------------------------*/
2215 static void genUminus (iCode *ic)
2218 sym_link *optype, *rtype;
2222 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2224 aopOp(IC_LEFT(ic),ic,FALSE);
2225 aopOp(IC_RESULT(ic),ic,TRUE);
2227 /* if both in bit space then special
2229 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2230 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2232 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0));
2233 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2234 emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0));
2239 optype = operandType(IC_LEFT(ic));
2240 rtype = operandType(IC_RESULT(ic));
2242 /* if float then do float stuff */
2243 if (IS_FLOAT(optype)) {
2244 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2248 /* otherwise subtract from zero by taking the 2's complement */
2249 size = AOP_SIZE(IC_LEFT(ic));
2251 for(i=0; i<size; i++) {
2252 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2253 emitpcode(POC_COMF, popGet(AOP(IC_LEFT(ic)),i));
2255 emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2256 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2260 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0));
2261 for(i=1; i<size; i++) {
2263 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),i));
2267 /* release the aops */
2268 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2269 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2272 /*-----------------------------------------------------------------*/
2273 /* saveRegisters - will look for a call and save the registers */
2274 /*-----------------------------------------------------------------*/
2275 static void saveRegisters(iCode *lic)
2284 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2286 for (ic = lic ; ic ; ic = ic->next)
2287 if (ic->op == CALL || ic->op == PCALL)
2291 fprintf(stderr,"found parameter push with no function call\n");
2295 /* if the registers have been saved already then
2297 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2300 /* find the registers in use at this time
2301 and push them away to safety */
2302 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2306 if (options.useXstack) {
2307 if (bitVectBitValue(rsave,R0_IDX))
2308 pic14_emitcode("mov","b,r0");
2309 pic14_emitcode("mov","r0,%s",spname);
2310 for (i = 0 ; i < pic14_nRegs ; i++) {
2311 if (bitVectBitValue(rsave,i)) {
2313 pic14_emitcode("mov","a,b");
2315 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2316 pic14_emitcode("movx","@r0,a");
2317 pic14_emitcode("inc","r0");
2320 pic14_emitcode("mov","%s,r0",spname);
2321 if (bitVectBitValue(rsave,R0_IDX))
2322 pic14_emitcode("mov","r0,b");
2324 //for (i = 0 ; i < pic14_nRegs ; i++) {
2325 // if (bitVectBitValue(rsave,i))
2326 // pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2329 dtype = operandType(IC_LEFT(ic));
2330 if (currFunc && dtype &&
2331 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2332 IFFUNC_ISISR(currFunc->type) &&
2335 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2338 /*-----------------------------------------------------------------*/
2339 /* unsaveRegisters - pop the pushed registers */
2340 /*-----------------------------------------------------------------*/
2341 static void unsaveRegisters (iCode *ic)
2348 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2349 /* find the registers in use at this time
2350 and push them away to safety */
2351 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2354 if (options.useXstack) {
2355 pic14_emitcode("mov","r0,%s",spname);
2356 for (i = pic14_nRegs ; i >= 0 ; i--) {
2357 if (bitVectBitValue(rsave,i)) {
2358 pic14_emitcode("dec","r0");
2359 pic14_emitcode("movx","a,@r0");
2361 pic14_emitcode("mov","b,a");
2363 pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2367 pic14_emitcode("mov","%s,r0",spname);
2368 if (bitVectBitValue(rsave,R0_IDX))
2369 pic14_emitcode("mov","r0,b");
2371 //for (i = pic14_nRegs ; i >= 0 ; i--) {
2372 // if (bitVectBitValue(rsave,i))
2373 // pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2379 /*-----------------------------------------------------------------*/
2381 /*-----------------------------------------------------------------*/
2382 static void pushSide(operand * oper, int size)
2386 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2388 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2389 if (AOP_TYPE(oper) != AOP_REG &&
2390 AOP_TYPE(oper) != AOP_DIR &&
2392 pic14_emitcode("mov","a,%s",l);
2393 pic14_emitcode("push","acc");
2395 pic14_emitcode("push","%s",l);
2400 /*-----------------------------------------------------------------*/
2401 /* assignResultValue - */
2402 /*-----------------------------------------------------------------*/
2403 static void assignResultValue(operand * oper)
2405 int size = AOP_SIZE(oper);
2410 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2412 DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2414 /* assign MSB first (passed via WREG) */
2416 get_returnvalue (oper, size, offset + GpsuedoStkPtr);
2422 /*-----------------------------------------------------------------*/
2423 /* genIpush - genrate code for pushing this gets a little complex */
2424 /*-----------------------------------------------------------------*/
2425 static void genIpush (iCode *ic)
2429 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2431 int size, offset = 0 ;
2435 /* if this is not a parm push : ie. it is spill push
2436 and spill push is always done on the local stack */
2437 if (!ic->parmPush) {
2439 /* and the item is spilt then do nothing */
2440 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2443 aopOp(IC_LEFT(ic),ic,FALSE);
2444 size = AOP_SIZE(IC_LEFT(ic));
2445 /* push it on the stack */
2447 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2452 pic14_emitcode("push","%s",l);
2457 /* this is a paramter push: in this case we call
2458 the routine to find the call and save those
2459 registers that need to be saved */
2462 /* then do the push */
2463 aopOp(IC_LEFT(ic),ic,FALSE);
2466 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2467 size = AOP_SIZE(IC_LEFT(ic));
2470 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2471 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
2472 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2474 pic14_emitcode("mov","a,%s",l);
2475 pic14_emitcode("push","acc");
2477 pic14_emitcode("push","%s",l);
2480 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2484 /*-----------------------------------------------------------------*/
2485 /* genIpop - recover the registers: can happen only for spilling */
2486 /*-----------------------------------------------------------------*/
2487 static void genIpop (iCode *ic)
2491 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2492 assert (!"genIpop -- unimplemented");
2497 /* if the temp was not pushed then */
2498 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2501 aopOp(IC_LEFT(ic),ic,FALSE);
2502 size = AOP_SIZE(IC_LEFT(ic));
2505 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2508 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2512 /*-----------------------------------------------------------------*/
2513 /* unsaverbank - restores the resgister bank from stack */
2514 /*-----------------------------------------------------------------*/
2515 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2519 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2525 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2527 if (options.useXstack) {
2529 r = getFreePtr(ic,&aop,FALSE);
2532 pic14_emitcode("mov","%s,_spx",r->name);
2533 pic14_emitcode("movx","a,@%s",r->name);
2534 pic14_emitcode("mov","psw,a");
2535 pic14_emitcode("dec","%s",r->name);
2538 pic14_emitcode ("pop","psw");
2541 for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2542 if (options.useXstack) {
2543 pic14_emitcode("movx","a,@%s",r->name);
2544 //pic14_emitcode("mov","(%s+%d),a",
2545 // regspic14[i].base,8*bank+regspic14[i].offset);
2546 pic14_emitcode("dec","%s",r->name);
2549 pic14_emitcode("pop",""); //"(%s+%d)",
2550 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2553 if (options.useXstack) {
2555 pic14_emitcode("mov","_spx,%s",r->name);
2556 freeAsmop(NULL,aop,ic,TRUE);
2562 /*-----------------------------------------------------------------*/
2563 /* saverbank - saves an entire register bank on the stack */
2564 /*-----------------------------------------------------------------*/
2565 static void saverbank (int bank, iCode *ic, bool pushPsw)
2569 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2575 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2576 if (options.useXstack) {
2579 r = getFreePtr(ic,&aop,FALSE);
2580 pic14_emitcode("mov","%s,_spx",r->name);
2584 for (i = 0 ; i < pic14_nRegs ;i++) {
2585 if (options.useXstack) {
2586 pic14_emitcode("inc","%s",r->name);
2587 //pic14_emitcode("mov","a,(%s+%d)",
2588 // regspic14[i].base,8*bank+regspic14[i].offset);
2589 pic14_emitcode("movx","@%s,a",r->name);
2591 pic14_emitcode("push","");// "(%s+%d)",
2592 //regspic14[i].base,8*bank+regspic14[i].offset);
2596 if (options.useXstack) {
2597 pic14_emitcode("mov","a,psw");
2598 pic14_emitcode("movx","@%s,a",r->name);
2599 pic14_emitcode("inc","%s",r->name);
2600 pic14_emitcode("mov","_spx,%s",r->name);
2601 freeAsmop (NULL,aop,ic,TRUE);
2604 pic14_emitcode("push","psw");
2606 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2612 /*-----------------------------------------------------------------*/
2613 /* genCall - generates a call statement */
2614 /*-----------------------------------------------------------------*/
2615 static void genCall (iCode *ic)
2624 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2626 /* if caller saves & we have not saved then */
2630 /* if we are calling a function that is not using
2631 the same register bank then we need to save the
2632 destination registers on the stack */
2633 dtype = operandType(IC_LEFT(ic));
2634 if (currFunc && dtype &&
2635 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2636 IFFUNC_ISISR(currFunc->type) &&
2639 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2641 /* if send set is not empty the assign */
2644 /* For the Pic port, there is no data stack.
2645 * So parameters passed to functions are stored
2646 * in registers. (The pCode optimizer will get
2647 * rid of most of these :).
2649 int psuedoStkPtr=-1;
2650 int firstTimeThruLoop = 1;
2652 _G.sendSet = reverseSet(_G.sendSet);
2654 /* First figure how many parameters are getting passed */
2655 for (sic = setFirstItem(_G.sendSet) ; sic ;
2656 sic = setNextItem(_G.sendSet)) {
2658 aopOp(IC_LEFT(sic),sic,FALSE);
2659 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2660 freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2663 for (sic = setFirstItem(_G.sendSet) ; sic ;
2664 sic = setNextItem(_G.sendSet)) {
2665 int size, offset = 0;
2667 aopOp(IC_LEFT(sic),sic,FALSE);
2668 size = AOP_SIZE(IC_LEFT(sic));
2671 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2672 AopType(AOP_TYPE(IC_LEFT(sic))));
2674 if(!firstTimeThruLoop) {
2675 /* If this is not the first time we've been through the loop
2676 * then we need to save the parameter in a temporary
2677 * register. The last byte of the last parameter is
2679 emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2682 firstTimeThruLoop=0;
2684 mov2w_op (IC_LEFT(sic), offset);
2687 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2692 sym = OP_SYMBOL(IC_LEFT(ic));
2693 name = sym->rname[0] ? sym->rname : sym->name;
2694 isExtern = IS_EXTERN(sym->etype) || pic14_inISR;
2696 /* Extern functions and ISRs maybe on a different page;
2697 * must call pagesel */
2698 emitpcode(POC_PAGESEL,popGetWithString(name,1));
2700 emitpcode(POC_CALL,popGetWithString(name,isExtern));
2702 /* May have returned from a different page;
2703 * must use pagesel to restore PCLATH before next
2704 * goto or call instruction */
2705 emitpcode(POC_PAGESEL,popGetWithString("$",0));
2708 /* if we need assign a result value */
2709 if ((IS_ITEMP(IC_RESULT(ic)) &&
2710 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2711 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2712 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2715 aopOp(IC_RESULT(ic),ic,FALSE);
2718 assignResultValue(IC_RESULT(ic));
2720 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2721 AopType(AOP_TYPE(IC_RESULT(ic))));
2723 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2726 /* if register bank was saved then pop them */
2728 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2730 /* if we hade saved some registers then unsave them */
2731 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2732 unsaveRegisters (ic);
2737 /*-----------------------------------------------------------------*/
2738 /* genPcall - generates a call by pointer statement */
2739 /*-----------------------------------------------------------------*/
2740 static void genPcall (iCode *ic)
2743 symbol *albl = newiTempLabel(NULL);
2744 symbol *blbl = newiTempLabel(NULL);
2751 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2752 /* if caller saves & we have not saved then */
2756 /* if we are calling a function that is not using
2757 the same register bank then we need to save the
2758 destination registers on the stack */
2759 dtype = operandType(IC_LEFT(ic));
2760 if (currFunc && dtype &&
2761 IFFUNC_ISISR(currFunc->type) &&
2762 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2763 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2766 aopOp(left,ic,FALSE);
2767 DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2769 poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2771 pushSide(IC_LEFT(ic), FPTRSIZE);
2773 /* if send set is not empty, assign parameters */
2776 DEBUGpic14_emitcode ("; ***","%s %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2777 /* no way to pass args - W always gets used to make the call */
2779 /* first idea - factor out a common helper function and call it.
2780 But don't know how to get it generated only once in its own block
2782 if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2785 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2786 DEBUGpic14_emitcode ("; ***","%s %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2787 buffer = Safe_calloc(1,strlen(rname)+16);
2788 sprintf(buffer, "%s_goto_helper", rname);
2789 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2793 emitpcode(POC_CALL,popGetLabel(albl->key));
2794 pcop = popGetLabel(blbl->key);
2795 emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
2796 emitpcode(POC_GOTO,pcop);
2797 emitpLabel(albl->key);
2799 emitpcode(poc,popGetAddr(AOP(left),1,0));
2800 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2801 emitpcode(poc,popGetAddr(AOP(left),0,0));
2802 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2804 emitpLabel(blbl->key);
2806 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2808 /* if we need to assign a result value */
2809 if ((IS_ITEMP(IC_RESULT(ic)) &&
2810 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2811 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2812 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2815 aopOp(IC_RESULT(ic),ic,FALSE);
2820 assignResultValue(IC_RESULT(ic));
2822 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2825 /* if register bank was saved then unsave them */
2826 if (currFunc && dtype &&
2827 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2828 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2830 /* if we hade saved some registers then
2833 unsaveRegisters (ic);
2837 /*-----------------------------------------------------------------*/
2838 /* resultRemat - result is rematerializable */
2839 /*-----------------------------------------------------------------*/
2840 static int resultRemat (iCode *ic)
2842 // DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2845 if (SKIP_IC(ic) || ic->op == IFX)
2848 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2849 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2850 if (sym->remat && !POINTER_SET(ic))
2857 #if defined(__BORLANDC__) || defined(_MSC_VER)
2858 #define STRCASECMP stricmp
2860 #define STRCASECMP strcasecmp
2864 /*-----------------------------------------------------------------*/
2865 /* inExcludeList - return 1 if the string is in exclude Reg list */
2866 /*-----------------------------------------------------------------*/
2867 static bool inExcludeList(char *s)
2869 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2872 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2873 if (options.excludeRegs[i] &&
2874 STRCASECMP(options.excludeRegs[i],"none") == 0)
2877 for ( i = 0 ; options.excludeRegs[i]; i++) {
2878 if (options.excludeRegs[i] &&
2879 STRCASECMP(s,options.excludeRegs[i]) == 0)
2886 /*-----------------------------------------------------------------*/
2887 /* genFunction - generated code for function entry */
2888 /*-----------------------------------------------------------------*/
2889 static void genFunction (iCode *ic)
2896 DEBUGpic14_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2898 labelOffset += (max_key+4);
2902 /* create the function header */
2903 pic14_emitcode(";","-----------------------------------------");
2904 pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2905 pic14_emitcode(";","-----------------------------------------");
2907 /* prevent this symbol from being emitted as 'extern' */
2908 pic14_stringInSet(sym->rname, &pic14_localFunctions, 1);
2910 pic14_emitcode("","%s:",sym->rname);
2911 addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2913 ftype = operandType(IC_LEFT(ic));
2915 /* if critical function then turn interrupts off */
2916 if (IFFUNC_ISCRITICAL(ftype))
2917 pic14_emitcode("clr","ea");
2919 /* here we need to generate the equates for the
2920 register bank if required */
2922 if (FUNC_REGBANK(ftype) != rbank) {
2925 rbank = FUNC_REGBANK(ftype);
2926 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2927 if (strcmp(regspic14[i].base,"0") == 0)
2928 pic14_emitcode("","%s = 0x%02x",
2930 8*rbank+regspic14[i].offset);
2932 pic14_emitcode ("","%s = %s + 0x%02x",
2935 8*rbank+regspic14[i].offset);
2940 /* if this is an interrupt service routine */
2942 if (IFFUNC_ISISR(sym->type)) {
2944 /* already done in pic14createInterruptVect() - delete me
2945 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2946 emitpcodeNULLop(POC_NOP);
2947 emitpcodeNULLop(POC_NOP);
2948 emitpcodeNULLop(POC_NOP);
2950 emitpcode(POC_MOVWF, popCopyReg(&pc_wsave));
2951 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2952 emitpcode(POC_CLRF, popCopyReg(&pc_status));
2953 emitpcode(POC_MOVWF, popCopyReg(&pc_ssave));
2954 emitpcode(POC_MOVFW, popCopyReg(&pc_pclath));
2955 emitpcode(POC_MOVWF, popCopyReg(&pc_psave));
2956 emitpcode(POC_CLRF, popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2958 pBlockConvert2ISR(pb);
2959 pic14_hasInterrupt = 1;
2961 if (!inExcludeList("acc"))
2962 pic14_emitcode ("push","acc");
2963 if (!inExcludeList("b"))
2964 pic14_emitcode ("push","b");
2965 if (!inExcludeList("dpl"))
2966 pic14_emitcode ("push","dpl");
2967 if (!inExcludeList("dph"))
2968 pic14_emitcode ("push","dph");
2969 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2971 pic14_emitcode ("push", "dpx");
2972 /* Make sure we're using standard DPTR */
2973 pic14_emitcode ("push", "dps");
2974 pic14_emitcode ("mov", "dps, #0x00");
2975 if (options.stack10bit)
2977 /* This ISR could conceivably use DPTR2. Better save it. */
2978 pic14_emitcode ("push", "dpl1");
2979 pic14_emitcode ("push", "dph1");
2980 pic14_emitcode ("push", "dpx1");
2983 /* if this isr has no bank i.e. is going to
2984 run with bank 0 , then we need to save more
2986 if (!FUNC_REGBANK(sym->type)) {
2988 /* if this function does not call any other
2989 function then we can be economical and
2990 save only those registers that are used */
2991 if (! IFFUNC_HASFCALL(sym->type)) {
2994 /* if any registers used */
2995 if (sym->regsUsed) {
2996 /* save the registers used */
2997 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2998 if (bitVectBitValue(sym->regsUsed,i) ||
2999 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3000 pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);
3005 /* this function has a function call cannot
3006 determines register usage so we will have the
3008 saverbank(0,ic,FALSE);
3013 /* if callee-save to be used for this function
3014 then save the registers being used in this function */
3015 if (IFFUNC_CALLEESAVES(sym->type)) {
3018 /* if any registers used */
3019 if (sym->regsUsed) {
3020 /* save the registers used */
3021 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3022 if (bitVectBitValue(sym->regsUsed,i) ||
3023 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
3024 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
3032 /* set the register bank to the desired value */
3033 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
3034 pic14_emitcode("push","psw");
3035 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);
3038 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3040 if (options.useXstack) {
3041 pic14_emitcode("mov","r0,%s",spname);
3042 pic14_emitcode("mov","a,_bp");
3043 pic14_emitcode("movx","@r0,a");
3044 pic14_emitcode("inc","%s",spname);
3048 /* set up the stack */
3049 pic14_emitcode ("push","_bp"); /* save the callers stack */
3051 pic14_emitcode ("mov","_bp,%s",spname);
3054 /* adjust the stack for the function */
3059 werror(W_STACK_OVERFLOW,sym->name);
3061 if (i > 3 && sym->recvSize < 4) {
3063 pic14_emitcode ("mov","a,sp");
3064 pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3065 pic14_emitcode ("mov","sp,a");
3070 pic14_emitcode("inc","sp");
3075 pic14_emitcode ("mov","a,_spx");
3076 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3077 pic14_emitcode ("mov","_spx,a");
3082 /*-----------------------------------------------------------------*/
3083 /* genEndFunction - generates epilogue for functions */
3084 /*-----------------------------------------------------------------*/
3085 static void genEndFunction (iCode *ic)
3087 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3091 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3093 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3095 pic14_emitcode ("mov","%s,_bp",spname);
3098 /* if use external stack but some variables were
3099 added to the local stack then decrement the
3101 if (options.useXstack && sym->stack) {
3102 pic14_emitcode("mov","a,sp");
3103 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3104 pic14_emitcode("mov","sp,a");
3108 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3109 if (options.useXstack) {
3110 pic14_emitcode("mov","r0,%s",spname);
3111 pic14_emitcode("movx","a,@r0");
3112 pic14_emitcode("mov","_bp,a");
3113 pic14_emitcode("dec","%s",spname);
3117 pic14_emitcode ("pop","_bp");
3121 /* restore the register bank */
3122 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3123 pic14_emitcode ("pop","psw");
3125 if (IFFUNC_ISISR(sym->type)) {
3127 /* now we need to restore the registers */
3128 /* if this isr has no bank i.e. is going to
3129 run with bank 0 , then we need to save more
3131 if (!FUNC_REGBANK(sym->type)) {
3133 /* if this function does not call any other
3134 function then we can be economical and
3135 save only those registers that are used */
3136 if (! IFFUNC_HASFCALL(sym->type)) {
3139 /* if any registers used */
3140 if (sym->regsUsed) {
3141 /* save the registers used */
3142 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3143 if (bitVectBitValue(sym->regsUsed,i) ||
3144 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3145 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3150 /* this function has a function call cannot
3151 determines register usage so we will have the
3153 unsaverbank(0,ic,FALSE);
3157 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3159 if (options.stack10bit)
3161 pic14_emitcode ("pop", "dpx1");
3162 pic14_emitcode ("pop", "dph1");
3163 pic14_emitcode ("pop", "dpl1");
3165 pic14_emitcode ("pop", "dps");
3166 pic14_emitcode ("pop", "dpx");
3168 if (!inExcludeList("dph"))
3169 pic14_emitcode ("pop","dph");
3170 if (!inExcludeList("dpl"))
3171 pic14_emitcode ("pop","dpl");
3172 if (!inExcludeList("b"))
3173 pic14_emitcode ("pop","b");
3174 if (!inExcludeList("acc"))
3175 pic14_emitcode ("pop","acc");
3177 if (IFFUNC_ISCRITICAL(sym->type))
3178 pic14_emitcode("setb","ea");
3181 /* if debug then send end of function */
3182 /* if (options.debug && currFunc) { */
3184 debugFile->writeEndFunction (currFunc, ic, 1);
3187 pic14_emitcode ("reti","");
3188 emitpcode(POC_MOVFW, popCopyReg(&pc_psave));
3189 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
3190 emitpcode(POC_CLRF, popCopyReg(&pc_status));
3191 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3192 emitpcode(POC_MOVWF, popCopyReg(&pc_status));
3193 emitpcode(POC_SWAPF, popCopyReg(&pc_wsave));
3194 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3195 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3196 emitpcodeNULLop(POC_RETFIE);
3199 if (IFFUNC_ISCRITICAL(sym->type))
3200 pic14_emitcode("setb","ea");
3202 if (IFFUNC_CALLEESAVES(sym->type)) {
3205 /* if any registers used */
3206 if (sym->regsUsed) {
3207 /* save the registers used */
3208 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3209 if (bitVectBitValue(sym->regsUsed,i) ||
3210 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3211 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3217 /* if debug then send end of function */
3219 debugFile->writeEndFunction (currFunc, ic, 1);
3222 pic14_emitcode ("return","");
3223 emitpcodeNULLop(POC_RETURN);
3225 /* Mark the end of a function */
3226 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3231 /*-----------------------------------------------------------------*/
3232 /* genRet - generate code for return statement */
3233 /*-----------------------------------------------------------------*/
3234 static void genRet (iCode *ic)
3236 int size,offset = 0;
3240 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3241 /* if we have no return value then
3242 just generate the "ret" */
3246 /* we have something to return then
3247 move the return value into place */
3248 aopOp(IC_LEFT(ic),ic,FALSE);
3249 size = AOP_SIZE(IC_LEFT(ic));
3251 for (offset = 0; offset < size; offset++)
3253 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
3256 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3259 /* generate a jump to the return label
3260 if the next is not the return statement */
3261 if (!(ic->next && ic->next->op == LABEL &&
3262 IC_LABEL(ic->next) == returnLabel)) {
3264 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3269 /*-----------------------------------------------------------------*/
3270 /* genLabel - generates a label */
3271 /*-----------------------------------------------------------------*/
3272 static void genLabel (iCode *ic)
3276 /* special case never generate */
3277 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3278 if (IC_LABEL(ic) == entryLabel)
3281 emitpLabel(IC_LABEL(ic)->key);
3282 pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3285 /*-----------------------------------------------------------------*/
3286 /* genGoto - generates a goto */
3287 /*-----------------------------------------------------------------*/
3289 static void genGoto (iCode *ic)
3293 emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3294 pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3298 /*-----------------------------------------------------------------*/
3299 /* genMultbits :- multiplication of bits */
3300 /*-----------------------------------------------------------------*/
3301 static void genMultbits (operand *left,
3306 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3308 if(!pic14_sameRegs(AOP(result),AOP(right)))
3309 emitpcode(POC_BSF, popGet(AOP(result),0));
3311 emitpcode(POC_BTFSC,popGet(AOP(right),0));
3312 emitpcode(POC_BTFSS,popGet(AOP(left),0));
3313 emitpcode(POC_BCF, popGet(AOP(result),0));
3318 /*-----------------------------------------------------------------*/
3319 /* genMultOneByte : 8 bit multiplication & division */
3320 /*-----------------------------------------------------------------*/
3321 static void genMultOneByte (operand *left,
3325 char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
3333 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3334 DEBUGpic14_AopType(__LINE__,left,right,result);
3335 DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3337 /* (if two literals, the value is computed before) */
3338 /* if one literal, literal on the right */
3339 if (AOP_TYPE(left) == AOP_LIT){
3345 assert (AOP_SIZE(left) == AOP_SIZE(right));
3347 size = min(AOP_SIZE(result),AOP_SIZE(left));
3348 offset = Gstack_base_addr - (2*size - 1);
3350 /* pass right operand as argument */
3351 for (i=0; i < size; i++)
3353 mov2w (AOP(right), i);
3354 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3357 /* pass left operand as argument */
3358 for (i=0; i < size; i++)
3360 mov2w (AOP(left), i);
3361 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3363 assert (offset == Gstack_base_addr);
3365 /* call library routine */
3366 assert (size > 0 && size <= 4);
3367 call_libraryfunc (func[size]);
3370 movwf (AOP(result), size-1);
3371 for (i=0; i < size - 1; i++)
3373 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
3374 movwf (AOP(result), size - 2 - i);
3377 /* now (zero-/sign) extend the result to its size */
3378 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
3381 /*-----------------------------------------------------------------*/
3382 /* genMult - generates code for multiplication */
3383 /*-----------------------------------------------------------------*/
3384 static void genMult (iCode *ic)
3386 operand *left = IC_LEFT(ic);
3387 operand *right = IC_RIGHT(ic);
3388 operand *result= IC_RESULT(ic);
3392 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3393 /* assign the amsops */
3394 aopOp (left,ic,FALSE);
3395 aopOp (right,ic,FALSE);
3396 aopOp (result,ic,TRUE);
3398 DEBUGpic14_AopType(__LINE__,left,right,result);
3400 /* special cases first */
3402 if (AOP_TYPE(left) == AOP_CRY &&
3403 AOP_TYPE(right)== AOP_CRY) {
3404 genMultbits(left,right,result);
3408 /* if both are of size == 1 */
3409 if (AOP_SIZE(left) == 1 &&
3410 AOP_SIZE(right) == 1 ) {
3411 genMultOneByte(left,right,result);
3415 /* should have been converted to function call */
3419 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3420 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3421 freeAsmop(result,NULL,ic,TRUE);
3424 /*-----------------------------------------------------------------*/
3425 /* genDivbits :- division of bits */
3426 /*-----------------------------------------------------------------*/
3427 static void genDivbits (operand *left,
3436 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3437 /* the result must be bit */
3438 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3439 l = aopGet(AOP(left),0,FALSE,FALSE);
3443 pic14_emitcode("div","ab");
3444 pic14_emitcode("rrc","a");
3445 aopPut(AOP(result),"c",0);
3448 /*-----------------------------------------------------------------*/
3449 /* genDivOneByte : 8 bit division */
3450 /*-----------------------------------------------------------------*/
3451 static void genDivOneByte (operand *left,
3458 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3460 assert (AOP_SIZE(result) == 1);
3461 assert (AOP_SIZE(right) == 1);
3462 assert (AOP_SIZE(left) == 1);
3464 size = min(AOP_SIZE(result),AOP_SIZE(left));
3466 if (AOP_TYPE(right) == AOP_LIT)
3468 /* XXX: might add specialized code */
3471 if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3473 /* unsigned division */
3475 mov2w(AOP(right),0);
3476 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3478 call_libraryfunc("__divuchar");
3479 movwf(AOP(result),0);
3484 temp = popGetTempReg();
3485 lbl = newiTempLabel(NULL);
3487 /* XXX: improve this naive approach:
3488 [result] = [a] / [b]
3489 ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
3493 movwf temp // temp <-- left
3494 movf right,W // W <-- right
3498 subwf temp,F // temp <-- temp - W
3499 skipNC // subwf clears CARRY (i.e. sets BORROW) if temp < W
3501 decf result // we just subtract once too often
3504 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3505 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
3508 emitpcode(POC_MOVWF, temp);
3509 mov2w(AOP(right),0);
3510 emitpcode(POC_CLRF, popGet(AOP(result),0));
3512 emitpLabel(lbl->key);
3513 emitpcode(POC_INCF, popGet(AOP(result),0));
3514 emitpcode(POC_SUBWF, temp);
3516 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3517 emitpcode(POC_DECF, popGet(AOP(result),0));
3522 /* signed division */
3523 mov2w(AOP(right),0);
3524 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3526 call_libraryfunc("__divschar");
3527 movwf(AOP(result),0);
3530 /* now performed the signed/unsigned division -- extend result */
3531 addSign(result, 1, !SPEC_USIGN(operandType(result)));
3534 /*-----------------------------------------------------------------*/
3535 /* genDiv - generates code for division */
3536 /*-----------------------------------------------------------------*/
3537 static void genDiv (iCode *ic)
3539 operand *left = IC_LEFT(ic);
3540 operand *right = IC_RIGHT(ic);
3541 operand *result= IC_RESULT(ic);
3544 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3545 /* assign the amsops */
3546 aopOp (left,ic,FALSE);
3547 aopOp (right,ic,FALSE);
3548 aopOp (result,ic,TRUE);
3550 /* special cases first */
3552 if (AOP_TYPE(left) == AOP_CRY &&
3553 AOP_TYPE(right)== AOP_CRY) {
3554 genDivbits(left,right,result);
3558 /* if both are of size == 1 */
3559 if (AOP_SIZE(left) == 1 &&
3560 AOP_SIZE(right) == 1 ) {
3561 genDivOneByte(left,right,result);
3565 /* should have been converted to function call */
3568 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3569 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3570 freeAsmop(result,NULL,ic,TRUE);
3573 /*-----------------------------------------------------------------*/
3574 /* genModbits :- modulus of bits */
3575 /*-----------------------------------------------------------------*/
3576 static void genModbits (operand *left,
3584 /* the result must be bit */
3585 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3586 l = aopGet(AOP(left),0,FALSE,FALSE);
3590 pic14_emitcode("div","ab");
3591 pic14_emitcode("mov","a,b");
3592 pic14_emitcode("rrc","a");
3593 aopPut(AOP(result),"c",0);
3596 /*-----------------------------------------------------------------*/
3597 /* genModOneByte : 8 bit modulus */
3598 /*-----------------------------------------------------------------*/
3599 static void genModOneByte (operand *left,
3606 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3608 assert (AOP_SIZE(result) == 1);
3609 assert (AOP_SIZE(right) == 1);
3610 assert (AOP_SIZE(left) == 1);
3612 size = min(AOP_SIZE(result),AOP_SIZE(left));
3614 if (AOP_TYPE(right) == AOP_LIT)
3616 /* XXX: might add specialized code */
3619 if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3621 /* unsigned division */
3623 mov2w(AOP(right),0);
3624 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3626 call_libraryfunc("__moduchar");
3627 movwf(AOP(result),0);
3632 lbl = newiTempLabel(NULL);
3634 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3636 /* XXX: improve this naive approach:
3637 [result] = [a] % [b]
3638 ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3642 movwf result // result <-- left
3643 movf right,W // W <-- right
3645 subwf result,F // result <-- result - W
3646 skipNC // subwf clears CARRY (i.e. sets BORROW) if result < W
3648 addwf result, F // we just subtract once too often
3651 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3652 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3654 if (!pic14_sameRegs(AOP(left), AOP(result)))
3657 emitpcode(POC_MOVWF, popGet(AOP(result),0));
3659 mov2w(AOP(right),0);
3661 emitpLabel(lbl->key);
3662 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3664 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3665 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3670 /* signed division */
3671 mov2w(AOP(right),0);
3672 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3674 call_libraryfunc("__modschar");
3675 movwf(AOP(result),0);
3678 /* now we performed the signed/unsigned modulus -- extend result */
3679 addSign(result, 1, !SPEC_USIGN(operandType(result)));
3682 /*-----------------------------------------------------------------*/
3683 /* genMod - generates code for division */
3684 /*-----------------------------------------------------------------*/
3685 static void genMod (iCode *ic)
3687 operand *left = IC_LEFT(ic);
3688 operand *right = IC_RIGHT(ic);
3689 operand *result= IC_RESULT(ic);
3692 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3693 /* assign the amsops */
3694 aopOp (left,ic,FALSE);
3695 aopOp (right,ic,FALSE);
3696 aopOp (result,ic,TRUE);
3698 /* special cases first */
3700 if (AOP_TYPE(left) == AOP_CRY &&
3701 AOP_TYPE(right)== AOP_CRY) {
3702 genModbits(left,right,result);
3706 /* if both are of size == 1 */
3707 if (AOP_SIZE(left) == 1 &&
3708 AOP_SIZE(right) == 1 ) {
3709 genModOneByte(left,right,result);
3713 /* should have been converted to function call */
3717 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3718 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3719 freeAsmop(result,NULL,ic,TRUE);
3722 /*-----------------------------------------------------------------*/
3723 /* genIfxJump :- will create a jump depending on the ifx */
3724 /*-----------------------------------------------------------------*/
3726 note: May need to add parameter to indicate when a variable is in bit space.
3728 static void genIfxJump (iCode *ic, char *jval)
3732 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3733 /* if true label then we jump if condition
3735 if ( IC_TRUE(ic) ) {
3737 if(strcmp(jval,"a") == 0)
3739 else if (strcmp(jval,"c") == 0)
3742 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3743 emitpcode(POC_BTFSC, newpCodeOpBit(jval,-1,1));
3746 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3747 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3751 /* false label is present */
3752 if(strcmp(jval,"a") == 0)
3754 else if (strcmp(jval,"c") == 0)
3757 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3758 emitpcode(POC_BTFSS, newpCodeOpBit(jval,-1,1));
3761 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3762 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3767 /* mark the icode as generated */
3772 /*-----------------------------------------------------------------*/
3774 /*-----------------------------------------------------------------*/
3775 static void genSkip(iCode *ifx,int status_bit)
3781 if ( IC_TRUE(ifx) ) {
3782 switch(status_bit) {
3797 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3798 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3802 switch(status_bit) {
3816 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3817 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3824 /*-----------------------------------------------------------------*/
3826 /*-----------------------------------------------------------------*/
3827 static void genSkipc(resolvedIfx *rifx)
3838 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3839 emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3840 rifx->generated = 1;
3844 /*-----------------------------------------------------------------*/
3846 /*-----------------------------------------------------------------*/
3847 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3853 if( (rifx->condition ^ invert_condition) & 1)
3858 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3859 rifx->generated = 1;
3864 /*-----------------------------------------------------------------*/
3866 /*-----------------------------------------------------------------*/
3867 static void genSkipz(iCode *ifx, int condition)
3870 assert (ifx != NULL);
3878 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3880 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3883 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3885 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3891 /*-----------------------------------------------------------------*/
3893 /*-----------------------------------------------------------------*/
3894 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3901 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3903 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3906 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3907 rifx->generated = 1;
3912 /*-----------------------------------------------------------------*/
3913 /* genChkZeroes :- greater or less than comparison */
3914 /* For each byte in a literal that is zero, inclusive or the */
3915 /* the corresponding byte in the operand with W */
3916 /* returns true if any of the bytes are zero */
3917 /*-----------------------------------------------------------------*/
3918 static int genChkZeroes(operand *op, int lit, int size)
3925 i = (lit >> (size*8)) & 0xff;
3929 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3931 emitpcode(POC_IORFW, popGet(AOP(op),size));
3941 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3942 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
3943 #define DEBUGpc emitpComment
3945 /*-----------------------------------------------------------------*/
3946 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
3947 /* aop (if it's NOT a literal) or from lit (if */
3948 /* aop is a literal) */
3949 /*-----------------------------------------------------------------*/
3950 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3951 if (aop->type == AOP_LIT) {
3952 emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3954 emitpcode (POC_MOVFW, popGet (aop, offset));
3958 /* genCmp performs a left < right comparison, stores
3959 * the outcome in result (if != NULL) and generates
3960 * control flow code for the ifx (if != NULL).
3962 * This version leaves in sequences like
3963 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3964 * which should be optmized by the peephole
3965 * optimizer - RN 2005-01-01 */
3966 static void genCmp (operand *left,operand *right,
3967 operand *result, iCode *ifx, int sign)
3977 int invert_result = 0;
3981 assert (AOP_SIZE(left) == AOP_SIZE(right));
3982 assert (left && right);
3984 size = AOP_SIZE(right) - 1;
3985 mask = (0x100UL << (size*8)) - 1;
3986 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3991 resolveIfx (&rIfx, ifx);
3993 /**********************************************************************
3994 * handle bits - bit compares are promoted to int compares seemingly! *
3995 **********************************************************************/
3997 // THIS IS COMPLETELY UNTESTED!
3998 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3999 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4000 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4001 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4004 // 1 < {0,1} is false --> clear C by skipping the next instruction
4005 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4006 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4007 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4008 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4009 emitCLRC; // only skipped for left=0 && right=1
4011 goto correct_result_in_carry;
4015 /*************************************************
4016 * make sure that left is register (or the like) *
4017 *************************************************/
4018 if (!isAOP_REGlike(left)) {
4019 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4020 assert (isAOP_LIT(left));
4021 assert (isAOP_REGlike(right));
4022 // swap left and right
4023 // left < right <==> right > left <==> (right >= left + 1)
4024 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4026 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4027 // MAXVALUE < right? always false
4028 if (performedLt) emitCLRC; else emitSETC;
4029 goto correct_result_in_carry;
4032 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4033 // that's why we handled it above.
4040 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4041 } else if (isAOP_LIT(right)) {
4042 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4045 assert (isAOP_REGlike(left)); // left must be register or the like
4046 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4048 /*************************************************
4049 * special cases go here *
4050 *************************************************/
4052 if (isAOP_LIT(right)) {
4054 // unsigned comparison to a literal
4055 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4057 // unsigned left < 0? always false
4058 if (performedLt) emitCLRC; else emitSETC;
4059 goto correct_result_in_carry;
4062 // signed comparison to a literal
4063 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4064 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4065 // signed left < 0x80000000? always false
4066 if (performedLt) emitCLRC; else emitSETC;
4067 goto correct_result_in_carry;
4068 } else if (lit == 0) {
4069 // compare left < 0; set CARRY if SIGNBIT(left) is set
4070 if (performedLt) emitSETC; else emitCLRC;
4071 emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
4072 if (performedLt) emitCLRC; else emitSETC;
4073 goto correct_result_in_carry;
4076 } // right is literal
4078 /*************************************************
4079 * perform a general case comparison *
4080 * make sure we get CARRY==1 <==> left >= right *
4081 *************************************************/
4082 // compare most significant bytes
4083 //DEBUGpc ("comparing bytes at offset %d", size);
4085 // unsigned comparison
4086 pic14_mov2w_regOrLit (AOP(right), lit, size);
4087 emitpcode (POC_SUBFW, popGet (AOP(left), size));
4089 // signed comparison
4090 // (add 2^n to both operands then perform an unsigned comparison)
4091 if (isAOP_LIT(right)) {
4092 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4093 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4095 if (litbyte == 0x80) {
4096 // left >= 0x80 -- always true, but more bytes to come
4097 mov2w (AOP(left), size);
4098 emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
4101 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4102 mov2w (AOP(left), size);
4103 emitpcode (POC_ADDLW, popGetLit (0x80));
4104 emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4107 pCodeOp *pctemp = popGetTempReg();
4108 mov2w (AOP(left), size);
4109 emitpcode (POC_ADDLW, popGetLit (0x80));
4110 emitpcode (POC_MOVWF, pctemp);
4111 mov2w (AOP(right), size);
4112 emitpcode (POC_ADDLW, popGetLit (0x80));
4113 emitpcode (POC_SUBFW, pctemp);
4114 popReleaseTempReg(pctemp);
4118 // compare remaining bytes (treat as unsigned case from above)
4119 templbl = newiTempLabel ( NULL );
4122 //DEBUGpc ("comparing bytes at offset %d", offs);
4124 emitpcode (POC_GOTO, popGetLabel (templbl->key));
4125 pic14_mov2w_regOrLit (AOP(right), lit, offs);
4126 emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4128 emitpLabel (templbl->key);
4129 goto result_in_carry;
4133 /****************************************************
4134 * now CARRY contains the result of the comparison: *
4135 * SUBWF sets CARRY iff *
4136 * F-W >= 0 <==> F >= W <==> !(F < W) *
4137 * (F=left, W=right) *
4138 ****************************************************/
4142 // value will be used in the following genSkipc()
4143 rIfx.condition ^= 1;
4146 correct_result_in_carry:
4148 // assign result to variable (if neccessary)
4149 if (result && AOP_TYPE(result) != AOP_CRY) {
4150 //DEBUGpc ("assign result");
4151 size = AOP_SIZE(result);
4153 emitpcode (POC_CLRF, popGet (AOP(result), size));
4155 if (invert_result) {
4157 emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4159 emitpcode (POC_RLF, popGet (AOP(result), 0));
4163 // perform conditional jump
4165 //DEBUGpc ("generate control flow");
4173 /* OLD VERSION -- BUGGY, DO NOT USE */
4175 /*-----------------------------------------------------------------*/
4176 /* genCmp :- greater or less than comparison */
4177 /*-----------------------------------------------------------------*/
4178 static void genCmp (operand *left,operand *right,
4179 operand *result, iCode *ifx, int sign)
4181 int size; //, offset = 0 ;
4182 unsigned long lit = 0L,i = 0;
4183 resolvedIfx rFalseIfx;
4184 // resolvedIfx rTrueIfx;
4188 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4191 DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4192 DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4196 resolveIfx(&rFalseIfx,ifx);
4197 truelbl = newiTempLabel(NULL);
4198 size = max(AOP_SIZE(left),AOP_SIZE(right));
4200 DEBUGpic14_AopType(__LINE__,left,right,result);
4204 /* if literal is on the right then swap with left */
4205 if ((AOP_TYPE(right) == AOP_LIT)) {
4206 operand *tmp = right ;
4207 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4208 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4211 lit = (lit - 1) & mask;
4214 rFalseIfx.condition ^= 1;
4217 } else if ((AOP_TYPE(left) == AOP_LIT)) {
4218 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4222 //if(IC_TRUE(ifx) == NULL)
4223 /* if left & right are bit variables */
4224 if (AOP_TYPE(left) == AOP_CRY &&
4225 AOP_TYPE(right) == AOP_CRY ) {
4226 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4227 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4229 /* subtract right from left if at the
4230 end the carry flag is set then we know that
4231 left is greater than right */
4233 symbol *lbl = newiTempLabel(NULL);
4236 if(AOP_TYPE(right) == AOP_LIT) {
4238 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4240 DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4247 genSkipCond(&rFalseIfx,left,size-1,7);
4249 /* no need to compare to 0...*/
4250 /* NOTE: this is a de-generate compare that most certainly
4251 * creates some dead code. */
4252 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4254 if(ifx) ifx->generated = 1;
4261 //i = (lit >> (size*8)) & 0xff;
4262 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4264 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4266 i = ((0-lit) & 0xff);
4269 /* lit is 0x7f, all signed chars are less than
4270 * this except for 0x7f itself */
4271 emitpcode(POC_XORLW, popGetLit(0x7f));
4272 genSkipz2(&rFalseIfx,0);
4274 emitpcode(POC_ADDLW, popGetLit(0x80));
4275 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4276 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4281 genSkipz2(&rFalseIfx,1);
4283 emitpcode(POC_ADDLW, popGetLit(i));
4284 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4288 if(ifx) ifx->generated = 1;
4292 /* chars are out of the way. now do ints and longs */
4295 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4302 genSkipCond(&rFalseIfx,left,size,7);
4303 if(ifx) ifx->generated = 1;
4308 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4310 //rFalseIfx.condition ^= 1;
4311 //genSkipCond(&rFalseIfx,left,size,7);
4312 //rFalseIfx.condition ^= 1;
4314 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4315 if(rFalseIfx.condition)
4316 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4318 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4320 emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4321 emitpcode(POC_ADDFW, popGet(AOP(left),0));
4322 emitpcode(POC_MOVFW, popGet(AOP(left),1));
4325 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4327 if(rFalseIfx.condition) {
4329 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4335 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4336 emitpLabel(truelbl->key);
4337 if(ifx) ifx->generated = 1;
4344 if( (lit & 0xff) == 0) {
4345 /* lower byte is zero */
4346 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4347 i = ((lit >> 8) & 0xff) ^0x80;
4348 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4349 emitpcode(POC_ADDLW, popGetLit( 0x80));
4350 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4351 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4354 if(ifx) ifx->generated = 1;
4359 /* Special cases for signed longs */
4360 if( (lit & 0xffffff) == 0) {
4361 /* lower byte is zero */
4362 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4363 i = ((lit >> 8*3) & 0xff) ^0x80;
4364 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4365 emitpcode(POC_ADDLW, popGetLit( 0x80));
4366 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4367 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4370 if(ifx) ifx->generated = 1;
4378 if(lit & (0x80 << (size*8))) {
4379 /* lit is negative */
4380 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4382 //genSkipCond(&rFalseIfx,left,size,7);
4384 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4386 if(rFalseIfx.condition)
4387 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4389 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4393 /* lit is positive */
4394 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4395 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4396 if(rFalseIfx.condition)
4397 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4399 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4403 /* There are no more special cases, so perform a general compare */
4405 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4406 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4410 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4412 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4414 //rFalseIfx.condition ^= 1;
4415 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4417 emitpLabel(truelbl->key);
4419 if(ifx) ifx->generated = 1;
4426 /* sign is out of the way. So now do an unsigned compare */
4427 DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4430 /* General case - compare to an unsigned literal on the right.*/
4432 i = (lit >> (size*8)) & 0xff;
4433 emitpcode(POC_MOVLW, popGetLit(i));
4434 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4436 i = (lit >> (size*8)) & 0xff;
4439 emitpcode(POC_MOVLW, popGetLit(i));
4441 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4443 /* this byte of the lit is zero,
4444 *if it's not the last then OR in the variable */
4446 emitpcode(POC_IORFW, popGet(AOP(left),size));
4451 emitpLabel(lbl->key);
4452 //if(emitFinalCheck)
4453 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4455 emitpLabel(truelbl->key);
4457 if(ifx) ifx->generated = 1;
4464 if(AOP_TYPE(left) == AOP_LIT) {
4465 //symbol *lbl = newiTempLabel(NULL);
4467 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4470 DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4473 if((lit == 0) && (sign == 0)){
4476 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4478 emitpcode(POC_IORFW, popGet(AOP(right),--size));
4480 genSkipz2(&rFalseIfx,0);
4481 if(ifx) ifx->generated = 1;
4488 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4489 /* degenerate compare can never be true */
4490 if(rFalseIfx.condition == 0)
4491 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4493 if(ifx) ifx->generated = 1;
4498 /* signed comparisons to a literal byte */
4500 int lp1 = (lit+1) & 0xff;
4502 DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4505 rFalseIfx.condition ^= 1;
4506 genSkipCond(&rFalseIfx,right,0,7);
4509 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4510 emitpcode(POC_XORLW, popGetLit(0x7f));
4511 genSkipz2(&rFalseIfx,1);
4514 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4515 emitpcode(POC_ADDLW, popGetLit(0x80));
4516 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4517 rFalseIfx.condition ^= 1;
4518 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4521 if(ifx) ifx->generated = 1;
4523 /* unsigned comparisons to a literal byte */
4525 switch(lit & 0xff ) {
4527 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4528 genSkipz2(&rFalseIfx,0);
4529 if(ifx) ifx->generated = 1;
4532 genSkipCond(&rFalseIfx,right,0,7);
4533 if(ifx) ifx->generated = 1;
4537 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4538 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4539 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4540 rFalseIfx.condition ^= 1;
4541 if (AOP_TYPE(result) == AOP_CRY) {
4542 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4543 if(ifx) ifx->generated = 1;
4545 DEBUGpic14_emitcode ("; ***","%s %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4546 emitpcode(POC_CLRF, popGet(AOP(result),0));
4547 emitpcode(POC_RLF, popGet(AOP(result),0));
4548 emitpcode(POC_MOVLW, popGetLit(0x01));
4549 emitpcode(POC_XORWF, popGet(AOP(result),0));
4560 /* Size is greater than 1 */
4568 /* this means lit = 0xffffffff, or -1 */
4571 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4572 rFalseIfx.condition ^= 1;
4573 genSkipCond(&rFalseIfx,right,size,7);
4574 if(ifx) ifx->generated = 1;
4581 if(rFalseIfx.condition) {
4582 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4583 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4586 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4588 emitpcode(POC_IORFW, popGet(AOP(right),size));
4592 if(rFalseIfx.condition) {
4593 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4594 emitpLabel(truelbl->key);
4596 rFalseIfx.condition ^= 1;
4597 genSkipCond(&rFalseIfx,right,s,7);
4600 if(ifx) ifx->generated = 1;
4604 if((size == 1) && (0 == (lp1&0xff))) {
4605 /* lower byte of signed word is zero */
4606 DEBUGpic14_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
4607 i = ((lp1 >> 8) & 0xff) ^0x80;
4608 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4609 emitpcode(POC_ADDLW, popGetLit( 0x80));
4610 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4611 rFalseIfx.condition ^= 1;
4612 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4615 if(ifx) ifx->generated = 1;
4619 if(lit & (0x80 << (size*8))) {
4620 /* Lit is less than zero */
4621 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
4622 //rFalseIfx.condition ^= 1;
4623 //genSkipCond(&rFalseIfx,left,size,7);
4624 //rFalseIfx.condition ^= 1;
4625 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4626 //emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4628 if(rFalseIfx.condition)
4629 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4631 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4635 /* Lit is greater than or equal to zero */
4636 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
4637 //rFalseIfx.condition ^= 1;
4638 //genSkipCond(&rFalseIfx,right,size,7);
4639 //rFalseIfx.condition ^= 1;
4641 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4642 //emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4644 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4645 if(rFalseIfx.condition)
4646 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4648 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4653 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4654 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4658 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4660 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4662 rFalseIfx.condition ^= 1;
4663 //rFalseIfx.condition = 1;
4664 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4666 emitpLabel(truelbl->key);
4668 if(ifx) ifx->generated = 1;
4673 /* compare word or long to an unsigned literal on the right.*/
4678 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4681 break; /* handled above */
4684 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4686 emitpcode(POC_IORFW, popGet(AOP(right),size));
4687 genSkipz2(&rFalseIfx,0);
4691 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4693 emitpcode(POC_IORFW, popGet(AOP(right),size));
4696 if(rFalseIfx.condition)
4697 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4699 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4702 emitpcode(POC_MOVLW, popGetLit(lit+1));
4703 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4705 rFalseIfx.condition ^= 1;
4706 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4709 emitpLabel(truelbl->key);
4711 if(ifx) ifx->generated = 1;
4717 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4718 i = (lit >> (size*8)) & 0xff;
4720 emitpcode(POC_MOVLW, popGetLit(i));
4721 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4724 i = (lit >> (size*8)) & 0xff;
4727 emitpcode(POC_MOVLW, popGetLit(i));
4729 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4731 /* this byte of the lit is zero,
4732 *if it's not the last then OR in the variable */
4734 emitpcode(POC_IORFW, popGet(AOP(right),size));
4739 emitpLabel(lbl->key);
4741 rFalseIfx.condition ^= 1;
4742 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4746 emitpLabel(truelbl->key);
4747 if(ifx) ifx->generated = 1;
4751 /* Compare two variables */
4753 DEBUGpic14_emitcode(";sign","%d",sign);
4757 /* Sigh. thus sucks... */
4759 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4760 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4761 emitpcode(POC_MOVLW, popGetLit(0x80));
4762 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4763 emitpcode(POC_XORFW, popGet(AOP(right),size));
4764 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4766 /* Signed char comparison */
4767 /* Special thanks to Nikolai Golovchenko for this snippet */
4768 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4769 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4770 emitpcode(POC_RRFW, popGet(AOP(left),0)); /* could be any register */
4771 emitpcode(POC_XORFW, popGet(AOP(left),0));
4772 emitpcode(POC_XORFW, popGet(AOP(right),0));
4773 emitpcode(POC_ADDLW, popGetLit(0x80));
4775 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4776 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4778 if(ifx) ifx->generated = 1;
4784 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4785 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4789 /* The rest of the bytes of a multi-byte compare */
4793 emitpcode(POC_GOTO, popGetLabel(lbl->key));
4796 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4797 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4802 emitpLabel(lbl->key);
4804 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4805 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
4806 (AOP_TYPE(result) == AOP_REG)) {
4807 emitpcode(POC_CLRF, popGet(AOP(result),0));
4808 emitpcode(POC_RLF, popGet(AOP(result),0));
4810 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4812 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4813 if(ifx) ifx->generated = 1;
4820 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4821 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4822 pic14_outBitC(result);
4824 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4825 /* if the result is used in the next
4826 ifx conditional branch then generate
4827 code a little differently */
4829 genIfxJump (ifx,"c");
4831 pic14_outBitC(result);
4832 /* leave the result in acc */
4838 /*-----------------------------------------------------------------*/
4839 /* genCmpGt :- greater than comparison */
4840 /*-----------------------------------------------------------------*/
4841 static void genCmpGt (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));
4856 /* assign the amsops */
4857 aopOp (left,ic,FALSE);
4858 aopOp (right,ic,FALSE);
4859 aopOp (result,ic,TRUE);
4861 genCmp(right, left, result, ifx, sign);
4863 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4864 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4865 freeAsmop(result,NULL,ic,TRUE);
4868 /*-----------------------------------------------------------------*/
4869 /* genCmpLt - less than comparisons */
4870 /*-----------------------------------------------------------------*/
4871 static void genCmpLt (iCode *ic, iCode *ifx)
4873 operand *left, *right, *result;
4874 sym_link *letype , *retype;
4878 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4880 right= IC_RIGHT(ic);
4881 result = IC_RESULT(ic);
4883 letype = getSpec(operandType(left));
4884 retype =getSpec(operandType(right));
4885 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4887 /* assign the amsops */
4888 aopOp (left,ic,FALSE);
4889 aopOp (right,ic,FALSE);
4890 aopOp (result,ic,TRUE);
4892 genCmp(left, right, result, ifx, sign);
4894 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4895 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4896 freeAsmop(result,NULL,ic,TRUE);
4900 /*-----------------------------------------------------------------*/
4901 /* genc16bit2lit - compare a 16 bit value to a literal */
4902 /*-----------------------------------------------------------------*/
4903 static void genc16bit2lit(operand *op, int lit, int offset)
4908 DEBUGpic14_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
4909 if( (lit&0xff) == 0)
4914 switch( BYTEofLONG(lit,i)) {
4916 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4919 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4922 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4925 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4926 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4931 switch( BYTEofLONG(lit,i)) {
4933 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4937 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4941 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4944 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4946 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4954 /*-----------------------------------------------------------------*/
4955 /* gencjneshort - compare and jump if not equal */
4956 /*-----------------------------------------------------------------*/
4957 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4959 int size = min(AOP_SIZE(left),AOP_SIZE(right));
4964 //unsigned long lit = 0L;
4966 if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4967 emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4970 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4971 DEBUGpic14_AopType(__LINE__,left,right,result);
4973 assert (!pic14_sameRegs (AOP(left), AOP(result)));
4974 assert (!pic14_sameRegs (AOP(right), AOP(result)));
4975 if (AOP_SIZE(result)) {
4976 for (offset = 0; offset < AOP_SIZE(result); offset++)
4977 emitpcode (POC_CLRF, popGet (AOP(result), offset));
4980 assert (AOP_SIZE(left) == AOP_SIZE(right));
4981 //resolveIfx(&rIfx,ifx);
4982 lbl = newiTempLabel (NULL);
4985 mov2w (AOP(right),size);
4986 emitpcode (POC_XORFW, popGet (AOP(left), size));
4990 emitpcode (POC_GOTO, popGetLabel (lbl->key));
4993 emitpLabel (lbl->key);
4994 if (AOP_SIZE(result)) {
4996 emitpcode (POC_INCF, popGet (AOP(result), 0));
4999 genSkipz (ifx, NULL != IC_TRUE(ifx));
5006 DEBUGpic14_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
5007 assert (!pic14_sameRegs (AOP(result), AOP(left)));
5008 assert (!pic14_sameRegs (AOP(result), AOP(right)));
5009 for (offset=0; offset < AOP_SIZE(result); offset++)
5011 emitpcode (POC_CLRF, popGet (AOP(result), offset));
5016 /* if the left side is a literal or
5017 if the right is in a pointer register and left
5019 if ((AOP_TYPE(left) == AOP_LIT) ||
5020 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5025 if(AOP_TYPE(right) == AOP_LIT)
5026 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5028 /* if the right side is a literal then anything goes */
5029 if (AOP_TYPE(right) == AOP_LIT &&
5030 AOP_TYPE(left) != AOP_DIR ) {
5033 genc16bit2lit(left, lit, 0);
5035 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5041 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5042 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5044 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5048 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5056 /* if the right side is in a register or in direct space or
5057 if the left is a pointer register & right is not */
5058 else if (AOP_TYPE(right) == AOP_REG ||
5059 AOP_TYPE(right) == AOP_DIR ||
5060 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5061 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5062 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5063 int lbl_key = lbl->key;
5066 DEBUGpic14_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
5067 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
5068 __FUNCTION__,__LINE__);
5072 /* switch(size) { */
5074 /* genc16bit2lit(left, lit, 0); */
5076 /* emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
5082 if((AOP_TYPE(left) == AOP_DIR) &&
5083 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5085 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5086 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5088 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5090 switch (lit & 0xff) {
5092 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5095 emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
5096 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5097 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5101 emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5102 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5103 //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5104 emitpcode(POC_GOTO,popGetLabel(lbl_key));
5108 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5109 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5114 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5117 if(AOP_TYPE(result) == AOP_CRY) {
5118 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5123 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5125 /* fix me. probably need to check result size too */
5126 //emitpcode(POC_CLRF,popGet(AOP(result),0));
5131 emitpcode(POC_GOTO,popGetLabel(lbl_key));
5141 } else if(AOP_TYPE(right) == AOP_REG &&
5142 AOP_TYPE(left) != AOP_DIR){
5146 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5147 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5148 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5153 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5158 /* right is a pointer reg need both a & b */
5161 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5163 pic14_emitcode("mov","b,%s",l);
5164 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5165 pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
5170 emitpcode(POC_INCF,popGet(AOP(result),0));
5172 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5174 emitpLabel(lbl->key);
5176 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5185 /*-----------------------------------------------------------------*/
5186 /* gencjne - compare and jump if not equal */
5187 /*-----------------------------------------------------------------*/
5188 static void gencjne(operand *left, operand *right, iCode *ifx)
5190 symbol *tlbl = newiTempLabel(NULL);
5192 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5193 gencjneshort(left, right, lbl);
5195 pic14_emitcode("mov","a,%s",one);
5196 pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5197 pic14_emitcode("","%05d_DS_:",lbl->key+100);
5198 pic14_emitcode("clr","a");
5199 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5201 emitpLabel(lbl->key);
5202 emitpLabel(tlbl->key);
5207 /*-----------------------------------------------------------------*/
5208 /* genCmpEq - generates code for equal to */
5209 /*-----------------------------------------------------------------*/
5210 static void genCmpEq (iCode *ic, iCode *ifx)
5212 operand *left, *right, *result;
5214 symbol *false_label;
5217 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5220 DEBUGpic14_emitcode ("; ifx is non-null","");
5222 DEBUGpic14_emitcode ("; ifx is null","");
5224 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5225 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5226 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5228 DEBUGpic14_AopType(__LINE__,left,right,result);
5230 /* if literal, move literal to right */
5231 if (op_isLitLike (IC_LEFT(ic))) {
5232 operand *tmp = right ;
5238 if (ifx && !IC_TRUE(ifx))
5240 assert (IC_FALSE(ifx));
5241 false_label = IC_FALSE(ifx);
5244 size = min(AOP_SIZE(left),AOP_SIZE(right));
5245 assert(!pic14_sameRegs(AOP(result),AOP(left)));
5246 assert(!pic14_sameRegs(AOP(result),AOP(right)));
5248 /* assume left != right */
5251 for (i=0; i < AOP_SIZE(result); i++)
5253 emitpcode(POC_CLRF, popGet(AOP(result),i));
5257 if (AOP_TYPE(right) == AOP_LIT)
5259 unsigned long lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
5261 size = AOP_SIZE(left);
5262 assert(!op_isLitLike(left));
5267 mov2w(AOP(left), 0);
5268 for (i=1; i < size; i++)
5269 emitpcode(POC_IORFW,popGet(AOP(left),i));
5270 /* now Z is set iff `left == right' */
5272 if (!false_label) false_label = newiTempLabel(NULL);
5273 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5277 for (i=0; i < size; i++)
5280 emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
5281 /* now Z is cleared if `left != right' */
5283 if (!false_label) false_label = newiTempLabel(NULL);
5284 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5291 /* right is no literal */
5294 for (i=0; i < size; i++)
5296 mov2w(AOP(right),i);
5297 emitpcode(POC_XORFW,popGet(AOP(left),i));
5298 /* now Z is cleared if `left != right' */
5300 if (!false_label) false_label = newiTempLabel(NULL);
5301 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5305 /* if we reach here, left == right */
5307 if (AOP_SIZE(result) > 0)
5309 emitpcode(POC_INCF, popGet(AOP(result),0));
5312 if (ifx && IC_TRUE(ifx))
5314 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5317 if (false_label && (!ifx || IC_TRUE(ifx)))
5318 emitpLabel(false_label->key);
5320 if (ifx) ifx->generated = 1;
5322 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5323 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5324 freeAsmop(result,NULL,ic,TRUE);
5327 /*-----------------------------------------------------------------*/
5328 /* ifxForOp - returns the icode containing the ifx for operand */
5329 /*-----------------------------------------------------------------*/
5330 static iCode *ifxForOp ( operand *op, iCode *ic )
5333 /* if true symbol then needs to be assigned */
5334 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5335 if (IS_TRUE_SYMOP(op))
5338 /* if this has register type condition and
5339 the next instruction is ifx with the same operand
5340 and live to of the operand is upto the ifx only then */
5342 ic->next->op == IFX &&
5343 IC_COND(ic->next)->key == op->key &&
5344 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5348 ic->next->op == IFX &&
5349 IC_COND(ic->next)->key == op->key) {
5350 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5354 DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5356 ic->next->op == IFX)
5357 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5360 ic->next->op == IFX &&
5361 IC_COND(ic->next)->key == op->key) {
5362 DEBUGpic14_emitcode ("; "," key is okay");
5363 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5364 OP_SYMBOL(op)->liveTo,
5371 /*-----------------------------------------------------------------*/
5372 /* genAndOp - for && operation */
5373 /*-----------------------------------------------------------------*/
5374 static void genAndOp (iCode *ic)
5376 operand *left,*right, *result;
5380 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5381 /* note here that && operations that are in an
5382 if statement are taken away by backPatchLabels
5383 only those used in arthmetic operations remain */
5384 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5385 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5386 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5388 DEBUGpic14_AopType(__LINE__,left,right,result);
5390 emitpcode(POC_MOVFW,popGet(AOP(left),0));
5391 emitpcode(POC_ANDFW,popGet(AOP(right),0));
5392 emitpcode(POC_MOVWF,popGet(AOP(result),0));
5394 /* if both are bit variables */
5395 /* if (AOP_TYPE(left) == AOP_CRY && */
5396 /* AOP_TYPE(right) == AOP_CRY ) { */
5397 /* pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5398 /* pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5399 /* pic14_outBitC(result); */
5401 /* tlbl = newiTempLabel(NULL); */
5402 /* pic14_toBoolean(left); */
5403 /* pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5404 /* pic14_toBoolean(right); */
5405 /* pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5406 /* pic14_outBitAcc(result); */
5409 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5410 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5411 freeAsmop(result,NULL,ic,TRUE);
5415 /*-----------------------------------------------------------------*/
5416 /* genOrOp - for || operation */
5417 /*-----------------------------------------------------------------*/
5420 modified this code, but it doesn't appear to ever get called
5423 static void genOrOp (iCode *ic)
5425 operand *left,*right, *result;
5429 /* note here that || operations that are in an
5430 if statement are taken away by backPatchLabels
5431 only those used in arthmetic operations remain */
5433 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5434 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5435 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5436 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5438 DEBUGpic14_AopType(__LINE__,left,right,result);
5440 for (i=0; i < AOP_SIZE(result); i++)
5442 emitpcode(POC_CLRF, popGet(AOP(result), i));
5445 tlbl = newiTempLabel(NULL);
5446 pic14_toBoolean(left);
5448 emitpcode(POC_GOTO, popGetLabel(tlbl->key));
5449 pic14_toBoolean(right);
5450 emitpLabel(tlbl->key);
5451 /* here Z is clear IFF `left || right' */
5453 emitpcode(POC_INCF, popGet(AOP(result), 0));
5455 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5456 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5457 freeAsmop(result,NULL,ic,TRUE);
5460 /*-----------------------------------------------------------------*/
5461 /* isLiteralBit - test if lit == 2^n */
5462 /*-----------------------------------------------------------------*/
5463 static int isLiteralBit(unsigned long lit)
5465 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5466 0x100L,0x200L,0x400L,0x800L,
5467 0x1000L,0x2000L,0x4000L,0x8000L,
5468 0x10000L,0x20000L,0x40000L,0x80000L,
5469 0x100000L,0x200000L,0x400000L,0x800000L,
5470 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5471 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5475 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5476 for(idx = 0; idx < 32; idx++)
5482 /*-----------------------------------------------------------------*/
5483 /* continueIfTrue - */
5484 /*-----------------------------------------------------------------*/
5485 static void continueIfTrue (iCode *ic)
5488 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5490 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5494 /*-----------------------------------------------------------------*/
5496 /*-----------------------------------------------------------------*/
5497 static void jumpIfTrue (iCode *ic)
5500 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5502 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5506 /*-----------------------------------------------------------------*/
5507 /* jmpTrueOrFalse - */
5508 /*-----------------------------------------------------------------*/
5509 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5512 // ugly but optimized by peephole
5513 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5515 symbol *nlbl = newiTempLabel(NULL);
5516 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5517 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5518 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5519 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5522 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5523 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5528 /*-----------------------------------------------------------------*/
5529 /* genAnd - code for and */
5530 /*-----------------------------------------------------------------*/
5531 static void genAnd (iCode *ic, iCode *ifx)
5533 operand *left, *right, *result;
5535 unsigned long lit = 0L;
5540 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5541 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5542 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5543 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5545 resolveIfx(&rIfx,ifx);
5547 /* if left is a literal & right is not then exchange them */
5548 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5549 AOP_NEEDSACC(left)) {
5550 operand *tmp = right ;
5555 /* if result = right then exchange them */
5556 if(pic14_sameRegs(AOP(result),AOP(right))){
5557 operand *tmp = right ;
5562 /* if right is bit then exchange them */
5563 if (AOP_TYPE(right) == AOP_CRY &&
5564 AOP_TYPE(left) != AOP_CRY){
5565 operand *tmp = right ;
5569 if(AOP_TYPE(right) == AOP_LIT)
5570 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5572 size = AOP_SIZE(result);
5574 DEBUGpic14_AopType(__LINE__,left,right,result);
5577 // result = bit & yy;
5578 if (AOP_TYPE(left) == AOP_CRY){
5579 // c = bit & literal;
5580 if(AOP_TYPE(right) == AOP_LIT){
5582 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5585 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5588 if(size && (AOP_TYPE(result) == AOP_CRY)){
5589 pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5592 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5596 pic14_emitcode("clr","c");
5599 if (AOP_TYPE(right) == AOP_CRY){
5601 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5602 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5605 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5607 pic14_emitcode("rrc","a");
5608 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5614 pic14_outBitC(result);
5616 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5617 genIfxJump(ifx, "c");
5621 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5622 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5623 if((AOP_TYPE(right) == AOP_LIT) &&
5624 (AOP_TYPE(result) == AOP_CRY) &&
5625 (AOP_TYPE(left) != AOP_CRY)){
5626 int posbit = isLiteralBit(lit);
5630 //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5633 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5638 while (posbit > 7) {
5642 emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5643 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5644 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5651 symbol *tlbl = newiTempLabel(NULL);
5652 int sizel = AOP_SIZE(left);
5654 pic14_emitcode("setb","c");
5656 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5657 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5659 if((posbit = isLiteralBit(bytelit)) != 0)
5660 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5662 if(bytelit != 0x0FFL)
5663 pic14_emitcode("anl","a,%s",
5664 aopGet(AOP(right),offset,FALSE,TRUE));
5665 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5670 // bit = left & literal
5672 pic14_emitcode("clr","c");
5673 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5675 // if(left & literal)
5678 jmpTrueOrFalse(ifx, tlbl);
5682 pic14_outBitC(result);
5686 /* if left is same as result */
5687 if(pic14_sameRegs(AOP(result),AOP(left))){
5689 for(;size--; offset++,lit>>=8) {
5690 if(AOP_TYPE(right) == AOP_LIT){
5691 switch(lit & 0xff) {
5693 /* and'ing with 0 has clears the result */
5694 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5697 /* and'ing with 0xff is a nop when the result and left are the same */
5702 int p = my_powof2( (~lit) & 0xff );
5704 /* only one bit is set in the literal, so use a bcf instruction */
5705 emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5708 if(know_W != (int)(lit&0xff))
5709 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5711 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5716 if (AOP_TYPE(left) == AOP_ACC) {
5717 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5719 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5720 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5727 // left & result in different registers
5728 if(AOP_TYPE(result) == AOP_CRY){
5730 // if(size), result in bit
5731 // if(!size && ifx), conditional oper: if(left & right)
5732 symbol *tlbl = newiTempLabel(NULL);
5733 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5735 pic14_emitcode("setb","c");
5737 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5738 pic14_emitcode("anl","a,%s",
5739 aopGet(AOP(left),offset,FALSE,FALSE));
5740 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5745 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5746 pic14_outBitC(result);
5748 jmpTrueOrFalse(ifx, tlbl);
5750 for(;(size--);offset++) {
5752 // result = left & right
5753 if(AOP_TYPE(right) == AOP_LIT){
5754 int t = (lit >> (offset*8)) & 0x0FFL;
5757 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5760 if(AOP_TYPE(left) != AOP_ACC) {
5761 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5763 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5766 if(AOP_TYPE(left) == AOP_ACC) {
5767 emitpcode(POC_ANDLW, popGetLit(t));
5769 emitpcode(POC_MOVLW, popGetLit(t));
5770 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5772 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5777 if (AOP_TYPE(left) == AOP_ACC) {
5778 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5780 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5781 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5783 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5789 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5790 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5791 freeAsmop(result,NULL,ic,TRUE);
5794 /*-----------------------------------------------------------------*/
5795 /* genOr - code for or */
5796 /*-----------------------------------------------------------------*/
5797 static void genOr (iCode *ic, iCode *ifx)
5799 operand *left, *right, *result;
5801 unsigned long lit = 0L;
5804 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5806 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5807 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5808 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5810 DEBUGpic14_AopType(__LINE__,left,right,result);
5812 /* if left is a literal & right is not then exchange them */
5813 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5814 AOP_NEEDSACC(left)) {
5815 operand *tmp = right ;
5820 /* if result = right then exchange them */
5821 if(pic14_sameRegs(AOP(result),AOP(right))){
5822 operand *tmp = right ;
5827 /* if right is bit then exchange them */
5828 if (AOP_TYPE(right) == AOP_CRY &&
5829 AOP_TYPE(left) != AOP_CRY){
5830 operand *tmp = right ;
5835 DEBUGpic14_AopType(__LINE__,left,right,result);
5837 if(AOP_TYPE(right) == AOP_LIT)
5838 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5840 size = AOP_SIZE(result);
5844 if (AOP_TYPE(left) == AOP_CRY){
5845 if(AOP_TYPE(right) == AOP_LIT){
5846 // c = bit & literal;
5848 // lit != 0 => result = 1
5849 if(AOP_TYPE(result) == AOP_CRY){
5851 emitpcode(POC_BSF, popGet(AOP(result),0));
5852 //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5853 // AOP(result)->aopu.aop_dir,
5854 // AOP(result)->aopu.aop_dir);
5856 continueIfTrue(ifx);
5860 // lit == 0 => result = left
5861 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5863 pic14_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5866 if (AOP_TYPE(right) == AOP_CRY){
5867 if(pic14_sameRegs(AOP(result),AOP(left))){
5869 emitpcode(POC_BCF, popGet(AOP(result),0));
5870 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5871 emitpcode(POC_BSF, popGet(AOP(result),0));
5873 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5874 AOP(result)->aopu.aop_dir,
5875 AOP(result)->aopu.aop_dir);
5876 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5877 AOP(right)->aopu.aop_dir,
5878 AOP(right)->aopu.aop_dir);
5879 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5880 AOP(result)->aopu.aop_dir,
5881 AOP(result)->aopu.aop_dir);
5883 if( AOP_TYPE(result) == AOP_ACC) {
5884 emitpcode(POC_MOVLW, popGetLit(0));
5885 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5886 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5887 emitpcode(POC_MOVLW, popGetLit(1));
5891 emitpcode(POC_BCF, popGet(AOP(result),0));
5892 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5893 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5894 emitpcode(POC_BSF, popGet(AOP(result),0));
5896 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5897 AOP(result)->aopu.aop_dir,
5898 AOP(result)->aopu.aop_dir);
5899 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5900 AOP(right)->aopu.aop_dir,
5901 AOP(right)->aopu.aop_dir);
5902 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5903 AOP(left)->aopu.aop_dir,
5904 AOP(left)->aopu.aop_dir);
5905 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5906 AOP(result)->aopu.aop_dir,
5907 AOP(result)->aopu.aop_dir);
5912 symbol *tlbl = newiTempLabel(NULL);
5913 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5916 emitpcode(POC_BCF, popGet(AOP(result),0));
5917 if( AOP_TYPE(right) == AOP_ACC) {
5918 emitpcode(POC_IORLW, popGetLit(0));
5920 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5921 emitpcode(POC_BSF, popGet(AOP(result),0));
5926 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5927 pic14_emitcode(";XXX setb","c");
5928 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5929 AOP(left)->aopu.aop_dir,tlbl->key+100);
5930 pic14_toBoolean(right);
5931 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5932 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5933 jmpTrueOrFalse(ifx, tlbl);
5937 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5944 pic14_outBitC(result);
5946 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5947 genIfxJump(ifx, "c");
5951 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5952 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5953 if((AOP_TYPE(right) == AOP_LIT) &&
5954 (AOP_TYPE(result) == AOP_CRY) &&
5955 (AOP_TYPE(left) != AOP_CRY)){
5957 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5960 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5962 continueIfTrue(ifx);
5965 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5966 // lit = 0, result = boolean(left)
5968 pic14_emitcode(";XXX setb","c");
5969 pic14_toBoolean(right);
5971 symbol *tlbl = newiTempLabel(NULL);
5972 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5974 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5976 genIfxJump (ifx,"a");
5980 pic14_outBitC(result);
5984 /* if left is same as result */
5985 if(pic14_sameRegs(AOP(result),AOP(left))){
5987 for(;size--; offset++,lit>>=8) {
5988 if(AOP_TYPE(right) == AOP_LIT){
5989 if((lit & 0xff) == 0)
5990 /* or'ing with 0 has no effect */
5993 int p = my_powof2(lit & 0xff);
5995 /* only one bit is set in the literal, so use a bsf instruction */
5997 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5999 if(know_W != (int)(lit & 0xff))
6000 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
6001 know_W = lit & 0xff;
6002 emitpcode(POC_IORWF, popGet(AOP(left),offset));
6007 if (AOP_TYPE(left) == AOP_ACC) {
6008 emitpcode(POC_IORFW, popGet(AOP(right),offset));
6009 pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6011 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
6012 emitpcode(POC_IORWF, popGet(AOP(left),offset));
6014 pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6015 pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
6021 // left & result in different registers
6022 if(AOP_TYPE(result) == AOP_CRY){
6024 // if(size), result in bit
6025 // if(!size && ifx), conditional oper: if(left | right)
6026 symbol *tlbl = newiTempLabel(NULL);
6027 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6028 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6032 pic14_emitcode(";XXX setb","c");
6034 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6035 pic14_emitcode(";XXX orl","a,%s",
6036 aopGet(AOP(left),offset,FALSE,FALSE));
6037 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6042 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6043 pic14_outBitC(result);
6045 jmpTrueOrFalse(ifx, tlbl);
6046 } else for(;(size--);offset++){
6048 // result = left | right
6049 if(AOP_TYPE(right) == AOP_LIT){
6050 int t = (lit >> (offset*8)) & 0x0FFL;
6053 if (AOP_TYPE(left) != AOP_ACC) {
6054 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
6056 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6060 if (AOP_TYPE(left) == AOP_ACC) {
6061 emitpcode(POC_IORLW, popGetLit(t));
6063 emitpcode(POC_MOVLW, popGetLit(t));
6064 emitpcode(POC_IORFW, popGet(AOP(left),offset));
6066 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6071 // faster than result <- left, anl result,right
6072 // and better if result is SFR
6073 if (AOP_TYPE(left) == AOP_ACC) {
6074 emitpcode(POC_IORFW,popGet(AOP(right),offset));
6076 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6077 emitpcode(POC_IORFW,popGet(AOP(left),offset));
6079 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6084 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6085 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6086 freeAsmop(result,NULL,ic,TRUE);
6089 /*-----------------------------------------------------------------*/
6090 /* genXor - code for xclusive or */
6091 /*-----------------------------------------------------------------*/
6092 static void genXor (iCode *ic, iCode *ifx)
6094 operand *left, *right, *result;
6096 unsigned long lit = 0L;
6099 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6101 aopOp((left = IC_LEFT(ic)),ic,FALSE);
6102 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6103 aopOp((result=IC_RESULT(ic)),ic,TRUE);
6105 /* if left is a literal & right is not ||
6106 if left needs acc & right does not */
6107 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6108 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6109 operand *tmp = right ;
6114 /* if result = right then exchange them */
6115 if(pic14_sameRegs(AOP(result),AOP(right))){
6116 operand *tmp = right ;
6121 /* if right is bit then exchange them */
6122 if (AOP_TYPE(right) == AOP_CRY &&
6123 AOP_TYPE(left) != AOP_CRY){
6124 operand *tmp = right ;
6128 if(AOP_TYPE(right) == AOP_LIT)
6129 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6131 size = AOP_SIZE(result);
6135 if (AOP_TYPE(left) == AOP_CRY){
6136 if(AOP_TYPE(right) == AOP_LIT){
6137 // c = bit & literal;
6139 // lit>>1 != 0 => result = 1
6140 if(AOP_TYPE(result) == AOP_CRY){
6142 {emitpcode(POC_BSF, popGet(AOP(result),offset));
6143 pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6145 continueIfTrue(ifx);
6148 pic14_emitcode("setb","c");
6152 // lit == 0, result = left
6153 if(size && pic14_sameRegs(AOP(result),AOP(left)))
6155 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6157 // lit == 1, result = not(left)
6158 if(size && pic14_sameRegs(AOP(result),AOP(left))){
6159 emitpcode(POC_MOVLW, popGet(AOP(result),offset));
6160 emitpcode(POC_XORWF, popGet(AOP(result),offset));
6161 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6164 assert ( !"incomplete genXor" );
6165 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6166 pic14_emitcode("cpl","c");
6173 symbol *tlbl = newiTempLabel(NULL);
6174 if (AOP_TYPE(right) == AOP_CRY){
6176 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6179 int sizer = AOP_SIZE(right);
6181 // if val>>1 != 0, result = 1
6182 pic14_emitcode("setb","c");
6184 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6186 // test the msb of the lsb
6187 pic14_emitcode("anl","a,#0xfe");
6188 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6192 pic14_emitcode("rrc","a");
6194 pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6195 pic14_emitcode("cpl","c");
6196 pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6201 pic14_outBitC(result);
6203 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6204 genIfxJump(ifx, "c");
6208 if(pic14_sameRegs(AOP(result),AOP(left))){
6209 /* if left is same as result */
6210 for(;size--; offset++) {
6211 if(AOP_TYPE(right) == AOP_LIT){
6212 int t = (lit >> (offset*8)) & 0x0FFL;
6216 if (IS_AOP_PREG(left)) {
6217 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6218 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6219 aopPut(AOP(result),"a",offset);
6221 emitpcode(POC_MOVLW, popGetLit(t));
6222 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6223 pic14_emitcode("xrl","%s,%s",
6224 aopGet(AOP(left),offset,FALSE,TRUE),
6225 aopGet(AOP(right),offset,FALSE,FALSE));
6228 if (AOP_TYPE(left) == AOP_ACC)
6229 pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6231 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6232 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6234 if (IS_AOP_PREG(left)) {
6235 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6236 aopPut(AOP(result),"a",offset);
6238 pic14_emitcode("xrl","%s,a",
6239 aopGet(AOP(left),offset,FALSE,TRUE));
6245 // left & result in different registers
6246 if(AOP_TYPE(result) == AOP_CRY){
6248 // if(size), result in bit
6249 // if(!size && ifx), conditional oper: if(left ^ right)
6250 symbol *tlbl = newiTempLabel(NULL);
6251 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6253 pic14_emitcode("setb","c");
6255 if((AOP_TYPE(right) == AOP_LIT) &&
6256 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6257 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6259 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6260 pic14_emitcode("xrl","a,%s",
6261 aopGet(AOP(left),offset,FALSE,FALSE));
6263 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6268 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6269 pic14_outBitC(result);
6271 jmpTrueOrFalse(ifx, tlbl);
6272 } else for(;(size--);offset++){
6274 // result = left & right
6275 if(AOP_TYPE(right) == AOP_LIT){
6276 int t = (lit >> (offset*8)) & 0x0FFL;
6279 if (AOP_TYPE(left) != AOP_ACC) {
6280 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6282 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6283 pic14_emitcode("movf","%s,w",
6284 aopGet(AOP(left),offset,FALSE,FALSE));
6285 pic14_emitcode("movwf","%s",
6286 aopGet(AOP(result),offset,FALSE,FALSE));
6289 if (AOP_TYPE(left) == AOP_ACC) {
6290 emitpcode(POC_XORLW, popGetLit(t));
6292 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6294 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6297 if (AOP_TYPE(left) == AOP_ACC) {
6298 emitpcode(POC_XORLW, popGetLit(t));
6300 emitpcode(POC_MOVLW, popGetLit(t));
6301 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6303 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6304 pic14_emitcode("movlw","0x%x",t);
6305 pic14_emitcode("xorwf","%s,w",
6306 aopGet(AOP(left),offset,FALSE,FALSE));
6307 pic14_emitcode("movwf","%s",
6308 aopGet(AOP(result),offset,FALSE,FALSE));
6314 // faster than result <- left, anl result,right
6315 // and better if result is SFR
6316 if (AOP_TYPE(left) == AOP_ACC) {
6317 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6319 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6320 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6322 if ( AOP_TYPE(result) != AOP_ACC){
6323 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6329 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6330 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6331 freeAsmop(result,NULL,ic,TRUE);
6334 /*-----------------------------------------------------------------*/
6335 /* genInline - write the inline code out */
6336 /*-----------------------------------------------------------------*/
6337 static void genInline (iCode *ic)
6339 char *buffer, *bp, *bp1;
6342 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6344 _G.inLine += (!options.asmpeep);
6346 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6347 strcpy(buffer,IC_INLINE(ic));
6349 /* emit each line as a code */
6355 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6363 /* print label, use this special format with NULL directive
6364 * to denote that the argument should not be indented with tab */
6365 addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6372 if ((bp1 != bp) && *bp1)
6373 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6377 _G.inLine -= (!options.asmpeep);
6380 /*-----------------------------------------------------------------*/
6381 /* genRRC - rotate right with carry */
6382 /*-----------------------------------------------------------------*/
6383 static void genRRC (iCode *ic)
6385 operand *left , *result ;
6386 int size, offset = 0, same;
6389 /* rotate right with carry */
6391 result=IC_RESULT(ic);
6392 aopOp (left,ic,FALSE);
6393 aopOp (result,ic,FALSE);
6395 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6397 same = pic14_sameRegs(AOP(result),AOP(left));
6399 size = AOP_SIZE(result);
6401 /* get the lsb and put it into the carry */
6402 emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6409 emitpcode(POC_RRF, popGet(AOP(left),offset));
6411 emitpcode(POC_RRFW, popGet(AOP(left),offset));
6412 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6418 freeAsmop(left,NULL,ic,TRUE);
6419 freeAsmop(result,NULL,ic,TRUE);
6422 /*-----------------------------------------------------------------*/
6423 /* genRLC - generate code for rotate left with carry */
6424 /*-----------------------------------------------------------------*/
6425 static void genRLC (iCode *ic)
6427 operand *left , *result ;
6428 int size, offset = 0;
6432 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6433 /* rotate right with carry */
6435 result=IC_RESULT(ic);
6436 aopOp (left,ic,FALSE);
6437 aopOp (result,ic,FALSE);
6439 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6441 same = pic14_sameRegs(AOP(result),AOP(left));
6443 /* move it to the result */
6444 size = AOP_SIZE(result);
6446 /* get the msb and put it into the carry */
6447 emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6454 emitpcode(POC_RLF, popGet(AOP(left),offset));
6456 emitpcode(POC_RLFW, popGet(AOP(left),offset));
6457 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6464 freeAsmop(left,NULL,ic,TRUE);
6465 freeAsmop(result,NULL,ic,TRUE);
6468 /*-----------------------------------------------------------------*/
6469 /* genGetHbit - generates code get highest order bit */
6470 /*-----------------------------------------------------------------*/
6471 static void genGetHbit (iCode *ic)
6473 operand *left, *result;
6475 result=IC_RESULT(ic);
6476 aopOp (left,ic,FALSE);
6477 aopOp (result,ic,FALSE);
6480 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6481 /* get the highest order byte into a */
6482 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6483 if(AOP_TYPE(result) == AOP_CRY){
6484 pic14_emitcode("rlc","a");
6485 pic14_outBitC(result);
6488 pic14_emitcode("rl","a");
6489 pic14_emitcode("anl","a,#0x01");
6490 pic14_outAcc(result);
6494 freeAsmop(left,NULL,ic,TRUE);
6495 freeAsmop(result,NULL,ic,TRUE);
6498 /*-----------------------------------------------------------------*/
6499 /* AccLsh - shift left accumulator by known count */
6500 /* MARK: pic14 always rotates through CARRY! */
6501 /*-----------------------------------------------------------------*/
6502 static void AccLsh (pCodeOp *pcop,int shCount)
6505 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6506 shCount &= 0x0007; // shCount : 0..7
6513 emitpcode(POC_RLF,pcop);
6517 emitpcode(POC_RLF,pcop);
6518 emitpcode(POC_RLF,pcop);
6521 emitpcode(POC_RLF,pcop);
6522 emitpcode(POC_RLF,pcop);
6523 emitpcode(POC_RLF,pcop);
6526 emitpcode(POC_SWAPF,pcop);
6529 emitpcode(POC_SWAPF,pcop);
6530 emitpcode(POC_RLF,pcop);
6533 emitpcode(POC_SWAPF,pcop);
6534 emitpcode(POC_RLF,pcop);
6535 emitpcode(POC_RLF,pcop);
6538 emitpcode(POC_RRFW,pcop);
6539 emitpcode(POC_RRF,pcop);
6542 /* clear invalid bits */
6543 emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6544 emitpcode(POC_ANDWF, pcop);
6547 /*-----------------------------------------------------------------*/
6548 /* AccRsh - shift right accumulator by known count */
6549 /* MARK: pic14 always rotates through CARRY! */
6550 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6551 /* 1: mask out invalid bits (zero-extend) */
6552 /* 2: sign-extend result (pretty slow) */
6553 /*-----------------------------------------------------------------*/
6554 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6557 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6558 shCount &= 0x0007; // shCount : 0..7
6564 /* load sign if needed */
6565 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6566 else if (mask_mode == 1) emitCLRC;
6567 emitpcode(POC_RRF,pcop);
6571 /* load sign if needed */
6572 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6573 emitpcode(POC_RRF,pcop);
6574 /* load sign if needed */
6575 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6576 emitpcode(POC_RRF,pcop);
6577 if (mask_mode == 2) return;
6580 /* load sign if needed */
6581 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6582 emitpcode(POC_RRF,pcop);
6583 /* load sign if needed */
6584 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6585 emitpcode(POC_RRF,pcop);
6586 /* load sign if needed */
6587 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6588 emitpcode(POC_RRF,pcop);
6589 if (mask_mode == 2) return;
6592 emitpcode(POC_SWAPF,pcop);
6595 emitpcode(POC_SWAPF,pcop);
6596 emitpcode(POC_RRF,pcop);
6599 emitpcode(POC_SWAPF,pcop);
6600 emitpcode(POC_RRF,pcop);
6601 emitpcode(POC_RRF,pcop);
6607 emitpcode(POC_RLFW,pcop);
6608 emitpcode(POC_CLRF,pcop);
6610 emitpcode(POC_COMF,pcop);
6613 emitpcode(POC_RLFW,pcop);
6614 emitpcode(POC_RLF,pcop);
6621 /* leave invalid bits undefined */
6625 /* clear invalid bits -- zero-extend */
6626 emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6627 emitpcode(POC_ANDWF, pcop);
6629 if (mask_mode == 2) {
6631 emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6632 emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6633 emitpcode(POC_IORWF, pcop);
6638 /*-----------------------------------------------------------------*/
6639 /* AccSRsh - signed right shift accumulator by known count */
6640 /*-----------------------------------------------------------------*/
6641 static void AccSRsh (int shCount)
6644 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6647 pic14_emitcode("mov","c,acc.7");
6648 pic14_emitcode("rrc","a");
6649 } else if(shCount == 2){
6650 pic14_emitcode("mov","c,acc.7");
6651 pic14_emitcode("rrc","a");
6652 pic14_emitcode("mov","c,acc.7");
6653 pic14_emitcode("rrc","a");
6655 tlbl = newiTempLabel(NULL);
6656 /* rotate right accumulator */
6657 AccRol(8 - shCount);
6658 /* and kill the higher order bits */
6659 pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6660 pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6661 pic14_emitcode("orl","a,#0x%02x",
6662 (unsigned char)~SRMask[shCount]);
6663 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6668 /*-----------------------------------------------------------------*/
6669 /* shiftR1Left2Result - shift right one byte from left to result */
6670 /*-----------------------------------------------------------------*/
6671 static void shiftR1Left2ResultSigned (operand *left, int offl,
6672 operand *result, int offr,
6678 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6680 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6684 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6686 emitpcode(POC_RRF, popGet(AOP(result),offr));
6688 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6689 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6695 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6697 emitpcode(POC_RRF, popGet(AOP(result),offr));
6699 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6700 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6702 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6703 emitpcode(POC_RRF, popGet(AOP(result),offr));
6709 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6711 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6712 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6715 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6716 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6717 emitpcode(POC_ANDLW, popGetLit(0x1f));
6719 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6720 emitpcode(POC_IORLW, popGetLit(0xe0));
6722 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6726 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6727 emitpcode(POC_ANDLW, popGetLit(0x0f));
6728 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6729 emitpcode(POC_IORLW, popGetLit(0xf0));
6730 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6734 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6736 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6737 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6739 emitpcode(POC_RRFW, popGet(AOP(result),offr));
6740 emitpcode(POC_ANDLW, popGetLit(0x07));
6741 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6742 emitpcode(POC_IORLW, popGetLit(0xf8));
6743 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6748 emitpcode(POC_MOVLW, popGetLit(0x00));
6749 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6750 emitpcode(POC_MOVLW, popGetLit(0xfe));
6751 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6752 emitpcode(POC_IORLW, popGetLit(0x01));
6753 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6755 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6756 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6757 emitpcode(POC_DECF, popGet(AOP(result),offr));
6758 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6759 emitpcode(POC_BCF, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6765 emitpcode(POC_MOVLW, popGetLit(0x00));
6766 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6767 emitpcode(POC_MOVLW, popGetLit(0xff));
6768 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6770 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6771 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6772 emitpcode(POC_DECF, popGet(AOP(result),offr));
6780 /*-----------------------------------------------------------------*/
6781 /* shiftR1Left2Result - shift right one byte from left to result */
6782 /*-----------------------------------------------------------------*/
6783 static void shiftR1Left2Result (operand *left, int offl,
6784 operand *result, int offr,
6785 int shCount, int sign)
6790 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6792 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6794 /* Copy the msb into the carry if signed. */
6796 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6806 emitpcode(POC_RRF, popGet(AOP(result),offr));
6808 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6809 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6815 emitpcode(POC_RRF, popGet(AOP(result),offr));
6817 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6818 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6821 emitpcode(POC_RRF, popGet(AOP(result),offr));
6826 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6828 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6829 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6832 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6833 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6834 emitpcode(POC_ANDLW, popGetLit(0x1f));
6835 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6839 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6840 emitpcode(POC_ANDLW, popGetLit(0x0f));
6841 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6845 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6846 emitpcode(POC_ANDLW, popGetLit(0x0f));
6847 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6849 emitpcode(POC_RRF, popGet(AOP(result),offr));
6854 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6855 emitpcode(POC_ANDLW, popGetLit(0x80));
6856 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6857 emitpcode(POC_RLF, popGet(AOP(result),offr));
6858 emitpcode(POC_RLF, popGet(AOP(result),offr));
6863 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6864 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6865 emitpcode(POC_RLF, popGet(AOP(result),offr));
6874 /*-----------------------------------------------------------------*/
6875 /* shiftL1Left2Result - shift left one byte from left to result */
6876 /*-----------------------------------------------------------------*/
6877 static void shiftL1Left2Result (operand *left, int offl,
6878 operand *result, int offr, int shCount)
6884 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6886 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6887 DEBUGpic14_emitcode ("; ***","same = %d",same);
6888 // l = aopGet(AOP(left),offl,FALSE,FALSE);
6890 /* shift left accumulator */
6891 //AccLsh(shCount); // don't comment out just yet...
6892 // aopPut(AOP(result),"a",offr);
6896 /* Shift left 1 bit position */
6897 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6899 emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6901 emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6902 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6906 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6907 emitpcode(POC_ANDLW,popGetLit(0x7e));
6908 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6909 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6912 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6913 emitpcode(POC_ANDLW,popGetLit(0x3e));
6914 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6915 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6916 emitpcode(POC_RLF, popGet(AOP(result),offr));
6919 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6920 emitpcode(POC_ANDLW, popGetLit(0xf0));
6921 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6924 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6925 emitpcode(POC_ANDLW, popGetLit(0xf0));
6926 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6927 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6930 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6931 emitpcode(POC_ANDLW, popGetLit(0x30));
6932 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6933 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6934 emitpcode(POC_RLF, popGet(AOP(result),offr));
6937 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6938 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6939 emitpcode(POC_RRF, popGet(AOP(result),offr));
6943 DEBUGpic14_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6949 /*-----------------------------------------------------------------*/
6950 /* movLeft2Result - move byte from left to result */
6951 /*-----------------------------------------------------------------*/
6952 static void movLeft2Result (operand *left, int offl,
6953 operand *result, int offr)
6957 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6958 if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6959 l = aopGet(AOP(left),offl,FALSE,FALSE);
6961 if (*l == '@' && (IS_AOP_PREG(result))) {
6962 pic14_emitcode("mov","a,%s",l);
6963 aopPut(AOP(result),"a",offr);
6965 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6966 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6971 /*-----------------------------------------------------------------*/
6972 /* shiftLeft_Left2ResultLit - shift left by known count */
6973 /*-----------------------------------------------------------------*/
6975 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6977 int size, same, offr, i;
6979 size = AOP_SIZE(left);
6980 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6982 same = pic14_sameRegs (AOP(left), AOP(result));
6985 shCount = shCount & 0x07;
6991 case 0: /* takes 0 or 2N cycles (for offr==0) */
6992 if (!same || offr) {
6993 for (i=size-1; i >= 0; i--)
6994 movLeft2Result (left, i, result, offr + i);
6998 case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
7000 shiftLeft_Left2ResultLit (left, result, 8 * offr);
7001 shiftLeft_Left2ResultLit (result, result, shCount);
7002 return; /* prevent clearing result again */
7005 for (i=0; i < size; i++) {
7006 if (same && !offr) {
7007 emitpcode (POC_RLF, popGet (AOP(left), i));
7009 emitpcode (POC_RLFW, popGet (AOP(left), i));
7010 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7016 case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
7017 /* works in-place/with offr as well */
7018 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
7019 emitpcode (POC_ANDLW, popGetLit (0xF0));
7020 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
7022 for (i = size - 2; i >= 0; i--)
7024 emitpcode (POC_SWAPFW, popGet (AOP(left), i));
7025 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7026 emitpcode (POC_ANDLW, popGetLit (0x0F));
7027 emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
7028 emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
7032 case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
7033 /* works in-place/with offr as well */
7034 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
7035 for (i = size-2; i >= 0; i--) {
7036 emitpcode (POC_RRFW, popGet (AOP(left), i));
7037 emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
7039 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7040 emitpcode (POC_RRF, popGet (AOP(result), offr));
7044 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
7045 shiftLeft_Left2ResultLit (result, result, 1);
7046 return; /* prevent clearing result again */
7052 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7056 /*-----------------------------------------------------------------*/
7057 /* shiftRight_Left2ResultLit - shift right by known count */
7058 /*-----------------------------------------------------------------*/
7060 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
7062 int size, same, offr, i;
7064 size = AOP_SIZE(left);
7065 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7067 same = pic14_sameRegs (AOP(left), AOP(result));
7070 shCount = shCount & 0x07;
7078 case 0: /* takes 0 or 2N cycles (for offr==0) */
7079 if (!same || offr) {
7080 for (i=0; i < size; i++)
7081 movLeft2Result (left, i + offr, result, i);
7085 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7086 emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7088 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7089 shiftRight_Left2ResultLit (result, result, shCount, sign);
7090 return; /* prevent sign-extending result again */
7094 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7097 for (i = size-1; i >= 0; i--) {
7098 if (same && !offr) {
7099 emitpcode (POC_RRF, popGet (AOP(left), i));
7101 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7102 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7108 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7109 /* works in-place/with offr as well */
7110 emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7111 emitpcode (POC_ANDLW, popGetLit (0x0F));
7112 emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7114 for (i = 1; i < size; i++)
7116 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7117 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7118 emitpcode (POC_ANDLW, popGetLit (0xF0));
7119 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7120 emitpcode (POC_XORWF, popGet (AOP(result), i));
7125 emitpcode (POC_MOVLW, popGetLit (0xF0));
7126 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7127 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7131 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7132 /* works in-place/with offr as well */
7133 emitpcode (POC_RLFW, popGet (AOP(left), offr));
7134 for (i = 0; i < size-1; i++) {
7135 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7136 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7138 emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7140 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7143 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7148 shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7149 shiftRight_Left2ResultLit (result, result, 1, sign);
7150 return; /* prevent sign extending result again */
7155 addSign (result, size, sign);
7159 /*-----------------------------------------------------------------*/
7160 /* shiftL2Left2Result - shift left two bytes from left to result */
7161 /*-----------------------------------------------------------------*/
7162 static void shiftL2Left2Result (operand *left, int offl,
7163 operand *result, int offr, int shCount)
7167 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7169 if(pic14_sameRegs(AOP(result), AOP(left))) {
7177 emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7178 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7179 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7183 emitpcode(POC_RLF, popGet(AOP(result),offr));
7184 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7190 emitpcode(POC_MOVLW, popGetLit(0x0f));
7191 emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7192 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7193 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7194 emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7195 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7196 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7198 emitpcode(POC_RLF, popGet(AOP(result),offr));
7199 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7203 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7204 emitpcode(POC_RRF, popGet(AOP(result),offr));
7205 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7206 emitpcode(POC_RRF, popGet(AOP(result),offr));
7207 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7208 emitpcode(POC_ANDLW,popGetLit(0xc0));
7209 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7210 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7211 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7212 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7215 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7216 emitpcode(POC_RRFW, popGet(AOP(result),offr));
7217 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7218 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7219 emitpcode(POC_RRF, popGet(AOP(result),offr));
7229 /* note, use a mov/add for the shift since the mov has a
7230 chance of getting optimized out */
7231 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7232 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7233 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7234 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7235 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7239 emitpcode(POC_RLF, popGet(AOP(result),offr));
7240 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7246 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7247 emitpcode(POC_ANDLW, popGetLit(0xF0));
7248 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7249 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7250 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7251 emitpcode(POC_ANDLW, popGetLit(0xF0));
7252 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7253 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7257 emitpcode(POC_RLF, popGet(AOP(result),offr));
7258 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7262 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7263 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7264 emitpcode(POC_RRFW, popGet(AOP(result),offl));
7265 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7267 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7268 emitpcode(POC_RRF, popGet(AOP(result),offr));
7269 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7270 emitpcode(POC_ANDLW,popGetLit(0xc0));
7271 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7272 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7273 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7274 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7277 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7278 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7279 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7280 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7281 emitpcode(POC_RRF, popGet(AOP(result),offr));
7287 /*-----------------------------------------------------------------*/
7288 /* shiftR2Left2Result - shift right two bytes from left to result */
7289 /*-----------------------------------------------------------------*/
7290 static void shiftR2Left2Result (operand *left, int offl,
7291 operand *result, int offr,
7292 int shCount, int sign)
7297 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7298 same = pic14_sameRegs(AOP(result), AOP(left));
7300 if(same && ((offl + MSB16) == offr)){
7302 /* don't crash result[offr] */
7303 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7304 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7307 movLeft2Result(left,offl, result, offr);
7308 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7311 /* a:x >> shCount (x = lsb(result))*/
7314 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7316 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7325 emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7330 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7331 emitpcode(POC_RRF,popGet(AOP(result),offr));
7333 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7334 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7335 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7336 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7341 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7344 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7345 emitpcode(POC_RRF,popGet(AOP(result),offr));
7352 emitpcode(POC_MOVLW, popGetLit(0xf0));
7353 emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7354 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7356 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7357 emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7358 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7359 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7361 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7362 emitpcode(POC_ANDLW, popGetLit(0x0f));
7363 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7365 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7366 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7367 emitpcode(POC_ANDLW, popGetLit(0xf0));
7368 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7369 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7373 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7374 emitpcode(POC_RRF, popGet(AOP(result),offr));
7378 emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7379 emitpcode(POC_BTFSC,
7380 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7381 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7389 emitpcode(POC_RLF, popGet(AOP(result),offr));
7390 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7392 emitpcode(POC_RLF, popGet(AOP(result),offr));
7393 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7394 emitpcode(POC_RLFW, popGet(AOP(result),offr));
7395 emitpcode(POC_ANDLW,popGetLit(0x03));
7397 emitpcode(POC_BTFSC,
7398 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7399 emitpcode(POC_IORLW,popGetLit(0xfc));
7401 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7402 emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7403 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7404 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7406 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7407 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7408 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7409 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7410 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7411 emitpcode(POC_RLF, popGet(AOP(result),offr));
7412 emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7413 emitpcode(POC_ANDLW,popGetLit(0x03));
7415 emitpcode(POC_BTFSC,
7416 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7417 emitpcode(POC_IORLW,popGetLit(0xfc));
7419 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7420 //emitpcode(POC_RLF, popGet(AOP(result),offr));
7427 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7428 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7429 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7430 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7433 emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7435 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7439 /*-----------------------------------------------------------------*/
7440 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7441 /*-----------------------------------------------------------------*/
7442 static void shiftLLeftOrResult (operand *left, int offl,
7443 operand *result, int offr, int shCount)
7446 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7448 /* shift left accumulator */
7449 AccLsh(left,offl,shCount);
7450 /* or with result */
7451 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7452 assert ( !"broken (modifies left, fails for left==result))" );
7455 /*-----------------------------------------------------------------*/
7456 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7457 /*-----------------------------------------------------------------*/
7458 static void shiftRLeftOrResult (operand *left, int offl,
7459 operand *result, int offr, int shCount)
7462 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7464 /* shift right accumulator */
7465 AccRsh(left,offl,shCount);
7466 /* or with result */
7467 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7468 assert ( !"broken (modifies left, fails for left==result))" );
7471 /*-----------------------------------------------------------------*/
7472 /* genlshOne - left shift a one byte quantity by known count */
7473 /*-----------------------------------------------------------------*/
7474 static void genlshOne (operand *result, operand *left, int shCount)
7477 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7478 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7481 /*-----------------------------------------------------------------*/
7482 /* genlshTwo - left shift two bytes by known amount != 0 */
7483 /*-----------------------------------------------------------------*/
7484 static void genlshTwo (operand *result,operand *left, int shCount)
7489 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7490 size = pic14_getDataSize(result);
7492 /* if shCount >= 8 */
7498 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7500 movLeft2Result(left, LSB, result, MSB16);
7502 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7505 /* 1 <= shCount <= 7 */
7508 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7510 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7514 /*-----------------------------------------------------------------*/
7515 /* shiftLLong - shift left one long from left to result */
7516 /* offl = LSB or MSB16 */
7517 /*-----------------------------------------------------------------*/
7518 static void shiftLLong (operand *left, operand *result, int offr )
7521 int size = AOP_SIZE(result);
7524 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7525 if(size >= LSB+offr){
7526 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7528 pic14_emitcode("add","a,acc");
7529 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7530 size >= MSB16+offr && offr != LSB )
7531 pic14_emitcode("xch","a,%s",
7532 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7534 aopPut(AOP(result),"a",LSB+offr);
7537 if(size >= MSB16+offr){
7538 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7539 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7542 pic14_emitcode("rlc","a");
7543 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7544 size >= MSB24+offr && offr != LSB)
7545 pic14_emitcode("xch","a,%s",
7546 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7548 aopPut(AOP(result),"a",MSB16+offr);
7551 if(size >= MSB24+offr){
7552 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7553 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7556 pic14_emitcode("rlc","a");
7557 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7558 size >= MSB32+offr && offr != LSB )
7559 pic14_emitcode("xch","a,%s",
7560 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7562 aopPut(AOP(result),"a",MSB24+offr);
7565 if(size > MSB32+offr){
7566 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7567 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7570 pic14_emitcode("rlc","a");
7571 aopPut(AOP(result),"a",MSB32+offr);
7574 aopPut(AOP(result),zero,LSB);
7577 /*-----------------------------------------------------------------*/
7578 /* genlshFour - shift four byte by a known amount != 0 */
7579 /*-----------------------------------------------------------------*/
7580 static void genlshFour (operand *result, operand *left, int shCount)
7585 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7586 size = AOP_SIZE(result);
7588 /* if shifting more that 3 bytes */
7589 if (shCount >= 24 ) {
7592 /* lowest order of left goes to the highest
7593 order of the destination */
7594 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7596 movLeft2Result(left, LSB, result, MSB32);
7597 aopPut(AOP(result),zero,LSB);
7598 aopPut(AOP(result),zero,MSB16);
7599 aopPut(AOP(result),zero,MSB32);
7603 /* more than two bytes */
7604 else if ( shCount >= 16 ) {
7605 /* lower order two bytes goes to higher order two bytes */
7607 /* if some more remaining */
7609 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7611 movLeft2Result(left, MSB16, result, MSB32);
7612 movLeft2Result(left, LSB, result, MSB24);
7614 aopPut(AOP(result),zero,MSB16);
7615 aopPut(AOP(result),zero,LSB);
7619 /* if more than 1 byte */
7620 else if ( shCount >= 8 ) {
7621 /* lower order three bytes goes to higher order three bytes */
7625 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7627 movLeft2Result(left, LSB, result, MSB16);
7629 else{ /* size = 4 */
7631 movLeft2Result(left, MSB24, result, MSB32);
7632 movLeft2Result(left, MSB16, result, MSB24);
7633 movLeft2Result(left, LSB, result, MSB16);
7634 aopPut(AOP(result),zero,LSB);
7636 else if(shCount == 1)
7637 shiftLLong(left, result, MSB16);
7639 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7640 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7641 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7642 aopPut(AOP(result),zero,LSB);
7647 /* 1 <= shCount <= 7 */
7648 else if(shCount <= 2){
7649 shiftLLong(left, result, LSB);
7651 shiftLLong(result, result, LSB);
7653 /* 3 <= shCount <= 7, optimize */
7655 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7656 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7657 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7663 /*-----------------------------------------------------------------*/
7664 /* genLeftShiftLiteral - left shifting by known count */
7665 /*-----------------------------------------------------------------*/
7666 static void genLeftShiftLiteral (operand *left,
7671 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7675 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7676 freeAsmop(right,NULL,ic,TRUE);
7678 aopOp(left,ic,FALSE);
7679 aopOp(result,ic,FALSE);
7681 size = getSize(operandType(result));
7684 pic14_emitcode("; shift left ","result %d, left %d",size,
7688 /* I suppose that the left size >= result size */
7691 movLeft2Result(left, size, result, size);
7695 else if(shCount >= (size * 8))
7697 aopPut(AOP(result),zero,size);
7701 genlshOne (result,left,shCount);
7706 genlshTwo (result,left,shCount);
7710 genlshFour (result,left,shCount);
7714 freeAsmop(left,NULL,ic,TRUE);
7715 freeAsmop(result,NULL,ic,TRUE);
7719 /*-----------------------------------------------------------------*
7720 * genMultiAsm - repeat assembly instruction for size of register.
7721 * if endian == 1, then the high byte (i.e base address + size of
7722 * register) is used first else the low byte is used first;
7723 *-----------------------------------------------------------------*/
7724 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7730 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7743 emitpcode(poc, popGet(AOP(reg),offset));
7750 /*-----------------------------------------------------------------*/
7751 /* genLeftShift - generates code for left shifting */
7752 /*-----------------------------------------------------------------*/
7753 static void genLeftShift (iCode *ic)
7755 operand *left,*right, *result;
7757 unsigned long lit = 0L;
7759 symbol *tlbl , *tlbl1;
7763 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7765 right = IC_RIGHT(ic);
7767 result = IC_RESULT(ic);
7769 aopOp(right,ic,FALSE);
7770 aopOp(left,ic,FALSE);
7771 aopOp(result,ic,FALSE);
7774 /* if the shift count is known then do it
7775 as efficiently as possible */
7776 if (AOP_TYPE(right) == AOP_LIT) {
7777 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7781 /* shift count is unknown then we have to form
7782 a loop get the loop count in B : Note: we take
7783 only the lower order byte since shifting
7784 more that 32 bits make no sense anyway, ( the
7785 largest size of an object can be only 32 bits ) */
7787 /* this code fails for RIGHT == RESULT */
7788 assert (!pic14_sameRegs (AOP(right), AOP(result)));
7790 /* now move the left to the result if they are not the
7792 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
7793 AOP_SIZE(result) > 1) {
7795 size = AOP_SIZE(result);
7798 l = aopGet(AOP(left),offset,FALSE,TRUE);
7799 if (*l == '@' && (IS_AOP_PREG(result))) {
7801 pic14_emitcode("mov","a,%s",l);
7802 aopPut(AOP(result),"a",offset);
7804 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
7805 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7806 //aopPut(AOP(result),l,offset);
7812 if(AOP_TYPE(left) == AOP_LIT)
7813 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7815 size = AOP_SIZE(result);
7817 /* if it is only one byte then */
7819 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7820 emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7821 emitpcode(POC_ANDLW, popGetLit(0xf0));
7822 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7823 emitpcode(POC_MOVFW, popGet(AOP(left),0));
7824 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7825 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7826 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7827 emitpcode(POC_RLFW, popGet(AOP(result),0));
7828 emitpcode(POC_ANDLW, popGetLit(0xfe));
7829 emitpcode(POC_ADDFW, popGet(AOP(result),0));
7830 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7831 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7834 tlbl = newiTempLabel(NULL);
7835 if (!pic14_sameRegs(AOP(left),AOP(result))) {
7836 mov2w (AOP(left), 0);
7837 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7840 emitpcode(POC_COMFW, popGet(AOP(right),0));
7841 emitpcode(POC_RRF, popGet(AOP(result),0));
7842 emitpLabel(tlbl->key);
7843 emitpcode(POC_RLF, popGet(AOP(result),0));
7844 emitpcode(POC_ADDLW, popGetLit(1));
7846 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7851 if (pic14_sameRegs(AOP(left),AOP(result))) {
7853 tlbl = newiTempLabel(NULL);
7854 emitpcode(POC_COMFW, popGet(AOP(right),0));
7855 genMultiAsm(POC_RRF, result, size,1);
7856 emitpLabel(tlbl->key);
7857 genMultiAsm(POC_RLF, result, size,0);
7858 emitpcode(POC_ADDLW, popGetLit(1));
7860 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7864 //tlbl = newiTempLabel(NULL);
7866 //tlbl1 = newiTempLabel(NULL);
7868 //reAdjustPreg(AOP(result));
7870 //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7871 //pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7872 //l = aopGet(AOP(result),offset,FALSE,FALSE);
7874 //pic14_emitcode("add","a,acc");
7875 //aopPut(AOP(result),"a",offset++);
7877 // l = aopGet(AOP(result),offset,FALSE,FALSE);
7879 // pic14_emitcode("rlc","a");
7880 // aopPut(AOP(result),"a",offset++);
7882 //reAdjustPreg(AOP(result));
7884 //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7885 //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7888 tlbl = newiTempLabel(NULL);
7889 tlbl1= newiTempLabel(NULL);
7891 size = AOP_SIZE(result);
7894 pctemp = popGetTempReg(); /* grab a temporary working register. */
7896 emitpcode(POC_MOVFW, popGet(AOP(right),0));
7898 /* offset should be 0, 1 or 3 */
7899 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7901 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
7903 emitpcode(POC_MOVWF, pctemp);
7906 emitpLabel(tlbl->key);
7909 emitpcode(POC_RLF, popGet(AOP(result),0));
7911 emitpcode(POC_RLF, popGet(AOP(result),offset++));
7913 emitpcode(POC_DECFSZ, pctemp);
7914 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7915 emitpLabel(tlbl1->key);
7917 popReleaseTempReg(pctemp);
7921 freeAsmop (right,NULL,ic,TRUE);
7922 freeAsmop(left,NULL,ic,TRUE);
7923 freeAsmop(result,NULL,ic,TRUE);
7928 /*-----------------------------------------------------------------*/
7929 /* genrshOne - right shift a one byte quantity by known count */
7930 /*-----------------------------------------------------------------*/
7931 static void genrshOne (operand *result, operand *left,
7932 int shCount, int sign)
7935 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7936 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7939 /*-----------------------------------------------------------------*/
7940 /* genrshTwo - right shift two bytes by known amount != 0 */
7941 /*-----------------------------------------------------------------*/
7942 static void genrshTwo (operand *result,operand *left,
7943 int shCount, int sign)
7946 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7947 /* if shCount >= 8 */
7951 shiftR1Left2Result(left, MSB16, result, LSB,
7954 movLeft2Result(left, MSB16, result, LSB);
7956 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7959 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7960 emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7964 /* 1 <= shCount <= 7 */
7966 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
7969 /*-----------------------------------------------------------------*/
7970 /* shiftRLong - shift right one long from left to result */
7971 /* offl = LSB or MSB16 */
7972 /*-----------------------------------------------------------------*/
7973 static void shiftRLong (operand *left, int offl,
7974 operand *result, int sign)
7979 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7981 size = AOP_SIZE(left);
7982 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7985 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7989 assert (offl >= 0 && offl < size);
7991 same = pic14_sameRegs (AOP(left), AOP(result));
7993 /* perform the shift */
7996 if (same && !offl) {
7997 emitpcode (POC_RRF, popGet (AOP(result), size));
7999 emitpcode (POC_RRFW, popGet (AOP(left), size));
8000 emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
8004 addSign (result, AOP_SIZE(left) - offl, sign);
8007 /*-----------------------------------------------------------------*/
8008 /* genrshFour - shift four byte by a known amount != 0 */
8009 /*-----------------------------------------------------------------*/
8010 static void genrshFour (operand *result, operand *left,
8011 int shCount, int sign)
8014 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8015 /* if shifting more that 3 bytes */
8016 if(shCount >= 24 ) {
8019 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8021 movLeft2Result(left, MSB32, result, LSB);
8023 addSign(result, MSB16, sign);
8025 else if(shCount >= 16){
8028 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8030 movLeft2Result(left, MSB24, result, LSB);
8031 movLeft2Result(left, MSB32, result, MSB16);
8033 addSign(result, MSB24, sign);
8035 else if(shCount >= 8){
8038 shiftRLong(left, MSB16, result, sign);
8039 else if(shCount == 0){
8040 movLeft2Result(left, MSB16, result, LSB);
8041 movLeft2Result(left, MSB24, result, MSB16);
8042 movLeft2Result(left, MSB32, result, MSB24);
8043 addSign(result, MSB32, sign);
8046 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8047 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8048 /* the last shift is signed */
8049 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8050 addSign(result, MSB32, sign);
8053 else{ /* 1 <= shCount <= 7 */
8055 shiftRLong(left, LSB, result, sign);
8057 shiftRLong(result, LSB, result, sign);
8060 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8061 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8062 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8067 /*-----------------------------------------------------------------*/
8068 /* genRightShiftLiteral - right shifting by known count */
8069 /*-----------------------------------------------------------------*/
8070 static void genRightShiftLiteral (operand *left,
8076 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8080 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8081 freeAsmop(right,NULL,ic,TRUE);
8083 aopOp(left,ic,FALSE);
8084 aopOp(result,ic,FALSE);
8087 pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8091 lsize = pic14_getDataSize(left);
8092 res_size = pic14_getDataSize(result);
8093 /* test the LEFT size !!! */
8095 /* I suppose that the left size >= result size */
8098 movLeft2Result(left, res_size, result, res_size);
8101 else if(shCount >= (lsize * 8)){
8104 emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8106 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8107 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8112 emitpcode(POC_MOVLW, popGetLit(0));
8113 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8114 emitpcode(POC_MOVLW, popGetLit(0xff));
8116 emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8121 emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8128 genrshOne (result,left,shCount,sign);
8132 genrshTwo (result,left,shCount,sign);
8136 genrshFour (result,left,shCount,sign);
8144 freeAsmop(left,NULL,ic,TRUE);
8145 freeAsmop(result,NULL,ic,TRUE);
8150 /*-----------------------------------------------------------------*/
8151 /* genSignedRightShift - right shift of signed number */
8152 /*-----------------------------------------------------------------*/
8153 static void genSignedRightShift (iCode *ic)
8155 operand *right, *left, *result;
8158 symbol *tlbl, *tlbl1 ;
8161 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8163 /* we do it the hard way put the shift count in b
8164 and loop thru preserving the sign */
8166 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8168 right = IC_RIGHT(ic);
8170 result = IC_RESULT(ic);
8172 aopOp(right,ic,FALSE);
8173 aopOp(left,ic,FALSE);
8174 aopOp(result,ic,FALSE);
8177 if ( AOP_TYPE(right) == AOP_LIT) {
8178 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8179 //genRightShiftLiteral (left,right,result,ic,1);
8182 /* shift count is unknown then we have to form
8183 a loop get the loop count in B : Note: we take
8184 only the lower order byte since shifting
8185 more that 32 bits make no sense anyway, ( the
8186 largest size of an object can be only 32 bits ) */
8188 //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8189 //pic14_emitcode("inc","b");
8190 //freeAsmop (right,NULL,ic,TRUE);
8191 //aopOp(left,ic,FALSE);
8192 //aopOp(result,ic,FALSE);
8194 /* now move the left to the result if they are not the
8196 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
8197 AOP_SIZE(result) > 1) {
8199 size = AOP_SIZE(result);
8203 l = aopGet(AOP(left),offset,FALSE,TRUE);
8204 if (*l == '@' && IS_AOP_PREG(result)) {
8205 pic14_emitcode("mov","a,%s",l);
8206 aopPut(AOP(result),"a",offset);
8208 aopPut(AOP(result),l,offset);
8210 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8211 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8217 /* mov the highest order bit to OVR */
8218 tlbl = newiTempLabel(NULL);
8219 tlbl1= newiTempLabel(NULL);
8221 size = AOP_SIZE(result);
8224 pctemp = popGetTempReg(); /* grab a temporary working register. */
8226 emitpcode(POC_MOVFW, popGet(AOP(right),0));
8228 /* offset should be 0, 1 or 3 */
8229 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8231 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8233 emitpcode(POC_MOVWF, pctemp);
8236 emitpLabel(tlbl->key);
8238 emitpcode(POC_RLFW, popGet(AOP(result),offset));
8239 emitpcode(POC_RRF, popGet(AOP(result),offset));
8242 emitpcode(POC_RRF, popGet(AOP(result),--offset));
8245 emitpcode(POC_DECFSZ, pctemp);
8246 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8247 emitpLabel(tlbl1->key);
8249 popReleaseTempReg(pctemp);
8251 size = AOP_SIZE(result);
8253 pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8254 pic14_emitcode("rlc","a");
8255 pic14_emitcode("mov","ov,c");
8256 /* if it is only one byte then */
8258 l = aopGet(AOP(left),0,FALSE,FALSE);
8260 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8261 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8262 pic14_emitcode("mov","c,ov");
8263 pic14_emitcode("rrc","a");
8264 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8265 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8266 aopPut(AOP(result),"a",0);
8270 reAdjustPreg(AOP(result));
8271 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8272 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8273 pic14_emitcode("mov","c,ov");
8275 l = aopGet(AOP(result),offset,FALSE,FALSE);
8277 pic14_emitcode("rrc","a");
8278 aopPut(AOP(result),"a",offset--);
8280 reAdjustPreg(AOP(result));
8281 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8282 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8287 freeAsmop(left,NULL,ic,TRUE);
8288 freeAsmop(result,NULL,ic,TRUE);
8289 freeAsmop(right,NULL,ic,TRUE);
8293 /*-----------------------------------------------------------------*/
8294 /* loadSignToC - load the operand's sign bit into CARRY */
8295 /*-----------------------------------------------------------------*/
8297 static void loadSignToC (operand *op)
8300 assert (op && AOP(op) && AOP_SIZE(op));
8303 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8307 /*-----------------------------------------------------------------*/
8308 /* genRightShift - generate code for right shifting */
8309 /*-----------------------------------------------------------------*/
8310 static void genGenericShift (iCode *ic, int shiftRight)
8312 operand *right, *left, *result;
8315 symbol *tlbl, *tlbl1, *inverselbl;
8318 /* if signed then we do it the hard way preserve the
8319 sign bit moving it inwards */
8320 retype = getSpec(operandType(IC_RESULT(ic)));
8321 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8323 /* signed & unsigned types are treated the same : i.e. the
8324 signed is NOT propagated inwards : quoting from the
8325 ANSI - standard : "for E1 >> E2, is equivalent to division
8326 by 2**E2 if unsigned or if it has a non-negative value,
8327 otherwise the result is implementation defined ", MY definition
8328 is that the sign does not get propagated */
8330 right = IC_RIGHT(ic);
8332 result = IC_RESULT(ic);
8334 aopOp(right,ic,FALSE);
8335 aopOp(left,ic,FALSE);
8336 aopOp(result,ic,FALSE);
8338 /* if the shift count is known then do it
8339 as efficiently as possible */
8340 if (AOP_TYPE(right) == AOP_LIT) {
8341 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8345 shiftRight = !shiftRight;
8349 shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8351 shiftLeft_Left2ResultLit (left, result, lit);
8352 //genRightShiftLiteral (left,right,result,ic, 0);
8356 /* shift count is unknown then we have to form
8357 a loop get the loop count in B : Note: we take
8358 only the lower order byte since shifting
8359 more that 32 bits make no sense anyway, ( the
8360 largest size of an object can be only 32 bits ) */
8362 /* we must not overwrite the shift counter */
8363 assert (!pic14_sameRegs(AOP(right),AOP(result)));
8365 /* now move the left to the result if they are not the
8367 if (!pic14_sameRegs(AOP(left),AOP(result)))
8369 size = min(AOP_SIZE(result), AOP_SIZE(left));
8371 mov2w(AOP(left), size);
8372 movwf(AOP(result), size);
8374 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8377 tlbl = newiTempLabel(NULL);
8378 tlbl1= newiTempLabel(NULL);
8380 size = AOP_SIZE(result);
8382 mov2w(AOP(right),0);
8383 if (!SPEC_USIGN(operandType(right)))
8385 inverselbl = newiTempLabel(NULL);
8386 /* signed shift count -- invert shift direction for c<0 */
8387 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8388 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8390 emitpcode(POC_SUBLW, popGetLit(0)); /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8391 /* check for `a = b >> c' with `-c == 0' */
8393 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8394 emitpLabel(tlbl->key);
8395 /* propagate the sign bit inwards for SIGNED result */
8396 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8397 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8398 emitpcode(POC_ADDLW, popGetLit(1)); /* clears CARRY (unless W==0 afterwards) */
8400 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8402 if (!SPEC_USIGN(operandType(right)))
8404 symbol *inv_loop = newiTempLabel(NULL);
8406 shiftRight = !shiftRight; /* invert shift direction */
8408 /* we came here from the code above -- we are done */
8409 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8411 /* emit code for shifting N<0 steps, count is already in W */
8412 emitpLabel(inverselbl->key);
8413 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8414 emitpLabel(inv_loop->key);
8415 /* propagate the sign bit inwards for SIGNED result */
8416 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8417 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8418 emitpcode(POC_ADDLW, popGetLit(1));
8420 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8423 emitpLabel(tlbl1->key);
8425 freeAsmop(left,NULL,ic,TRUE);
8426 freeAsmop (right,NULL,ic,TRUE);
8427 freeAsmop(result,NULL,ic,TRUE);
8430 static void genRightShift (iCode *ic)
8432 genGenericShift(ic, 1);
8435 static void genLeftShift (iCode *ic)
8437 genGenericShift(ic, 0);
8440 /*-----------------------------------------------------------------*/
8441 /* SetIrp - Set IRP bit */
8442 /*-----------------------------------------------------------------*/
8443 void SetIrp(operand *result) {
8445 if (AOP_TYPE(result) == AOP_LIT) {
8446 unsigned lit = (unsigned)operandLitValue(result);
8452 if (PCOP(AOP(result))->type == PO_LITERAL) {
8453 int addrs = PCOL(AOP(result))->lit;
8459 emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8460 if(AOP_SIZE(result) > 1) {
8461 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8469 setup_fsr (operand *ptr)
8472 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8474 /* also setup-up IRP */
8478 /*-----------------------------------------------------------------*/
8479 /* emitPtrByteGet - emits code to get a byte into WREG from an */
8480 /* arbitrary pointer (__code, __data, generic) */
8481 /*-----------------------------------------------------------------*/
8483 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8490 if (!alreadyAddressed) setup_fsr (src);
8491 emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8495 assert( AOP_SIZE(src) == 2 );
8497 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8499 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8500 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
8501 call_libraryfunc ("__gptrget1");
8505 assert( AOP_SIZE(src) == 3 );
8507 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8509 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8511 call_libraryfunc ("__gptrget1");
8515 assert( !"unhandled pointer type" );
8520 /*-----------------------------------------------------------------*/
8521 /* emitPtrByteSet - emits code to set a byte from src through a */
8522 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR). */
8523 /*-----------------------------------------------------------------*/
8525 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8532 if (!alreadyAddressed) setup_fsr (dst);
8533 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8537 assert( !"trying to assign to __code pointer" );
8541 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8543 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8545 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8547 call_libraryfunc ("__gptrput1");
8551 assert( !"unhandled pointer type" );
8556 /*-----------------------------------------------------------------*/
8557 /* genUnpackBits - generates code for unpacking bits */
8558 /*-----------------------------------------------------------------*/
8559 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8561 int rsize; /* result size */
8562 sym_link *etype; /* bitfield type information */
8563 int blen; /* bitfield length */
8564 int bstr; /* bitfield starting bit within byte */
8567 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8568 etype = getSpec(operandType(result));
8569 rsize = getSize (operandType (result));
8570 blen = SPEC_BLEN (etype);
8571 bstr = SPEC_BSTR (etype);
8573 /* single bit field case */
8575 if (ifx) { /* that is for an if statement */
8578 resolveIfx(&rIfx,ifx);
8579 if (ptype == -1) /* direct */
8580 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8582 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8583 emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8584 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8588 assert (!pic14_sameRegs (AOP(result), AOP(left)));
8589 for (i=0; i < AOP_SIZE(result); i++)
8590 emitpcode (POC_CLRF, popGet (AOP(result), i));
8595 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8596 /* adjust result below */
8603 emitPtrByteGet (left, ptype, FALSE);
8604 emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8606 /* adjust result below */
8610 assert( !"unhandled pointer type" );
8613 /* move sign-/zero extended bit to result */
8614 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8615 emitpcode (POC_INCF, popGet (AOP(result), 0));
8617 emitpcode (POC_DECF, popGet (AOP(result), 0));
8619 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8623 else if (blen <= 8 && ((blen + bstr) <= 8))
8628 for (i=0; i < AOP_SIZE(result); i++)
8629 emitpcode (POC_CLRF, popGet (AOP(result), i));
8634 mov2w(AOP(left), 0);
8641 emitPtrByteGet (left, ptype, FALSE);
8645 assert( !"unhandled pointer type" );
8649 emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8650 movwf(AOP(result), 0);
8651 AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8653 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8655 /* signed bitfield */
8656 assert (bstr + blen > 0);
8657 emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8658 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8659 emitpcode(POC_IORWF, popGet(AOP(result),0));
8661 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8665 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8669 /*-----------------------------------------------------------------*/
8670 /* genDataPointerGet - generates code when ptr offset is known */
8671 /*-----------------------------------------------------------------*/
8672 static void genDataPointerGet (operand *left,
8676 int size , offset = 0;
8679 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8682 /* optimization - most of the time, left and result are the same
8683 * address, but different types. for the pic code, we could omit
8686 aopOp(result,ic,TRUE);
8688 if (pic14_sameRegs (AOP(left), AOP(result)))
8691 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8693 //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8695 size = AOP_SIZE(result);
8696 if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8700 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8701 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8705 freeAsmop(left,NULL,ic,TRUE);
8706 freeAsmop(result,NULL,ic,TRUE);
8710 /*-----------------------------------------------------------------*/
8711 /* genNearPointerGet - pic14_emitcode for near pointer fetch */
8712 /*-----------------------------------------------------------------*/
8713 static void genNearPointerGet (operand *left,
8718 sym_link *ltype = operandType(left);
8719 sym_link *rtype = operandType(result);
8720 sym_link *retype= getSpec(rtype); /* bitfield type information */
8724 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8727 aopOp(left,ic,FALSE);
8729 /* if left is rematerialisable and
8730 result is not bit variable type and
8731 the left is pointer to data space i.e
8732 lower 128 bytes of space */
8733 if (AOP_TYPE(left) == AOP_PCODE && //AOP_TYPE(left) == AOP_IMMD &&
8734 !IS_BITVAR(retype) &&
8735 PIC_IS_DATA_PTR(ltype)) {
8736 genDataPointerGet (left,result,ic);
8740 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8741 aopOp (result,ic,FALSE);
8743 /* Check if can access directly instead of via a pointer */
8744 if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8745 && AOP_SIZE(result) == 1)
8750 if (IS_BITFIELD(getSpec(operandType(result))))
8752 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8756 /* If the pointer value is not in a the FSR then need to put it in */
8757 /* Must set/reset IRP bit for use with FSR. */
8762 /* if bitfield then unpack the bits */
8764 /* we have can just get the values */
8765 int size = AOP_SIZE(result);
8768 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8772 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8774 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8775 if (AOP_TYPE(result) == AOP_LIT) {
8776 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8778 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8780 if (size && !direct)
8781 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8786 /* now some housekeeping stuff */
8788 /* we had to allocate for this iCode */
8789 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8790 freeAsmop(NULL,aop,ic,TRUE);
8792 /* we did not allocate which means left
8793 already in a pointer register, then
8794 if size > 0 && this could be used again
8795 we have to point it back to where it
8797 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8798 if (AOP_SIZE(result) > 1 &&
8799 !OP_SYMBOL(left)->remat &&
8800 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8802 int size = AOP_SIZE(result) - 1;
8804 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8810 freeAsmop(left,NULL,ic,TRUE);
8811 freeAsmop(result,NULL,ic,TRUE);
8816 /*-----------------------------------------------------------------*/
8817 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch */
8818 /*-----------------------------------------------------------------*/
8819 static void genPagedPointerGet (operand *left,
8826 sym_link *rtype, *retype;
8829 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8831 rtype = operandType(result);
8832 retype= getSpec(rtype);
8834 aopOp(left,ic,FALSE);
8836 /* if the value is already in a pointer register
8837 then don't need anything more */
8838 if (!AOP_INPREG(AOP(left))) {
8839 /* otherwise get a free pointer register */
8841 preg = getFreePtr(ic,&aop,FALSE);
8842 pic14_emitcode("mov","%s,%s",
8844 aopGet(AOP(left),0,FALSE,TRUE));
8845 rname = preg->name ;
8847 rname = aopGet(AOP(left),0,FALSE,FALSE);
8849 freeAsmop(left,NULL,ic,TRUE);
8850 aopOp (result,ic,FALSE);
8852 /* if bitfield then unpack the bits */
8853 if (IS_BITFIELD(retype))
8854 genUnpackBits (result,left,rname,PPOINTER,0);
8856 /* we have can just get the values */
8857 int size = AOP_SIZE(result);
8862 pic14_emitcode("movx","a,@%s",rname);
8863 aopPut(AOP(result),"a",offset);
8868 pic14_emitcode("inc","%s",rname);
8872 /* now some housekeeping stuff */
8874 /* we had to allocate for this iCode */
8875 freeAsmop(NULL,aop,ic,TRUE);
8877 /* we did not allocate which means left
8878 already in a pointer register, then
8879 if size > 0 && this could be used again
8880 we have to point it back to where it
8882 if (AOP_SIZE(result) > 1 &&
8883 !OP_SYMBOL(left)->remat &&
8884 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8886 int size = AOP_SIZE(result) - 1;
8888 pic14_emitcode("dec","%s",rname);
8893 freeAsmop(result,NULL,ic,TRUE);
8898 /*-----------------------------------------------------------------*/
8899 /* genFarPointerGet - gget value from far space */
8900 /*-----------------------------------------------------------------*/
8901 static void genFarPointerGet (operand *left,
8902 operand *result, iCode *ic)
8905 sym_link *retype = getSpec(operandType(result));
8908 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8910 aopOp(left,ic,FALSE);
8912 /* if the operand is already in dptr
8913 then we do nothing else we move the value to dptr */
8914 if (AOP_TYPE(left) != AOP_STR) {
8915 /* if this is remateriazable */
8916 if (AOP_TYPE(left) == AOP_IMMD)
8917 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8918 else { /* we need to get it byte by byte */
8919 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8920 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8921 if (options.model == MODEL_FLAT24)
8923 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8927 /* so dptr know contains the address */
8928 freeAsmop(left,NULL,ic,TRUE);
8929 aopOp(result,ic,FALSE);
8931 /* if bit then unpack */
8932 if (IS_BITFIELD(retype))
8933 genUnpackBits(result,left,"dptr",FPOINTER,0);
8935 size = AOP_SIZE(result);
8939 pic14_emitcode("movx","a,@dptr");
8940 aopPut(AOP(result),"a",offset++);
8942 pic14_emitcode("inc","dptr");
8946 freeAsmop(result,NULL,ic,TRUE);
8951 /*-----------------------------------------------------------------*/
8952 /* genCodePointerGet - get value from code space */
8953 /*-----------------------------------------------------------------*/
8954 static void genCodePointerGet (operand *left,
8955 operand *result, iCode *ic)
8958 sym_link *retype = getSpec(operandType(result));
8960 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8962 aopOp(left,ic,FALSE);
8964 /* if the operand is already in dptr
8965 then we do nothing else we move the value to dptr */
8966 if (AOP_TYPE(left) != AOP_STR) {
8967 /* if this is remateriazable */
8968 if (AOP_TYPE(left) == AOP_IMMD)
8969 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8970 else { /* we need to get it byte by byte */
8971 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8972 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8973 if (options.model == MODEL_FLAT24)
8975 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8979 /* so dptr know contains the address */
8980 freeAsmop(left,NULL,ic,TRUE);
8981 aopOp(result,ic,FALSE);
8983 /* if bit then unpack */
8984 if (IS_BITFIELD(retype))
8985 genUnpackBits(result,left,"dptr",CPOINTER,0);
8987 size = AOP_SIZE(result);
8991 pic14_emitcode("clr","a");
8992 pic14_emitcode("movc","a,@a+dptr");
8993 aopPut(AOP(result),"a",offset++);
8995 pic14_emitcode("inc","dptr");
8999 freeAsmop(result,NULL,ic,TRUE);
9002 /*-----------------------------------------------------------------*/
9003 /* genGenPointerGet - gget value from generic pointer space */
9004 /*-----------------------------------------------------------------*/
9005 static void genGenPointerGet (operand *left,
9006 operand *result, iCode *ic)
9009 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9010 aopOp(left,ic,FALSE);
9011 aopOp(result,ic,FALSE);
9014 DEBUGpic14_AopType(__LINE__,left,NULL,result);
9016 if (IS_BITFIELD(getSpec(operandType(result))))
9018 genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
9023 /* emit call to __gptrget */
9024 char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
9025 int size = AOP_SIZE(result);
9028 assert (size > 0 && size <= 4);
9030 /* pass arguments */
9031 assert (AOP_SIZE(left) == 3);
9032 mov2w(AOP(left), 0);
9033 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9034 mov2w(AOP(left), 1);
9035 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9036 mov2w(AOP(left), 2);
9037 call_libraryfunc (func[size]);
9040 movwf (AOP(result), --size);
9042 emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
9043 movwf (AOP(result), size);
9047 freeAsmop(left,NULL,ic,TRUE);
9048 freeAsmop(result,NULL,ic,TRUE);
9052 /*-----------------------------------------------------------------*/
9053 /* genConstPointerGet - get value from const generic pointer space */
9054 /*-----------------------------------------------------------------*/
9055 static void genConstPointerGet (operand *left,
9056 operand *result, iCode *ic)
9058 //sym_link *retype = getSpec(operandType(result));
9060 symbol *albl, *blbl;//, *clbl;
9067 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9068 aopOp(left,ic,FALSE);
9069 aopOp(result,ic,FALSE);
9071 size = AOP_SIZE(result);
9073 DEBUGpic14_AopType(__LINE__,left,NULL,result);
9075 DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
9077 lit = op_isLitLike (left);
9078 poc = lit ? POC_MOVLW : POC_MOVFW;
9080 if (IS_BITFIELD(getSpec(operandType(result))))
9082 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
9087 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
9088 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
9089 assert (size > 0 && size <= 4);
9092 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9094 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9095 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
9096 call_libraryfunc (func[size]);
9098 movwf(AOP(result),size-1);
9099 for (i = 1; i < size; i++)
9101 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
9102 movwf(AOP(result),size - 1 - i);
9107 freeAsmop(left,NULL,ic,TRUE);
9108 freeAsmop(result,NULL,ic,TRUE);
9111 /*-----------------------------------------------------------------*/
9112 /* genPointerGet - generate code for pointer get */
9113 /*-----------------------------------------------------------------*/
9114 static void genPointerGet (iCode *ic)
9116 operand *left, *result ;
9117 sym_link *type, *etype;
9121 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9124 result = IC_RESULT(ic) ;
9126 /* depending on the type of pointer we need to
9127 move it to the correct pointer register */
9128 type = operandType(left);
9129 etype = getSpec(type);
9131 if (IS_PTR_CONST(type))
9132 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9134 /* if left is of type of pointer then it is simple */
9135 if (IS_PTR(type) && !IS_FUNC(type->next))
9136 p_type = DCL_TYPE(type);
9138 /* we have to go by the storage class */
9139 p_type = PTR_TYPE(SPEC_OCLS(etype));
9141 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9143 if (SPEC_OCLS(etype)->codesp ) {
9144 DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9145 //p_type = CPOINTER ;
9148 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9149 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9150 /*p_type = FPOINTER ;*/
9152 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9153 DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9154 /* p_type = PPOINTER; */
9156 if (SPEC_OCLS(etype) == idata )
9157 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9158 /* p_type = IPOINTER; */
9160 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9161 /* p_type = POINTER ; */
9164 /* now that we have the pointer type we assign
9165 the pointer values */
9171 genNearPointerGet (left,result,ic);
9175 genPagedPointerGet(left,result,ic);
9179 genFarPointerGet (left,result,ic);
9183 genConstPointerGet (left,result,ic);
9187 genGenPointerGet (left,result,ic);
9190 assert ( !"unhandled pointer type" );
9196 /*-----------------------------------------------------------------*/
9197 /* genPackBits - generates code for packed bit storage */
9198 /*-----------------------------------------------------------------*/
9199 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9201 int blen; /* bitfield length */
9202 int bstr; /* bitfield starting bit within byte */
9203 int litval; /* source literal value (if AOP_LIT) */
9204 unsigned char mask; /* bitmask within current byte */
9207 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9209 blen = SPEC_BLEN (etype);
9210 bstr = SPEC_BSTR (etype);
9212 /* If the bitfield length is less than a byte and does not cross byte boundaries */
9213 if ((blen <= 8) && ((bstr + blen) <= 8))
9215 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9216 (unsigned char) (0xFF >> (8 - bstr)));
9218 if (AOP_TYPE (right) == AOP_LIT)
9220 /* Case with a bitfield length <8 and literal source */
9221 int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9228 if (AOP(result)->type == AOP_PCODE)
9229 pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9231 pcop = popGet(AOP(result),0);
9232 emitpcode(lit?POC_BSF:POC_BCF,pcop);
9238 emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9242 assert( !"trying to assign to bitfield via pointer to __code space" );
9246 emitPtrByteGet(result, p_type, FALSE);
9248 emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9250 emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9252 emitPtrByteSet(result, p_type, TRUE);
9256 assert( !"unhandled pointer type" );
9258 } // switch (p_type)
9261 litval = lit << bstr;
9262 litval &= (~mask) & 0x00ff;
9267 mov2w (AOP(result), 0);
9268 if ((litval|mask) != 0x00ff)
9269 emitpcode(POC_ANDLW, popGetLit (mask));
9271 emitpcode(POC_IORLW, popGetLit (litval));
9272 movwf (AOP(result), 0);
9278 emitPtrByteGet(result, p_type, FALSE);
9279 if ((litval|mask) != 0x00ff)
9280 emitpcode(POC_ANDLW, popGetLit (mask));
9282 emitpcode(POC_IORLW, popGetLit (litval));
9283 emitPtrByteSet(result, p_type, TRUE);
9287 assert( !"trying to assign to bitfield via pointer to __code space" );
9291 assert( !"unhandled pointer type" );
9298 /* right is no literal */
9303 /* Note more efficient code, of pre clearing bit then only setting it if required,
9304 * can only be done if it is known that the result is not a SFR */
9305 emitpcode(POC_RRFW,popGet(AOP(right),0));
9307 emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9309 emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9315 emitPtrByteGet (result, p_type, FALSE);
9316 emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9317 emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9318 emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9319 emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9320 emitPtrByteSet (result, p_type, TRUE);
9324 assert( !"trying to assign to bitfield via pointer to __code space" );
9328 assert( !"unhandled pointer type" );
9333 /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9334 pCodeOp *temp = popGetTempReg ();
9336 mov2w (AOP(right), 0);
9338 emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9340 emitpcode(POC_MOVWF, temp);
9342 AccLsh (temp, bstr);
9348 mov2w (AOP(result), 0);
9349 emitpcode(POC_ANDLW, popGetLit (mask));
9350 emitpcode(POC_IORFW, temp);
9351 movwf (AOP(result), 0);
9357 emitPtrByteGet (result, p_type, FALSE);
9358 emitpcode(POC_ANDLW, popGetLit (mask));
9359 emitpcode(POC_IORFW, temp);
9360 emitPtrByteSet (result, p_type, TRUE);
9364 assert( !"trying to assign to bitfield via pointer to __code space" );
9368 assert( !"unhandled pointer type" );
9372 popReleaseTempReg (temp);
9374 } // if (AOP(right)->type != AOP_LIT)
9376 } // if (blen <= 8 && ((blen + bstr) <= 8))
9378 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9381 /*-----------------------------------------------------------------*/
9382 /* genDataPointerSet - remat pointer to data space */
9383 /*-----------------------------------------------------------------*/
9384 static void genDataPointerSet(operand *right,
9388 int size, offset = 0 ;
9392 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9393 aopOp(right,ic,FALSE);
9394 aopOp(result,ic,FALSE);
9396 assert (IS_SYMOP(result));
9397 assert (IS_PTR(OP_SYM_TYPE(result)));
9399 if (AOP_TYPE(right) == AOP_LIT)
9402 size = AOP_SIZE(right);
9403 ressize = getSize(OP_SYM_ETYPE(result));
9404 if (size > ressize) size = ressize;
9405 //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9407 //assert( !"what's going on here?" );
9410 if ( AOP_TYPE(result) == AOP_PCODE) {
9411 fprintf(stderr,"genDataPointerSet %s, %d\n",
9412 AOP(result)->aopu.pcop->name,
9413 PCOI(AOP(result)->aopu.pcop)->offset);
9417 // tsd, was l+1 - the underline `_' prefix was being stripped
9419 emitpComment ("%s:%u: size=%d/%d, offset=%d, AOP_TYPE(res)=%d", __FILE__,__LINE__, size, ressize, offset, AOP_TYPE(result));
9421 if (AOP_TYPE(right) == AOP_LIT) {
9422 unsigned int lit = pic14aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
9423 //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9425 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9426 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9428 emitpcode(POC_CLRF, popGet(AOP(result), offset));
9431 //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9432 emitpcode(POC_MOVFW, popGet(AOP(right), offset));
9433 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9439 freeAsmop(right,NULL,ic,TRUE);
9440 freeAsmop(result,NULL,ic,TRUE);
9443 /*-----------------------------------------------------------------*/
9444 /* genNearPointerSet - pic14_emitcode for near pointer put */
9445 /*-----------------------------------------------------------------*/
9446 static void genNearPointerSet (operand *right,
9451 sym_link *ptype = operandType(result);
9452 sym_link *retype = getSpec(operandType(right));
9453 sym_link *letype = getSpec(ptype);
9458 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9459 aopOp(result,ic,FALSE);
9462 /* if the result is rematerializable &
9463 in data space & not a bit variable */
9464 //if (AOP_TYPE(result) == AOP_IMMD &&
9465 if (AOP_TYPE(result) == AOP_PCODE &&
9466 PIC_IS_DATA_PTR(ptype) &&
9467 !IS_BITVAR (retype) &&
9468 !IS_BITVAR (letype)) {
9469 genDataPointerSet (right,result,ic);
9470 freeAsmop(result,NULL,ic,TRUE);
9475 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9476 aopOp(right,ic,FALSE);
9477 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9479 /* Check if can access directly instead of via a pointer */
9480 if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9484 if (IS_BITFIELD (letype))
9486 genPackBits (letype, result, right, direct?-1:POINTER);
9490 /* If the pointer value is not in a the FSR then need to put it in */
9491 /* Must set/reset IRP bit for use with FSR. */
9492 /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9497 /* we have can just get the values */
9498 int size = AOP_SIZE(right);
9501 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9503 char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9505 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9507 if (AOP_TYPE(right) == AOP_LIT) {
9508 emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9510 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9513 emitpcode(POC_MOVWF,popGet(AOP(result),0));
9515 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9517 if (size && !direct)
9518 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9523 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9524 /* now some housekeeping stuff */
9526 /* we had to allocate for this iCode */
9527 freeAsmop(NULL,aop,ic,TRUE);
9529 /* we did not allocate which means left
9530 already in a pointer register, then
9531 if size > 0 && this could be used again
9532 we have to point it back to where it
9534 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9535 if (AOP_SIZE(right) > 1 &&
9536 !OP_SYMBOL(result)->remat &&
9537 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9539 int size = AOP_SIZE(right) - 1;
9541 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9545 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9548 freeAsmop(right,NULL,ic,TRUE);
9549 freeAsmop(result,NULL,ic,TRUE);
9553 /*-----------------------------------------------------------------*/
9554 /* genPagedPointerSet - pic14_emitcode for Paged pointer put */
9555 /*-----------------------------------------------------------------*/
9556 static void genPagedPointerSet (operand *right,
9566 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9568 retype= getSpec(operandType(right));
9570 aopOp(result,ic,FALSE);
9572 /* if the value is already in a pointer register
9573 then don't need anything more */
9574 if (!AOP_INPREG(AOP(result))) {
9575 /* otherwise get a free pointer register */
9577 preg = getFreePtr(ic,&aop,FALSE);
9578 pic14_emitcode("mov","%s,%s",
9580 aopGet(AOP(result),0,FALSE,TRUE));
9581 rname = preg->name ;
9583 rname = aopGet(AOP(result),0,FALSE,FALSE);
9585 freeAsmop(result,NULL,ic,TRUE);
9586 aopOp (right,ic,FALSE);
9588 /* if bitfield then unpack the bits */
9589 if (IS_BITFIELD(retype))
9590 genPackBits (retype,result,right,rname,PPOINTER);
9592 /* we have can just get the values */
9593 int size = AOP_SIZE(right);
9597 l = aopGet(AOP(right),offset,FALSE,TRUE);
9600 pic14_emitcode("movx","@%s,a",rname);
9603 pic14_emitcode("inc","%s",rname);
9609 /* now some housekeeping stuff */
9611 /* we had to allocate for this iCode */
9612 freeAsmop(NULL,aop,ic,TRUE);
9614 /* we did not allocate which means left
9615 already in a pointer register, then
9616 if size > 0 && this could be used again
9617 we have to point it back to where it
9619 if (AOP_SIZE(right) > 1 &&
9620 !OP_SYMBOL(result)->remat &&
9621 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9623 int size = AOP_SIZE(right) - 1;
9625 pic14_emitcode("dec","%s",rname);
9630 freeAsmop(right,NULL,ic,TRUE);
9635 /*-----------------------------------------------------------------*/
9636 /* genFarPointerSet - set value from far space */
9637 /*-----------------------------------------------------------------*/
9638 static void genFarPointerSet (operand *right,
9639 operand *result, iCode *ic)
9642 sym_link *retype = getSpec(operandType(right));
9645 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9646 aopOp(result,ic,FALSE);
9648 /* if the operand is already in dptr
9649 then we do nothing else we move the value to dptr */
9650 if (AOP_TYPE(result) != AOP_STR) {
9651 /* if this is remateriazable */
9652 if (AOP_TYPE(result) == AOP_IMMD)
9653 pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9654 else { /* we need to get it byte by byte */
9655 pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9656 pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9657 if (options.model == MODEL_FLAT24)
9659 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9663 /* so dptr know contains the address */
9664 freeAsmop(result,NULL,ic,TRUE);
9665 aopOp(right,ic,FALSE);
9667 /* if bit then unpack */
9668 if (IS_BITFIELD(retype))
9669 genPackBits(retype,result,right,"dptr",FPOINTER);
9671 size = AOP_SIZE(right);
9675 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9677 pic14_emitcode("movx","@dptr,a");
9679 pic14_emitcode("inc","dptr");
9683 freeAsmop(right,NULL,ic,TRUE);
9687 /*-----------------------------------------------------------------*/
9688 /* genGenPointerSet - set value from generic pointer space */
9689 /*-----------------------------------------------------------------*/
9690 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9692 sym_link *retype = getSpec(operandType(result));
9695 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9696 aopOp(right,ic,FALSE);
9697 aopOp(result,ic,FALSE);
9700 DEBUGpic14_AopType(__LINE__,right,NULL,result);
9702 if (IS_BITFIELD(retype))
9704 genPackBits (retype, result, right, GPOINTER);
9709 /* emit call to __gptrput */
9710 char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9711 int size = AOP_SIZE(right);
9714 assert (size == getSize(OP_SYM_ETYPE(result)));
9715 assert (size > 0 && size <= 4);
9717 /* pass arguments */
9718 /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9724 mov2w_op (right, off);
9725 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9730 assert (AOP_SIZE(result) == 3);
9731 mov2w(AOP(result), 0);
9732 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9733 mov2w(AOP(result), 1);
9734 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9735 mov2w(AOP(result), 2);
9736 call_libraryfunc (func[size]);
9739 freeAsmop(right,NULL,ic,TRUE);
9740 freeAsmop(result,NULL,ic,TRUE);
9743 /*-----------------------------------------------------------------*/
9744 /* genPointerSet - stores the value into a pointer location */
9745 /*-----------------------------------------------------------------*/
9746 static void genPointerSet (iCode *ic)
9748 operand *right, *result ;
9749 sym_link *type, *etype;
9753 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9755 right = IC_RIGHT(ic);
9756 result = IC_RESULT(ic) ;
9758 /* depending on the type of pointer we need to
9759 move it to the correct pointer register */
9760 type = operandType(result);
9761 etype = getSpec(type);
9762 /* if left is of type of pointer then it is simple */
9763 if (IS_PTR(type) && !IS_FUNC(type->next)) {
9764 p_type = DCL_TYPE(type);
9767 /* we have to go by the storage class */
9768 p_type = PTR_TYPE(SPEC_OCLS(etype));
9770 /* if (SPEC_OCLS(etype)->codesp ) { */
9771 /* p_type = CPOINTER ; */
9774 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9775 /* p_type = FPOINTER ; */
9777 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9778 /* p_type = PPOINTER ; */
9780 /* if (SPEC_OCLS(etype) == idata ) */
9781 /* p_type = IPOINTER ; */
9783 /* p_type = POINTER ; */
9786 /* now that we have the pointer type we assign
9787 the pointer values */
9793 genNearPointerSet (right,result,ic);
9797 genPagedPointerSet (right,result,ic);
9801 genFarPointerSet (right,result,ic);
9805 genGenPointerSet (right,result,ic);
9809 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9810 "genPointerSet: illegal pointer type");
9814 /*-----------------------------------------------------------------*/
9815 /* genIfx - generate code for Ifx statement */
9816 /*-----------------------------------------------------------------*/
9817 static void genIfx (iCode *ic, iCode *popIc)
9819 operand *cond = IC_COND(ic);
9823 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9825 aopOp(cond,ic,FALSE);
9827 /* get the value into acc */
9828 if (AOP_TYPE(cond) != AOP_CRY)
9829 pic14_toBoolean(cond);
9833 /* if there was something to be popped then do it */
9839 /* This assumes that CARRY is set iff cond is true */
9842 assert (!IC_FALSE(ic));
9843 emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
9845 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9847 assert (IC_FALSE(ic));
9848 emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
9850 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9854 static int hasWarned = 0;
9857 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
9864 /* now Z is set iff !cond */
9867 assert (!IC_FALSE(ic));
9869 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9872 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9878 /* the result is now in the accumulator */
9879 freeAsmop(cond,NULL,ic,TRUE);
9882 /*-----------------------------------------------------------------*/
9883 /* genAddrOf - generates code for address of */
9884 /*-----------------------------------------------------------------*/
9885 static void genAddrOf (iCode *ic)
9887 operand *right, *result, *left;
9891 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9894 //aopOp(IC_RESULT(ic),ic,FALSE);
9896 aopOp((left=IC_LEFT(ic)),ic,FALSE);
9897 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9898 aopOp((result=IC_RESULT(ic)),ic,TRUE);
9900 DEBUGpic14_AopType(__LINE__,left,right,result);
9901 assert (IS_SYMOP (left));
9903 /* sanity check: generic pointers to code space are not yet supported,
9904 * pionters to codespace must not be assigned addresses of __data values. */
9906 fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9907 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)));
9908 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)));
9909 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)));
9910 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)));
9913 if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9914 fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9915 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9916 OP_SYMBOL(left)->name);
9917 } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9918 fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9919 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9920 OP_SYMBOL(left)->name);
9923 size = AOP_SIZE(IC_RESULT(ic));
9924 if (IS_GENPTR(OP_SYM_TYPE(result))) {
9926 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9931 /* fixing bug #863624, reported from (errolv) */
9932 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9933 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9936 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9937 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9942 if (IS_GENPTR(OP_SYM_TYPE(result)))
9944 /* provide correct tag */
9945 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9946 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9947 movwf (AOP(result), 2);
9950 freeAsmop(left,NULL,ic,FALSE);
9951 freeAsmop(result,NULL,ic,TRUE);
9956 /*-----------------------------------------------------------------*/
9957 /* genFarFarAssign - assignment when both are in far space */
9958 /*-----------------------------------------------------------------*/
9959 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9961 int size = AOP_SIZE(right);
9964 /* first push the right side on to the stack */
9966 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9968 pic14_emitcode ("push","acc");
9971 freeAsmop(right,NULL,ic,FALSE);
9972 /* now assign DPTR to result */
9973 aopOp(result,ic,FALSE);
9974 size = AOP_SIZE(result);
9976 pic14_emitcode ("pop","acc");
9977 aopPut(AOP(result),"a",--offset);
9979 freeAsmop(result,NULL,ic,FALSE);
9984 /*-----------------------------------------------------------------*/
9985 /* genAssign - generate code for assignment */
9986 /*-----------------------------------------------------------------*/
9987 static void genAssign (iCode *ic)
9989 operand *result, *right;
9990 int size, offset,know_W;
9991 unsigned long lit = 0L;
9993 result = IC_RESULT(ic);
9994 right = IC_RIGHT(ic) ;
9997 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9999 /* if they are the same */
10000 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10003 aopOp(right,ic,FALSE);
10004 aopOp(result,ic,TRUE);
10006 DEBUGpic14_AopType(__LINE__,NULL,right,result);
10008 /* if they are the same registers */
10009 if (pic14_sameRegs(AOP(right),AOP(result)))
10012 /* special case: assign from __code */
10013 if (!IS_ITEMP(right) /* --> iTemps never reside in __code */
10014 && IS_SYMOP (right) /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
10015 && !IS_FUNC(OP_SYM_TYPE(right)) /* --> we would want its address instead of the first instruction */
10016 && !IS_CODEPTR(OP_SYM_TYPE(right)) /* --> get symbols address instread */
10017 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
10019 emitpComment ("genAssign from CODESPACE");
10020 genConstPointerGet (right, result, ic);
10024 /* just for symmetry reasons... */
10025 if (!IS_ITEMP(result)
10026 && IS_SYMOP (result)
10027 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
10029 assert ( !"cannot write to CODESPACE" );
10032 /* if the result is a bit */
10033 if (AOP_TYPE(result) == AOP_CRY) {
10035 /* if the right size is a literal then
10036 we know what the value is */
10037 if (AOP_TYPE(right) == AOP_LIT) {
10039 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10040 popGet(AOP(result),0));
10042 if (((int) operandLitValue(right)))
10043 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10044 AOP(result)->aopu.aop_dir,
10045 AOP(result)->aopu.aop_dir);
10047 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10048 AOP(result)->aopu.aop_dir,
10049 AOP(result)->aopu.aop_dir);
10053 /* the right is also a bit variable */
10054 if (AOP_TYPE(right) == AOP_CRY) {
10055 emitpcode(POC_BCF, popGet(AOP(result),0));
10056 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10057 emitpcode(POC_BSF, popGet(AOP(result),0));
10059 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10060 AOP(result)->aopu.aop_dir,
10061 AOP(result)->aopu.aop_dir);
10062 pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
10063 AOP(right)->aopu.aop_dir,
10064 AOP(right)->aopu.aop_dir);
10065 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10066 AOP(result)->aopu.aop_dir,
10067 AOP(result)->aopu.aop_dir);
10071 /* we need to or */
10072 emitpcode(POC_BCF, popGet(AOP(result),0));
10073 pic14_toBoolean(right);
10075 emitpcode(POC_BSF, popGet(AOP(result),0));
10076 //aopPut(AOP(result),"a",0);
10080 /* bit variables done */
10082 size = AOP_SIZE(result);
10084 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
10085 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10086 if(aopIdx(AOP(result),0) == 4) {
10087 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10088 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10089 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10092 DEBUGpic14_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
10098 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10099 if(AOP_TYPE(right) == AOP_LIT) {
10100 lit = (unsigned long)pic14aopLiteral(AOP(right)->aopu.aop_lit, offset) & 0x0ff;
10102 if(know_W != (int)(lit&0xff))
10103 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10105 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10107 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10109 } else if (AOP_TYPE(right) == AOP_CRY) {
10110 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10112 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10113 emitpcode(POC_INCF, popGet(AOP(result),0));
10116 mov2w_op (right, offset);
10117 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10125 freeAsmop (right,NULL,ic,FALSE);
10126 freeAsmop (result,NULL,ic,TRUE);
10129 /*-----------------------------------------------------------------*/
10130 /* genJumpTab - genrates code for jump table */
10131 /*-----------------------------------------------------------------*/
10132 static void genJumpTab (iCode *ic)
10138 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10140 aopOp(IC_JTCOND(ic),ic,FALSE);
10141 /* get the condition into accumulator */
10142 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10144 /* multiply by three */
10145 pic14_emitcode("add","a,acc");
10146 pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10148 jtab = newiTempLabel(NULL);
10149 pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10150 pic14_emitcode("jmp","@a+dptr");
10151 pic14_emitcode("","%05d_DS_:",jtab->key+100);
10153 emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10154 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10155 emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10156 emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10158 emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10159 emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10160 emitpLabel(jtab->key);
10162 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10164 /* now generate the jump labels */
10165 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10166 jtab = setNextItem(IC_JTLABELS(ic))) {
10167 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10168 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10174 /*-----------------------------------------------------------------*/
10175 /* genMixedOperation - gen code for operators between mixed types */
10176 /*-----------------------------------------------------------------*/
10178 TSD - Written for the PIC port - but this unfortunately is buggy.
10179 This routine is good in that it is able to efficiently promote
10180 types to different (larger) sizes. Unfortunately, the temporary
10181 variables that are optimized out by this routine are sometimes
10182 used in other places. So until I know how to really parse the
10183 iCode tree, I'm going to not be using this routine :(.
10185 static int genMixedOperation (iCode *ic)
10189 operand *result = IC_RESULT(ic);
10190 sym_link *ctype = operandType(IC_LEFT(ic));
10191 operand *right = IC_RIGHT(ic);
10197 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10199 pic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10205 nextright = IC_RIGHT(nextic);
10206 nextleft = IC_LEFT(nextic);
10207 nextresult = IC_RESULT(nextic);
10209 aopOp(right,ic,FALSE);
10210 aopOp(result,ic,FALSE);
10211 aopOp(nextright, nextic, FALSE);
10212 aopOp(nextleft, nextic, FALSE);
10213 aopOp(nextresult, nextic, FALSE);
10215 if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10217 operand *t = right;
10221 pic14_emitcode(";remove right +","");
10223 } else if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10225 operand *t = right;
10229 pic14_emitcode(";remove left +","");
10233 big = AOP_SIZE(nextleft);
10234 small = AOP_SIZE(nextright);
10236 switch(nextic->op) {
10239 pic14_emitcode(";optimize a +","");
10240 /* if unsigned or not an integral type */
10241 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10242 pic14_emitcode(";add a bit to something","");
10245 pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10247 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10248 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10249 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10251 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10259 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10260 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10261 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10264 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10266 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10267 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10268 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10269 pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10270 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10273 pic14_emitcode("rlf","known_zero,w");
10280 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10281 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10282 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10284 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10294 freeAsmop(right,NULL,ic,TRUE);
10295 freeAsmop(result,NULL,ic,TRUE);
10296 freeAsmop(nextright,NULL,ic,TRUE);
10297 freeAsmop(nextleft,NULL,ic,TRUE);
10299 nextic->generated = 1;
10306 /*-----------------------------------------------------------------*/
10307 /* genCast - gen code for casting */
10308 /*-----------------------------------------------------------------*/
10309 static void genCast (iCode *ic)
10311 operand *result = IC_RESULT(ic);
10312 sym_link *restype = operandType(result);
10313 sym_link *rtype = operandType(IC_RIGHT(ic));
10314 operand *right = IC_RIGHT(ic);
10318 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10319 /* if they are equivalent then do nothing */
10320 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10323 aopOp(right,ic,FALSE) ;
10324 aopOp(result,ic,FALSE);
10326 DEBUGpic14_AopType(__LINE__,NULL,right,result);
10328 /* if the result is a bit */
10329 if (AOP_TYPE(result) == AOP_CRY) {
10330 assert(!"assigning to bit variables is not supported");
10333 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10335 size = AOP_SIZE(result);
10337 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10339 emitpcode(POC_CLRF, popGet(AOP(result),0));
10340 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10341 emitpcode(POC_INCF, popGet(AOP(result),0));
10344 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
10349 if (IS_PTR(restype))
10351 operand *result = IC_RESULT(ic);
10352 //operand *left = IC_LEFT(ic);
10353 operand *right = IC_RIGHT(ic);
10356 /* copy common part */
10357 int max, size = AOP_SIZE(result);
10358 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10359 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10361 /* warn if we discard generic opinter tag */
10362 if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10364 //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10370 mov2w_op (right, size);
10371 movwf (AOP(result), size);
10374 /* upcast into generic pointer type? */
10375 if (IS_GENPTR(restype)
10376 && (size < AOP_SIZE(result))
10377 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10379 //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10382 switch (DCL_TYPE(rtype))
10384 case POINTER: /* __data */
10385 case FPOINTER: /* __data */
10386 assert (AOP_SIZE(right) == 2);
10387 tag = GPTRTAG_DATA;
10390 case CPOINTER: /* __code */
10391 assert (AOP_SIZE(right) == 2);
10392 tag = GPTRTAG_CODE;
10395 case GPOINTER: /* unknown destination, __data or __code */
10396 /* assume __data space (address of immediate) */
10397 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10398 if (AOP(right)->code)
10399 tag = GPTRTAG_CODE;
10401 tag = GPTRTAG_DATA;
10405 assert (!"unhandled pointer type");
10408 /* convert other values into pointers to __data space */
10409 tag = GPTRTAG_DATA;
10412 assert (AOP_SIZE(result) == 3);
10414 emitpcode(POC_CLRF, popGet(AOP(result), 2));
10416 emitpcode(POC_MOVLW, popGetLit(tag));
10417 movwf(AOP(result), 2);
10420 addSign(result, max, 0);
10425 /* if they are the same size : or less */
10426 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10428 /* if they are in the same place */
10429 if (pic14_sameRegs(AOP(right),AOP(result)))
10432 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10433 if (IS_PTR_CONST(rtype))
10434 DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10435 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10436 DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10438 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10439 emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10440 emitpcode(POC_MOVWF, popGet(AOP(result),0));
10441 emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10442 emitpcode(POC_MOVWF, popGet(AOP(result),1));
10443 if(AOP_SIZE(result) <2)
10444 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10448 /* if they in different places then copy */
10449 size = AOP_SIZE(result);
10452 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10453 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10455 //aopPut(AOP(result),
10456 // aopGet(AOP(right),offset,FALSE,FALSE),
10465 /* so we now know that the size of destination is greater
10466 than the size of the source.
10467 Now, if the next iCode is an operator then we might be
10468 able to optimize the operation without performing a cast.
10470 if(0 && genMixedOperation(ic)) {
10471 /* XXX: cannot optimize: must copy regs! */
10475 /* we move to result for the size of source */
10476 size = AOP_SIZE(right);
10479 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10480 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10484 addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10487 freeAsmop(right,NULL,ic,TRUE);
10488 freeAsmop(result,NULL,ic,TRUE);
10492 /*-----------------------------------------------------------------*/
10493 /* genDjnz - generate decrement & jump if not zero instrucion */
10494 /*-----------------------------------------------------------------*/
10495 static int genDjnz (iCode *ic, iCode *ifx)
10497 symbol *lbl, *lbl1;
10499 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10504 /* if the if condition has a false label
10505 then we cannot save */
10509 /* if the minus is not of the form
10511 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10512 !IS_OP_LITERAL(IC_RIGHT(ic)))
10515 if (operandLitValue(IC_RIGHT(ic)) != 1)
10518 /* if the size of this greater than one then no
10520 if (getSize(operandType(IC_RESULT(ic))) > 1)
10523 /* otherwise we can save BIG */
10524 lbl = newiTempLabel(NULL);
10525 lbl1= newiTempLabel(NULL);
10527 aopOp(IC_RESULT(ic),ic,FALSE);
10529 if (IS_AOP_PREG(IC_RESULT(ic))) {
10530 pic14_emitcode("dec","%s",
10531 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10532 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10533 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10537 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10538 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10540 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10541 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10544 /* pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10545 /* pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10546 /* pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10547 /* pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10550 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10551 ifx->generated = 1;
10555 /*-----------------------------------------------------------------*/
10556 /* genReceive - generate code for a receive iCode */
10557 /*-----------------------------------------------------------------*/
10558 static void genReceive (iCode *ic)
10561 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10563 if (isOperandInFarSpace(IC_RESULT(ic)) &&
10564 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10565 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10567 int size = getSize(operandType(IC_RESULT(ic)));
10568 int offset = fReturnSizePic - size;
10570 pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10571 fReturn[fReturnSizePic - offset - 1] : "acc"));
10574 aopOp(IC_RESULT(ic),ic,FALSE);
10575 size = AOP_SIZE(IC_RESULT(ic));
10578 pic14_emitcode ("pop","acc");
10579 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10584 aopOp(IC_RESULT(ic),ic,FALSE);
10586 GpsuedoStkPtr = ic->parmBytes; // address used arg on stack
10587 assignResultValue(IC_RESULT(ic));
10590 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10593 /*-----------------------------------------------------------------*/
10594 /* genDummyRead - generate code for dummy read of volatiles */
10595 /*-----------------------------------------------------------------*/
10597 genDummyRead (iCode * ic)
10600 pic14_emitcode ("; genDummyRead","");
10601 pic14_emitcode ("; not implemented","");
10606 /*-----------------------------------------------------------------*/
10607 /* genpic14Code - generate code for pic14 based controllers */
10608 /*-----------------------------------------------------------------*/
10610 * At this point, ralloc.c has gone through the iCode and attempted
10611 * to optimize in a way suitable for a PIC. Now we've got to generate
10612 * PIC instructions that correspond to the iCode.
10614 * Once the instructions are generated, we'll pass through both the
10615 * peep hole optimizer and the pCode optimizer.
10616 *-----------------------------------------------------------------*/
10618 void genpic14Code (iCode *lic)
10625 lineHead = lineCurr = NULL;
10627 pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10630 /* if debug information required */
10631 if (options.debug && currFunc) {
10633 debugFile->writeFunction (currFunc, lic);
10638 for (ic = lic ; ic ; ic = ic->next ) {
10640 //DEBUGpic14_emitcode(";ic","");
10641 //fprintf (stderr, "in ic loop\n");
10642 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10643 //ic->lineno, printCLine(ic->filename, ic->lineno));
10645 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10647 //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10648 cline = printCLine (ic->filename, ic->lineno);
10649 if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10650 addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10651 //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10654 if (options.iCodeInAsm) {
10655 emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10657 /* if the result is marked as
10658 spilt and rematerializable or code for
10659 this has already been generated then
10661 if (resultRemat(ic) || ic->generated )
10664 /* depending on the operation */
10683 /* IPOP happens only when trying to restore a
10684 spilt live range, if there is an ifx statement
10685 following this pop then the if statement might
10686 be using some of the registers being popped which
10687 would destory the contents of the register so
10688 we need to check for this condition and handle it */
10690 ic->next->op == IFX &&
10691 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10692 genIfx (ic->next,ic);
10710 genEndFunction (ic);
10730 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10747 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
10751 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10758 /* note these two are xlated by algebraic equivalence
10759 during parsing SDCC.y */
10760 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10761 "got '>=' or '<=' shouldn't have come here");
10765 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10777 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10781 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10785 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10809 genRightShift (ic);
10812 case GET_VALUE_AT_ADDRESS:
10817 if (POINTER_SET(ic))
10844 addSet(&_G.sendSet,ic);
10847 case DUMMY_READ_VOLATILE:
10852 fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10859 /* now we are ready to call the
10860 peep hole optimizer */
10861 if (!options.nopeep) {
10862 peepHole (&lineHead);
10864 /* now do the actual printing */
10865 printLine (lineHead,codeOutFile);
10868 DFPRINTF((stderr,"printing pBlock\n\n"));
10869 printpBlock(stdout,pb);
10875 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10876 * (meaning: representing its own address) or not (referencing its contents).
10877 * This can only be decided based on the operand's type. */
10879 aop_isLitLike (asmop *aop)
10882 if (aop->type == AOP_LIT) return 1;
10883 if (aop->type == AOP_IMMD) return 1;
10884 if ((aop->type == AOP_PCODE) &&
10885 ((aop->aopu.pcop->type == PO_LITERAL)))
10887 /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10888 * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10895 op_isLitLike (operand *op)
10898 if (aop_isLitLike (AOP(op))) return 1;
10899 if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10900 if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;