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__);
5492 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
5493 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5498 /*-----------------------------------------------------------------*/
5500 /*-----------------------------------------------------------------*/
5501 static void jumpIfTrue (iCode *ic)
5504 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5508 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
5509 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5514 /*-----------------------------------------------------------------*/
5515 /* jmpTrueOrFalse - */
5516 /*-----------------------------------------------------------------*/
5517 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5520 // ugly but optimized by peephole
5521 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5523 symbol *nlbl = newiTempLabel(NULL);
5524 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5525 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5526 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5527 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5530 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5531 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5536 /*-----------------------------------------------------------------*/
5537 /* genAnd - code for and */
5538 /*-----------------------------------------------------------------*/
5539 static void genAnd (iCode *ic, iCode *ifx)
5541 operand *left, *right, *result;
5543 unsigned long lit = 0L;
5548 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5549 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5550 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5551 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5553 resolveIfx(&rIfx,ifx);
5555 /* if left is a literal & right is not then exchange them */
5556 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5557 AOP_NEEDSACC(left)) {
5558 operand *tmp = right ;
5563 /* if result = right then exchange them */
5564 if(pic14_sameRegs(AOP(result),AOP(right))){
5565 operand *tmp = right ;
5570 /* if right is bit then exchange them */
5571 if (AOP_TYPE(right) == AOP_CRY &&
5572 AOP_TYPE(left) != AOP_CRY){
5573 operand *tmp = right ;
5577 if(AOP_TYPE(right) == AOP_LIT)
5578 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5580 size = AOP_SIZE(result);
5582 DEBUGpic14_AopType(__LINE__,left,right,result);
5585 // result = bit & yy;
5586 if (AOP_TYPE(left) == AOP_CRY){
5587 // c = bit & literal;
5588 if(AOP_TYPE(right) == AOP_LIT){
5590 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5593 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5596 if(size && (AOP_TYPE(result) == AOP_CRY)){
5597 pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5600 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5604 pic14_emitcode("clr","c");
5607 if (AOP_TYPE(right) == AOP_CRY){
5609 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5610 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5613 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5615 pic14_emitcode("rrc","a");
5616 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5622 pic14_outBitC(result);
5624 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5625 genIfxJump(ifx, "c");
5629 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5630 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5631 if((AOP_TYPE(right) == AOP_LIT) &&
5632 (AOP_TYPE(result) == AOP_CRY) &&
5633 (AOP_TYPE(left) != AOP_CRY)){
5634 int posbit = isLiteralBit(lit);
5638 //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5641 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5646 while (posbit > 7) {
5650 emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5651 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5652 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5659 symbol *tlbl = newiTempLabel(NULL);
5660 int sizel = AOP_SIZE(left);
5662 pic14_emitcode("setb","c");
5664 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5665 mov2w( AOP(left), offset);
5667 if((posbit = isLiteralBit(bytelit)) != 0) {
5668 emitpcode(rIfx.condition ? POC_BTFSC : POC_BTFSS, // XXX: or the other way round?
5669 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit - 1, 0));
5670 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5673 emitpcode(POC_ANDLW, newpCodeOpLit(bytelit & 0x0ff));
5674 if (rIfx.condition) emitSKPZ;
5677 if(bytelit != 0x0FFL)
5679 pic14_emitcode("anl","a,%s",
5680 aopGet(AOP(right),offset,FALSE,TRUE));
5682 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5685 emitpcode(POC_GOTO, popGetLabel(rIfx.lbl->key));
5691 // bit = left & literal
5693 pic14_emitcode("clr","c");
5694 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5696 // if(left & literal)
5699 jmpTrueOrFalse(ifx, tlbl);
5703 pic14_outBitC(result);
5707 /* if left is same as result */
5708 if(pic14_sameRegs(AOP(result),AOP(left))){
5710 for(;size--; offset++,lit>>=8) {
5711 if(AOP_TYPE(right) == AOP_LIT){
5712 switch(lit & 0xff) {
5714 /* and'ing with 0 has clears the result */
5715 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5718 /* and'ing with 0xff is a nop when the result and left are the same */
5723 int p = my_powof2( (~lit) & 0xff );
5725 /* only one bit is set in the literal, so use a bcf instruction */
5726 emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5729 if(know_W != (int)(lit&0xff))
5730 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5732 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5737 if (AOP_TYPE(left) == AOP_ACC) {
5738 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5740 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5741 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5748 // left & result in different registers
5749 if(AOP_TYPE(result) == AOP_CRY){
5751 // if(size), result in bit
5752 // if(!size && ifx), conditional oper: if(left & right)
5753 symbol *tlbl = newiTempLabel(NULL);
5754 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5756 pic14_emitcode("setb","c");
5758 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5759 pic14_emitcode("anl","a,%s",
5760 aopGet(AOP(left),offset,FALSE,FALSE));
5761 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5766 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5767 pic14_outBitC(result);
5769 jmpTrueOrFalse(ifx, tlbl);
5771 for(;(size--);offset++) {
5773 // result = left & right
5774 if(AOP_TYPE(right) == AOP_LIT){
5775 int t = (lit >> (offset*8)) & 0x0FFL;
5778 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5781 if(AOP_TYPE(left) != AOP_ACC) {
5782 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5784 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5787 if(AOP_TYPE(left) == AOP_ACC) {
5788 emitpcode(POC_ANDLW, popGetLit(t));
5790 emitpcode(POC_MOVLW, popGetLit(t));
5791 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5793 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5798 if (AOP_TYPE(left) == AOP_ACC) {
5799 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5801 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5802 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5804 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5810 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5811 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5812 freeAsmop(result,NULL,ic,TRUE);
5815 /*-----------------------------------------------------------------*/
5816 /* genOr - code for or */
5817 /*-----------------------------------------------------------------*/
5818 static void genOr (iCode *ic, iCode *ifx)
5820 operand *left, *right, *result;
5822 unsigned long lit = 0L;
5825 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5827 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5828 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5829 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5831 DEBUGpic14_AopType(__LINE__,left,right,result);
5833 /* if left is a literal & right is not then exchange them */
5834 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5835 AOP_NEEDSACC(left)) {
5836 operand *tmp = right ;
5841 /* if result = right then exchange them */
5842 if(pic14_sameRegs(AOP(result),AOP(right))){
5843 operand *tmp = right ;
5848 /* if right is bit then exchange them */
5849 if (AOP_TYPE(right) == AOP_CRY &&
5850 AOP_TYPE(left) != AOP_CRY){
5851 operand *tmp = right ;
5856 DEBUGpic14_AopType(__LINE__,left,right,result);
5858 if(AOP_TYPE(right) == AOP_LIT)
5859 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5861 size = AOP_SIZE(result);
5865 if (AOP_TYPE(left) == AOP_CRY){
5866 if(AOP_TYPE(right) == AOP_LIT){
5867 // c = bit & literal;
5869 // lit != 0 => result = 1
5870 if(AOP_TYPE(result) == AOP_CRY){
5872 emitpcode(POC_BSF, popGet(AOP(result),0));
5873 //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5874 // AOP(result)->aopu.aop_dir,
5875 // AOP(result)->aopu.aop_dir);
5877 continueIfTrue(ifx);
5881 // lit == 0 => result = left
5882 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5884 pic14_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5887 if (AOP_TYPE(right) == AOP_CRY){
5888 if(pic14_sameRegs(AOP(result),AOP(left))){
5890 emitpcode(POC_BCF, popGet(AOP(result),0));
5891 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5892 emitpcode(POC_BSF, popGet(AOP(result),0));
5894 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5895 AOP(result)->aopu.aop_dir,
5896 AOP(result)->aopu.aop_dir);
5897 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5898 AOP(right)->aopu.aop_dir,
5899 AOP(right)->aopu.aop_dir);
5900 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5901 AOP(result)->aopu.aop_dir,
5902 AOP(result)->aopu.aop_dir);
5904 if( AOP_TYPE(result) == AOP_ACC) {
5905 emitpcode(POC_MOVLW, popGetLit(0));
5906 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5907 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5908 emitpcode(POC_MOVLW, popGetLit(1));
5912 emitpcode(POC_BCF, popGet(AOP(result),0));
5913 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5914 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5915 emitpcode(POC_BSF, popGet(AOP(result),0));
5917 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5918 AOP(result)->aopu.aop_dir,
5919 AOP(result)->aopu.aop_dir);
5920 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5921 AOP(right)->aopu.aop_dir,
5922 AOP(right)->aopu.aop_dir);
5923 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5924 AOP(left)->aopu.aop_dir,
5925 AOP(left)->aopu.aop_dir);
5926 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5927 AOP(result)->aopu.aop_dir,
5928 AOP(result)->aopu.aop_dir);
5933 symbol *tlbl = newiTempLabel(NULL);
5934 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5937 emitpcode(POC_BCF, popGet(AOP(result),0));
5938 if( AOP_TYPE(right) == AOP_ACC) {
5939 emitpcode(POC_IORLW, popGetLit(0));
5941 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5942 emitpcode(POC_BSF, popGet(AOP(result),0));
5947 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5948 pic14_emitcode(";XXX setb","c");
5949 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5950 AOP(left)->aopu.aop_dir,tlbl->key+100);
5951 pic14_toBoolean(right);
5952 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5953 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5954 jmpTrueOrFalse(ifx, tlbl);
5958 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5965 pic14_outBitC(result);
5967 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5968 genIfxJump(ifx, "c");
5972 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5973 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5974 if((AOP_TYPE(right) == AOP_LIT) &&
5975 (AOP_TYPE(result) == AOP_CRY) &&
5976 (AOP_TYPE(left) != AOP_CRY)){
5978 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5981 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5983 continueIfTrue(ifx);
5986 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5987 // lit = 0, result = boolean(left)
5989 pic14_emitcode(";XXX setb","c");
5990 pic14_toBoolean(right);
5992 symbol *tlbl = newiTempLabel(NULL);
5993 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5995 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5997 genIfxJump (ifx,"a");
6001 pic14_outBitC(result);
6005 /* if left is same as result */
6006 if(pic14_sameRegs(AOP(result),AOP(left))){
6008 for(;size--; offset++,lit>>=8) {
6009 if(AOP_TYPE(right) == AOP_LIT){
6010 if((lit & 0xff) == 0)
6011 /* or'ing with 0 has no effect */
6014 int p = my_powof2(lit & 0xff);
6016 /* only one bit is set in the literal, so use a bsf instruction */
6018 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6020 if(know_W != (int)(lit & 0xff))
6021 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
6022 know_W = lit & 0xff;
6023 emitpcode(POC_IORWF, popGet(AOP(left),offset));
6028 if (AOP_TYPE(left) == AOP_ACC) {
6029 emitpcode(POC_IORFW, popGet(AOP(right),offset));
6030 pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6032 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
6033 emitpcode(POC_IORWF, popGet(AOP(left),offset));
6035 pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6036 pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
6042 // left & result in different registers
6043 if(AOP_TYPE(result) == AOP_CRY){
6045 // if(size), result in bit
6046 // if(!size && ifx), conditional oper: if(left | right)
6047 symbol *tlbl = newiTempLabel(NULL);
6048 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6049 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6053 pic14_emitcode(";XXX setb","c");
6055 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6056 pic14_emitcode(";XXX orl","a,%s",
6057 aopGet(AOP(left),offset,FALSE,FALSE));
6058 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6063 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6064 pic14_outBitC(result);
6066 jmpTrueOrFalse(ifx, tlbl);
6067 } else for(;(size--);offset++){
6069 // result = left | right
6070 if(AOP_TYPE(right) == AOP_LIT){
6071 int t = (lit >> (offset*8)) & 0x0FFL;
6074 if (AOP_TYPE(left) != AOP_ACC) {
6075 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
6077 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6081 if (AOP_TYPE(left) == AOP_ACC) {
6082 emitpcode(POC_IORLW, popGetLit(t));
6084 emitpcode(POC_MOVLW, popGetLit(t));
6085 emitpcode(POC_IORFW, popGet(AOP(left),offset));
6087 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6092 // faster than result <- left, anl result,right
6093 // and better if result is SFR
6094 if (AOP_TYPE(left) == AOP_ACC) {
6095 emitpcode(POC_IORFW,popGet(AOP(right),offset));
6097 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6098 emitpcode(POC_IORFW,popGet(AOP(left),offset));
6100 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6105 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6106 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6107 freeAsmop(result,NULL,ic,TRUE);
6110 /*-----------------------------------------------------------------*/
6111 /* genXor - code for xclusive or */
6112 /*-----------------------------------------------------------------*/
6113 static void genXor (iCode *ic, iCode *ifx)
6115 operand *left, *right, *result;
6117 unsigned long lit = 0L;
6120 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6122 aopOp((left = IC_LEFT(ic)),ic,FALSE);
6123 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6124 aopOp((result=IC_RESULT(ic)),ic,TRUE);
6126 /* if left is a literal & right is not ||
6127 if left needs acc & right does not */
6128 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6129 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6130 operand *tmp = right ;
6135 /* if result = right then exchange them */
6136 if(pic14_sameRegs(AOP(result),AOP(right))){
6137 operand *tmp = right ;
6142 /* if right is bit then exchange them */
6143 if (AOP_TYPE(right) == AOP_CRY &&
6144 AOP_TYPE(left) != AOP_CRY){
6145 operand *tmp = right ;
6149 if(AOP_TYPE(right) == AOP_LIT)
6150 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6152 size = AOP_SIZE(result);
6156 if (AOP_TYPE(left) == AOP_CRY){
6157 if(AOP_TYPE(right) == AOP_LIT){
6158 // c = bit & literal;
6160 // lit>>1 != 0 => result = 1
6161 if(AOP_TYPE(result) == AOP_CRY){
6163 {emitpcode(POC_BSF, popGet(AOP(result),offset));
6164 pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6166 continueIfTrue(ifx);
6169 pic14_emitcode("setb","c");
6173 // lit == 0, result = left
6174 if(size && pic14_sameRegs(AOP(result),AOP(left)))
6176 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6178 // lit == 1, result = not(left)
6179 if(size && pic14_sameRegs(AOP(result),AOP(left))){
6180 emitpcode(POC_MOVLW, popGet(AOP(result),offset));
6181 emitpcode(POC_XORWF, popGet(AOP(result),offset));
6182 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6185 assert ( !"incomplete genXor" );
6186 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6187 pic14_emitcode("cpl","c");
6194 symbol *tlbl = newiTempLabel(NULL);
6195 if (AOP_TYPE(right) == AOP_CRY){
6197 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6200 int sizer = AOP_SIZE(right);
6202 // if val>>1 != 0, result = 1
6203 pic14_emitcode("setb","c");
6205 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6207 // test the msb of the lsb
6208 pic14_emitcode("anl","a,#0xfe");
6209 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6213 pic14_emitcode("rrc","a");
6215 pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6216 pic14_emitcode("cpl","c");
6217 pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6222 pic14_outBitC(result);
6224 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6225 genIfxJump(ifx, "c");
6229 if(pic14_sameRegs(AOP(result),AOP(left))){
6230 /* if left is same as result */
6231 for(;size--; offset++) {
6232 if(AOP_TYPE(right) == AOP_LIT){
6233 int t = (lit >> (offset*8)) & 0x0FFL;
6237 if (IS_AOP_PREG(left)) {
6238 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6239 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6240 aopPut(AOP(result),"a",offset);
6242 emitpcode(POC_MOVLW, popGetLit(t));
6243 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6244 pic14_emitcode("xrl","%s,%s",
6245 aopGet(AOP(left),offset,FALSE,TRUE),
6246 aopGet(AOP(right),offset,FALSE,FALSE));
6249 if (AOP_TYPE(left) == AOP_ACC)
6250 pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6252 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6253 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6255 if (IS_AOP_PREG(left)) {
6256 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6257 aopPut(AOP(result),"a",offset);
6259 pic14_emitcode("xrl","%s,a",
6260 aopGet(AOP(left),offset,FALSE,TRUE));
6266 // left & result in different registers
6267 if(AOP_TYPE(result) == AOP_CRY){
6269 // if(size), result in bit
6270 // if(!size && ifx), conditional oper: if(left ^ right)
6271 symbol *tlbl = newiTempLabel(NULL);
6272 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6274 pic14_emitcode("setb","c");
6276 if((AOP_TYPE(right) == AOP_LIT) &&
6277 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6278 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6280 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6281 pic14_emitcode("xrl","a,%s",
6282 aopGet(AOP(left),offset,FALSE,FALSE));
6284 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6289 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6290 pic14_outBitC(result);
6292 jmpTrueOrFalse(ifx, tlbl);
6293 } else for(;(size--);offset++){
6295 // result = left & right
6296 if(AOP_TYPE(right) == AOP_LIT){
6297 int t = (lit >> (offset*8)) & 0x0FFL;
6300 if (AOP_TYPE(left) != AOP_ACC) {
6301 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6303 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6304 pic14_emitcode("movf","%s,w",
6305 aopGet(AOP(left),offset,FALSE,FALSE));
6306 pic14_emitcode("movwf","%s",
6307 aopGet(AOP(result),offset,FALSE,FALSE));
6310 if (AOP_TYPE(left) == AOP_ACC) {
6311 emitpcode(POC_XORLW, popGetLit(t));
6313 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6315 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6318 if (AOP_TYPE(left) == AOP_ACC) {
6319 emitpcode(POC_XORLW, popGetLit(t));
6321 emitpcode(POC_MOVLW, popGetLit(t));
6322 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6324 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6325 pic14_emitcode("movlw","0x%x",t);
6326 pic14_emitcode("xorwf","%s,w",
6327 aopGet(AOP(left),offset,FALSE,FALSE));
6328 pic14_emitcode("movwf","%s",
6329 aopGet(AOP(result),offset,FALSE,FALSE));
6335 // faster than result <- left, anl result,right
6336 // and better if result is SFR
6337 if (AOP_TYPE(left) == AOP_ACC) {
6338 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6340 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6341 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6343 if ( AOP_TYPE(result) != AOP_ACC){
6344 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6350 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6351 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6352 freeAsmop(result,NULL,ic,TRUE);
6355 /*-----------------------------------------------------------------*/
6356 /* genInline - write the inline code out */
6357 /*-----------------------------------------------------------------*/
6358 static void genInline (iCode *ic)
6360 char *buffer, *bp, *bp1;
6363 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6365 _G.inLine += (!options.asmpeep);
6367 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6368 strcpy(buffer,IC_INLINE(ic));
6370 /* emit each line as a code */
6376 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6384 /* print label, use this special format with NULL directive
6385 * to denote that the argument should not be indented with tab */
6386 addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6393 if ((bp1 != bp) && *bp1)
6394 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6398 _G.inLine -= (!options.asmpeep);
6401 /*-----------------------------------------------------------------*/
6402 /* genRRC - rotate right with carry */
6403 /*-----------------------------------------------------------------*/
6404 static void genRRC (iCode *ic)
6406 operand *left , *result ;
6407 int size, offset = 0, same;
6410 /* rotate right with carry */
6412 result=IC_RESULT(ic);
6413 aopOp (left,ic,FALSE);
6414 aopOp (result,ic,FALSE);
6416 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6418 same = pic14_sameRegs(AOP(result),AOP(left));
6420 size = AOP_SIZE(result);
6422 /* get the lsb and put it into the carry */
6423 emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6430 emitpcode(POC_RRF, popGet(AOP(left),offset));
6432 emitpcode(POC_RRFW, popGet(AOP(left),offset));
6433 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6439 freeAsmop(left,NULL,ic,TRUE);
6440 freeAsmop(result,NULL,ic,TRUE);
6443 /*-----------------------------------------------------------------*/
6444 /* genRLC - generate code for rotate left with carry */
6445 /*-----------------------------------------------------------------*/
6446 static void genRLC (iCode *ic)
6448 operand *left , *result ;
6449 int size, offset = 0;
6453 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6454 /* rotate right with carry */
6456 result=IC_RESULT(ic);
6457 aopOp (left,ic,FALSE);
6458 aopOp (result,ic,FALSE);
6460 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6462 same = pic14_sameRegs(AOP(result),AOP(left));
6464 /* move it to the result */
6465 size = AOP_SIZE(result);
6467 /* get the msb and put it into the carry */
6468 emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6475 emitpcode(POC_RLF, popGet(AOP(left),offset));
6477 emitpcode(POC_RLFW, popGet(AOP(left),offset));
6478 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6485 freeAsmop(left,NULL,ic,TRUE);
6486 freeAsmop(result,NULL,ic,TRUE);
6489 /*-----------------------------------------------------------------*/
6490 /* genGetHbit - generates code get highest order bit */
6491 /*-----------------------------------------------------------------*/
6492 static void genGetHbit (iCode *ic)
6494 operand *left, *result;
6496 result=IC_RESULT(ic);
6497 aopOp (left,ic,FALSE);
6498 aopOp (result,ic,FALSE);
6501 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6502 /* get the highest order byte into a */
6503 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6504 if(AOP_TYPE(result) == AOP_CRY){
6505 pic14_emitcode("rlc","a");
6506 pic14_outBitC(result);
6509 pic14_emitcode("rl","a");
6510 pic14_emitcode("anl","a,#0x01");
6511 pic14_outAcc(result);
6515 freeAsmop(left,NULL,ic,TRUE);
6516 freeAsmop(result,NULL,ic,TRUE);
6519 /*-----------------------------------------------------------------*/
6520 /* AccLsh - shift left accumulator by known count */
6521 /* MARK: pic14 always rotates through CARRY! */
6522 /*-----------------------------------------------------------------*/
6523 static void AccLsh (pCodeOp *pcop,int shCount)
6526 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6527 shCount &= 0x0007; // shCount : 0..7
6534 emitpcode(POC_RLF,pcop);
6538 emitpcode(POC_RLF,pcop);
6539 emitpcode(POC_RLF,pcop);
6542 emitpcode(POC_RLF,pcop);
6543 emitpcode(POC_RLF,pcop);
6544 emitpcode(POC_RLF,pcop);
6547 emitpcode(POC_SWAPF,pcop);
6550 emitpcode(POC_SWAPF,pcop);
6551 emitpcode(POC_RLF,pcop);
6554 emitpcode(POC_SWAPF,pcop);
6555 emitpcode(POC_RLF,pcop);
6556 emitpcode(POC_RLF,pcop);
6559 emitpcode(POC_RRFW,pcop);
6560 emitpcode(POC_RRF,pcop);
6563 /* clear invalid bits */
6564 emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6565 emitpcode(POC_ANDWF, pcop);
6568 /*-----------------------------------------------------------------*/
6569 /* AccRsh - shift right accumulator by known count */
6570 /* MARK: pic14 always rotates through CARRY! */
6571 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6572 /* 1: mask out invalid bits (zero-extend) */
6573 /* 2: sign-extend result (pretty slow) */
6574 /*-----------------------------------------------------------------*/
6575 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6578 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6579 shCount &= 0x0007; // shCount : 0..7
6585 /* load sign if needed */
6586 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6587 else if (mask_mode == 1) emitCLRC;
6588 emitpcode(POC_RRF,pcop);
6592 /* load sign if needed */
6593 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6594 emitpcode(POC_RRF,pcop);
6595 /* load sign if needed */
6596 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6597 emitpcode(POC_RRF,pcop);
6598 if (mask_mode == 2) return;
6601 /* load sign if needed */
6602 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6603 emitpcode(POC_RRF,pcop);
6604 /* load sign if needed */
6605 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6606 emitpcode(POC_RRF,pcop);
6607 /* load sign if needed */
6608 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6609 emitpcode(POC_RRF,pcop);
6610 if (mask_mode == 2) return;
6613 emitpcode(POC_SWAPF,pcop);
6616 emitpcode(POC_SWAPF,pcop);
6617 emitpcode(POC_RRF,pcop);
6620 emitpcode(POC_SWAPF,pcop);
6621 emitpcode(POC_RRF,pcop);
6622 emitpcode(POC_RRF,pcop);
6628 emitpcode(POC_RLFW,pcop);
6629 emitpcode(POC_CLRF,pcop);
6631 emitpcode(POC_COMF,pcop);
6634 emitpcode(POC_RLFW,pcop);
6635 emitpcode(POC_RLF,pcop);
6642 /* leave invalid bits undefined */
6646 /* clear invalid bits -- zero-extend */
6647 emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6648 emitpcode(POC_ANDWF, pcop);
6650 if (mask_mode == 2) {
6652 emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6653 emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6654 emitpcode(POC_IORWF, pcop);
6659 /*-----------------------------------------------------------------*/
6660 /* AccSRsh - signed right shift accumulator by known count */
6661 /*-----------------------------------------------------------------*/
6662 static void AccSRsh (int shCount)
6665 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6668 pic14_emitcode("mov","c,acc.7");
6669 pic14_emitcode("rrc","a");
6670 } else if(shCount == 2){
6671 pic14_emitcode("mov","c,acc.7");
6672 pic14_emitcode("rrc","a");
6673 pic14_emitcode("mov","c,acc.7");
6674 pic14_emitcode("rrc","a");
6676 tlbl = newiTempLabel(NULL);
6677 /* rotate right accumulator */
6678 AccRol(8 - shCount);
6679 /* and kill the higher order bits */
6680 pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6681 pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6682 pic14_emitcode("orl","a,#0x%02x",
6683 (unsigned char)~SRMask[shCount]);
6684 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6689 /*-----------------------------------------------------------------*/
6690 /* shiftR1Left2Result - shift right one byte from left to result */
6691 /*-----------------------------------------------------------------*/
6692 static void shiftR1Left2ResultSigned (operand *left, int offl,
6693 operand *result, int offr,
6699 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6701 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6705 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6707 emitpcode(POC_RRF, popGet(AOP(result),offr));
6709 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6710 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6716 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6718 emitpcode(POC_RRF, popGet(AOP(result),offr));
6720 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6721 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6723 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6724 emitpcode(POC_RRF, popGet(AOP(result),offr));
6730 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6732 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6733 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6736 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6737 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6738 emitpcode(POC_ANDLW, popGetLit(0x1f));
6740 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6741 emitpcode(POC_IORLW, popGetLit(0xe0));
6743 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6747 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6748 emitpcode(POC_ANDLW, popGetLit(0x0f));
6749 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6750 emitpcode(POC_IORLW, popGetLit(0xf0));
6751 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6755 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6757 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6758 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6760 emitpcode(POC_RRFW, popGet(AOP(result),offr));
6761 emitpcode(POC_ANDLW, popGetLit(0x07));
6762 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6763 emitpcode(POC_IORLW, popGetLit(0xf8));
6764 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6769 emitpcode(POC_MOVLW, popGetLit(0x00));
6770 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6771 emitpcode(POC_MOVLW, popGetLit(0xfe));
6772 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6773 emitpcode(POC_IORLW, popGetLit(0x01));
6774 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6776 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6777 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6778 emitpcode(POC_DECF, popGet(AOP(result),offr));
6779 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6780 emitpcode(POC_BCF, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6786 emitpcode(POC_MOVLW, popGetLit(0x00));
6787 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6788 emitpcode(POC_MOVLW, popGetLit(0xff));
6789 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6791 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6792 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6793 emitpcode(POC_DECF, popGet(AOP(result),offr));
6801 /*-----------------------------------------------------------------*/
6802 /* shiftR1Left2Result - shift right one byte from left to result */
6803 /*-----------------------------------------------------------------*/
6804 static void shiftR1Left2Result (operand *left, int offl,
6805 operand *result, int offr,
6806 int shCount, int sign)
6811 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6813 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6815 /* Copy the msb into the carry if signed. */
6817 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6827 emitpcode(POC_RRF, popGet(AOP(result),offr));
6829 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6830 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6836 emitpcode(POC_RRF, popGet(AOP(result),offr));
6838 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6839 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6842 emitpcode(POC_RRF, popGet(AOP(result),offr));
6847 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6849 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6850 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6853 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6854 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6855 emitpcode(POC_ANDLW, popGetLit(0x1f));
6856 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6860 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6861 emitpcode(POC_ANDLW, popGetLit(0x0f));
6862 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6866 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6867 emitpcode(POC_ANDLW, popGetLit(0x0f));
6868 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6870 emitpcode(POC_RRF, popGet(AOP(result),offr));
6875 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6876 emitpcode(POC_ANDLW, popGetLit(0x80));
6877 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6878 emitpcode(POC_RLF, popGet(AOP(result),offr));
6879 emitpcode(POC_RLF, popGet(AOP(result),offr));
6884 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6885 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6886 emitpcode(POC_RLF, popGet(AOP(result),offr));
6895 /*-----------------------------------------------------------------*/
6896 /* shiftL1Left2Result - shift left one byte from left to result */
6897 /*-----------------------------------------------------------------*/
6898 static void shiftL1Left2Result (operand *left, int offl,
6899 operand *result, int offr, int shCount)
6905 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6907 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6908 DEBUGpic14_emitcode ("; ***","same = %d",same);
6909 // l = aopGet(AOP(left),offl,FALSE,FALSE);
6911 /* shift left accumulator */
6912 //AccLsh(shCount); // don't comment out just yet...
6913 // aopPut(AOP(result),"a",offr);
6917 /* Shift left 1 bit position */
6918 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6920 emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6922 emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6923 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6927 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6928 emitpcode(POC_ANDLW,popGetLit(0x7e));
6929 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6930 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6933 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6934 emitpcode(POC_ANDLW,popGetLit(0x3e));
6935 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6936 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6937 emitpcode(POC_RLF, popGet(AOP(result),offr));
6940 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6941 emitpcode(POC_ANDLW, popGetLit(0xf0));
6942 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6945 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6946 emitpcode(POC_ANDLW, popGetLit(0xf0));
6947 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6948 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6951 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6952 emitpcode(POC_ANDLW, popGetLit(0x30));
6953 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6954 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6955 emitpcode(POC_RLF, popGet(AOP(result),offr));
6958 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6959 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6960 emitpcode(POC_RRF, popGet(AOP(result),offr));
6964 DEBUGpic14_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6970 /*-----------------------------------------------------------------*/
6971 /* movLeft2Result - move byte from left to result */
6972 /*-----------------------------------------------------------------*/
6973 static void movLeft2Result (operand *left, int offl,
6974 operand *result, int offr)
6978 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6979 if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6980 l = aopGet(AOP(left),offl,FALSE,FALSE);
6982 if (*l == '@' && (IS_AOP_PREG(result))) {
6983 pic14_emitcode("mov","a,%s",l);
6984 aopPut(AOP(result),"a",offr);
6986 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6987 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6992 /*-----------------------------------------------------------------*/
6993 /* shiftLeft_Left2ResultLit - shift left by known count */
6994 /*-----------------------------------------------------------------*/
6996 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6998 int size, same, offr, i;
7000 size = AOP_SIZE(left);
7001 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7003 same = pic14_sameRegs (AOP(left), AOP(result));
7006 shCount = shCount & 0x07;
7012 case 0: /* takes 0 or 2N cycles (for offr==0) */
7013 if (!same || offr) {
7014 for (i=size-1; i >= 0; i--)
7015 movLeft2Result (left, i, result, offr + i);
7019 case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
7021 shiftLeft_Left2ResultLit (left, result, 8 * offr);
7022 shiftLeft_Left2ResultLit (result, result, shCount);
7023 return; /* prevent clearing result again */
7026 for (i=0; i < size; i++) {
7027 if (same && !offr) {
7028 emitpcode (POC_RLF, popGet (AOP(left), i));
7030 emitpcode (POC_RLFW, popGet (AOP(left), i));
7031 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7037 case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
7038 /* works in-place/with offr as well */
7039 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
7040 emitpcode (POC_ANDLW, popGetLit (0xF0));
7041 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
7043 for (i = size - 2; i >= 0; i--)
7045 emitpcode (POC_SWAPFW, popGet (AOP(left), i));
7046 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7047 emitpcode (POC_ANDLW, popGetLit (0x0F));
7048 emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
7049 emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
7053 case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
7054 /* works in-place/with offr as well */
7055 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
7056 for (i = size-2; i >= 0; i--) {
7057 emitpcode (POC_RRFW, popGet (AOP(left), i));
7058 emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
7060 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7061 emitpcode (POC_RRF, popGet (AOP(result), offr));
7065 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
7066 shiftLeft_Left2ResultLit (result, result, 1);
7067 return; /* prevent clearing result again */
7073 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7077 /*-----------------------------------------------------------------*/
7078 /* shiftRight_Left2ResultLit - shift right by known count */
7079 /*-----------------------------------------------------------------*/
7081 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
7083 int size, same, offr, i;
7085 size = AOP_SIZE(left);
7086 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7088 same = pic14_sameRegs (AOP(left), AOP(result));
7091 shCount = shCount & 0x07;
7099 case 0: /* takes 0 or 2N cycles (for offr==0) */
7100 if (!same || offr) {
7101 for (i=0; i < size; i++)
7102 movLeft2Result (left, i + offr, result, i);
7106 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7107 emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7109 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7110 shiftRight_Left2ResultLit (result, result, shCount, sign);
7111 return; /* prevent sign-extending result again */
7115 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7118 for (i = size-1; i >= 0; i--) {
7119 if (same && !offr) {
7120 emitpcode (POC_RRF, popGet (AOP(left), i));
7122 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7123 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7129 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7130 /* works in-place/with offr as well */
7131 emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7132 emitpcode (POC_ANDLW, popGetLit (0x0F));
7133 emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7135 for (i = 1; i < size; i++)
7137 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7138 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7139 emitpcode (POC_ANDLW, popGetLit (0xF0));
7140 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7141 emitpcode (POC_XORWF, popGet (AOP(result), i));
7146 emitpcode (POC_MOVLW, popGetLit (0xF0));
7147 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7148 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7152 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7153 /* works in-place/with offr as well */
7154 emitpcode (POC_RLFW, popGet (AOP(left), offr));
7155 for (i = 0; i < size-1; i++) {
7156 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7157 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7159 emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7161 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7164 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7169 shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7170 shiftRight_Left2ResultLit (result, result, 1, sign);
7171 return; /* prevent sign extending result again */
7176 addSign (result, size, sign);
7180 /*-----------------------------------------------------------------*/
7181 /* shiftL2Left2Result - shift left two bytes from left to result */
7182 /*-----------------------------------------------------------------*/
7183 static void shiftL2Left2Result (operand *left, int offl,
7184 operand *result, int offr, int shCount)
7188 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7190 if(pic14_sameRegs(AOP(result), AOP(left))) {
7198 emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7199 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7200 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7204 emitpcode(POC_RLF, popGet(AOP(result),offr));
7205 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7211 emitpcode(POC_MOVLW, popGetLit(0x0f));
7212 emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7213 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7214 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7215 emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7216 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7217 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7219 emitpcode(POC_RLF, popGet(AOP(result),offr));
7220 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7224 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7225 emitpcode(POC_RRF, popGet(AOP(result),offr));
7226 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7227 emitpcode(POC_RRF, popGet(AOP(result),offr));
7228 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7229 emitpcode(POC_ANDLW,popGetLit(0xc0));
7230 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7231 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7232 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7233 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7236 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7237 emitpcode(POC_RRFW, popGet(AOP(result),offr));
7238 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7239 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7240 emitpcode(POC_RRF, popGet(AOP(result),offr));
7250 /* note, use a mov/add for the shift since the mov has a
7251 chance of getting optimized out */
7252 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7253 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7254 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7255 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7256 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7260 emitpcode(POC_RLF, popGet(AOP(result),offr));
7261 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7267 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7268 emitpcode(POC_ANDLW, popGetLit(0xF0));
7269 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7270 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7271 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7272 emitpcode(POC_ANDLW, popGetLit(0xF0));
7273 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7274 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7278 emitpcode(POC_RLF, popGet(AOP(result),offr));
7279 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7283 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7284 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7285 emitpcode(POC_RRFW, popGet(AOP(result),offl));
7286 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7288 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7289 emitpcode(POC_RRF, popGet(AOP(result),offr));
7290 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7291 emitpcode(POC_ANDLW,popGetLit(0xc0));
7292 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7293 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7294 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7295 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7298 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7299 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7300 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7301 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7302 emitpcode(POC_RRF, popGet(AOP(result),offr));
7308 /*-----------------------------------------------------------------*/
7309 /* shiftR2Left2Result - shift right two bytes from left to result */
7310 /*-----------------------------------------------------------------*/
7311 static void shiftR2Left2Result (operand *left, int offl,
7312 operand *result, int offr,
7313 int shCount, int sign)
7318 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7319 same = pic14_sameRegs(AOP(result), AOP(left));
7321 if(same && ((offl + MSB16) == offr)){
7323 /* don't crash result[offr] */
7324 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7325 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7328 movLeft2Result(left,offl, result, offr);
7329 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7332 /* a:x >> shCount (x = lsb(result))*/
7335 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7337 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7346 emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7351 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7352 emitpcode(POC_RRF,popGet(AOP(result),offr));
7354 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7355 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7356 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7357 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7362 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7365 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7366 emitpcode(POC_RRF,popGet(AOP(result),offr));
7373 emitpcode(POC_MOVLW, popGetLit(0xf0));
7374 emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7375 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7377 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7378 emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7379 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7380 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7382 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7383 emitpcode(POC_ANDLW, popGetLit(0x0f));
7384 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7386 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7387 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7388 emitpcode(POC_ANDLW, popGetLit(0xf0));
7389 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7390 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7394 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7395 emitpcode(POC_RRF, popGet(AOP(result),offr));
7399 emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7400 emitpcode(POC_BTFSC,
7401 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7402 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7410 emitpcode(POC_RLF, popGet(AOP(result),offr));
7411 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7413 emitpcode(POC_RLF, popGet(AOP(result),offr));
7414 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7415 emitpcode(POC_RLFW, popGet(AOP(result),offr));
7416 emitpcode(POC_ANDLW,popGetLit(0x03));
7418 emitpcode(POC_BTFSC,
7419 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7420 emitpcode(POC_IORLW,popGetLit(0xfc));
7422 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7423 emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7424 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7425 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7427 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7428 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7429 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7430 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7431 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7432 emitpcode(POC_RLF, popGet(AOP(result),offr));
7433 emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7434 emitpcode(POC_ANDLW,popGetLit(0x03));
7436 emitpcode(POC_BTFSC,
7437 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7438 emitpcode(POC_IORLW,popGetLit(0xfc));
7440 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7441 //emitpcode(POC_RLF, popGet(AOP(result),offr));
7448 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7449 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7450 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7451 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7454 emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7456 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7460 /*-----------------------------------------------------------------*/
7461 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7462 /*-----------------------------------------------------------------*/
7463 static void shiftLLeftOrResult (operand *left, int offl,
7464 operand *result, int offr, int shCount)
7467 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7469 /* shift left accumulator */
7470 AccLsh(left,offl,shCount);
7471 /* or with result */
7472 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7473 assert ( !"broken (modifies left, fails for left==result))" );
7476 /*-----------------------------------------------------------------*/
7477 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7478 /*-----------------------------------------------------------------*/
7479 static void shiftRLeftOrResult (operand *left, int offl,
7480 operand *result, int offr, int shCount)
7483 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7485 /* shift right accumulator */
7486 AccRsh(left,offl,shCount);
7487 /* or with result */
7488 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7489 assert ( !"broken (modifies left, fails for left==result))" );
7492 /*-----------------------------------------------------------------*/
7493 /* genlshOne - left shift a one byte quantity by known count */
7494 /*-----------------------------------------------------------------*/
7495 static void genlshOne (operand *result, operand *left, int shCount)
7498 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7499 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7502 /*-----------------------------------------------------------------*/
7503 /* genlshTwo - left shift two bytes by known amount != 0 */
7504 /*-----------------------------------------------------------------*/
7505 static void genlshTwo (operand *result,operand *left, int shCount)
7510 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7511 size = pic14_getDataSize(result);
7513 /* if shCount >= 8 */
7519 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7521 movLeft2Result(left, LSB, result, MSB16);
7523 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7526 /* 1 <= shCount <= 7 */
7529 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7531 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7535 /*-----------------------------------------------------------------*/
7536 /* shiftLLong - shift left one long from left to result */
7537 /* offl = LSB or MSB16 */
7538 /*-----------------------------------------------------------------*/
7539 static void shiftLLong (operand *left, operand *result, int offr )
7542 int size = AOP_SIZE(result);
7545 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7546 if(size >= LSB+offr){
7547 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7549 pic14_emitcode("add","a,acc");
7550 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7551 size >= MSB16+offr && offr != LSB )
7552 pic14_emitcode("xch","a,%s",
7553 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7555 aopPut(AOP(result),"a",LSB+offr);
7558 if(size >= MSB16+offr){
7559 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7560 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7563 pic14_emitcode("rlc","a");
7564 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7565 size >= MSB24+offr && offr != LSB)
7566 pic14_emitcode("xch","a,%s",
7567 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7569 aopPut(AOP(result),"a",MSB16+offr);
7572 if(size >= MSB24+offr){
7573 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7574 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7577 pic14_emitcode("rlc","a");
7578 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7579 size >= MSB32+offr && offr != LSB )
7580 pic14_emitcode("xch","a,%s",
7581 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7583 aopPut(AOP(result),"a",MSB24+offr);
7586 if(size > MSB32+offr){
7587 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7588 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7591 pic14_emitcode("rlc","a");
7592 aopPut(AOP(result),"a",MSB32+offr);
7595 aopPut(AOP(result),zero,LSB);
7598 /*-----------------------------------------------------------------*/
7599 /* genlshFour - shift four byte by a known amount != 0 */
7600 /*-----------------------------------------------------------------*/
7601 static void genlshFour (operand *result, operand *left, int shCount)
7606 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7607 size = AOP_SIZE(result);
7609 /* if shifting more that 3 bytes */
7610 if (shCount >= 24 ) {
7613 /* lowest order of left goes to the highest
7614 order of the destination */
7615 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7617 movLeft2Result(left, LSB, result, MSB32);
7618 aopPut(AOP(result),zero,LSB);
7619 aopPut(AOP(result),zero,MSB16);
7620 aopPut(AOP(result),zero,MSB32);
7624 /* more than two bytes */
7625 else if ( shCount >= 16 ) {
7626 /* lower order two bytes goes to higher order two bytes */
7628 /* if some more remaining */
7630 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7632 movLeft2Result(left, MSB16, result, MSB32);
7633 movLeft2Result(left, LSB, result, MSB24);
7635 aopPut(AOP(result),zero,MSB16);
7636 aopPut(AOP(result),zero,LSB);
7640 /* if more than 1 byte */
7641 else if ( shCount >= 8 ) {
7642 /* lower order three bytes goes to higher order three bytes */
7646 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7648 movLeft2Result(left, LSB, result, MSB16);
7650 else{ /* size = 4 */
7652 movLeft2Result(left, MSB24, result, MSB32);
7653 movLeft2Result(left, MSB16, result, MSB24);
7654 movLeft2Result(left, LSB, result, MSB16);
7655 aopPut(AOP(result),zero,LSB);
7657 else if(shCount == 1)
7658 shiftLLong(left, result, MSB16);
7660 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7661 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7662 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7663 aopPut(AOP(result),zero,LSB);
7668 /* 1 <= shCount <= 7 */
7669 else if(shCount <= 2){
7670 shiftLLong(left, result, LSB);
7672 shiftLLong(result, result, LSB);
7674 /* 3 <= shCount <= 7, optimize */
7676 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7677 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7678 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7684 /*-----------------------------------------------------------------*/
7685 /* genLeftShiftLiteral - left shifting by known count */
7686 /*-----------------------------------------------------------------*/
7687 static void genLeftShiftLiteral (operand *left,
7692 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7696 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7697 freeAsmop(right,NULL,ic,TRUE);
7699 aopOp(left,ic,FALSE);
7700 aopOp(result,ic,FALSE);
7702 size = getSize(operandType(result));
7705 pic14_emitcode("; shift left ","result %d, left %d",size,
7709 /* I suppose that the left size >= result size */
7712 movLeft2Result(left, size, result, size);
7716 else if(shCount >= (size * 8))
7718 aopPut(AOP(result),zero,size);
7722 genlshOne (result,left,shCount);
7727 genlshTwo (result,left,shCount);
7731 genlshFour (result,left,shCount);
7735 freeAsmop(left,NULL,ic,TRUE);
7736 freeAsmop(result,NULL,ic,TRUE);
7740 /*-----------------------------------------------------------------*
7741 * genMultiAsm - repeat assembly instruction for size of register.
7742 * if endian == 1, then the high byte (i.e base address + size of
7743 * register) is used first else the low byte is used first;
7744 *-----------------------------------------------------------------*/
7745 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7751 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7764 emitpcode(poc, popGet(AOP(reg),offset));
7771 /*-----------------------------------------------------------------*/
7772 /* genLeftShift - generates code for left shifting */
7773 /*-----------------------------------------------------------------*/
7774 static void genLeftShift (iCode *ic)
7776 operand *left,*right, *result;
7778 unsigned long lit = 0L;
7780 symbol *tlbl , *tlbl1;
7784 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7786 right = IC_RIGHT(ic);
7788 result = IC_RESULT(ic);
7790 aopOp(right,ic,FALSE);
7791 aopOp(left,ic,FALSE);
7792 aopOp(result,ic,FALSE);
7795 /* if the shift count is known then do it
7796 as efficiently as possible */
7797 if (AOP_TYPE(right) == AOP_LIT) {
7798 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7802 /* shift count is unknown then we have to form
7803 a loop get the loop count in B : Note: we take
7804 only the lower order byte since shifting
7805 more that 32 bits make no sense anyway, ( the
7806 largest size of an object can be only 32 bits ) */
7808 /* this code fails for RIGHT == RESULT */
7809 assert (!pic14_sameRegs (AOP(right), AOP(result)));
7811 /* now move the left to the result if they are not the
7813 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
7814 AOP_SIZE(result) > 1) {
7816 size = AOP_SIZE(result);
7819 l = aopGet(AOP(left),offset,FALSE,TRUE);
7820 if (*l == '@' && (IS_AOP_PREG(result))) {
7822 pic14_emitcode("mov","a,%s",l);
7823 aopPut(AOP(result),"a",offset);
7825 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
7826 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7827 //aopPut(AOP(result),l,offset);
7833 if(AOP_TYPE(left) == AOP_LIT)
7834 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7836 size = AOP_SIZE(result);
7838 /* if it is only one byte then */
7840 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7841 emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7842 emitpcode(POC_ANDLW, popGetLit(0xf0));
7843 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7844 emitpcode(POC_MOVFW, popGet(AOP(left),0));
7845 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7846 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7847 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7848 emitpcode(POC_RLFW, popGet(AOP(result),0));
7849 emitpcode(POC_ANDLW, popGetLit(0xfe));
7850 emitpcode(POC_ADDFW, popGet(AOP(result),0));
7851 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7852 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7855 tlbl = newiTempLabel(NULL);
7856 if (!pic14_sameRegs(AOP(left),AOP(result))) {
7857 mov2w (AOP(left), 0);
7858 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7861 emitpcode(POC_COMFW, popGet(AOP(right),0));
7862 emitpcode(POC_RRF, popGet(AOP(result),0));
7863 emitpLabel(tlbl->key);
7864 emitpcode(POC_RLF, popGet(AOP(result),0));
7865 emitpcode(POC_ADDLW, popGetLit(1));
7867 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7872 if (pic14_sameRegs(AOP(left),AOP(result))) {
7874 tlbl = newiTempLabel(NULL);
7875 emitpcode(POC_COMFW, popGet(AOP(right),0));
7876 genMultiAsm(POC_RRF, result, size,1);
7877 emitpLabel(tlbl->key);
7878 genMultiAsm(POC_RLF, result, size,0);
7879 emitpcode(POC_ADDLW, popGetLit(1));
7881 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7885 //tlbl = newiTempLabel(NULL);
7887 //tlbl1 = newiTempLabel(NULL);
7889 //reAdjustPreg(AOP(result));
7891 //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7892 //pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7893 //l = aopGet(AOP(result),offset,FALSE,FALSE);
7895 //pic14_emitcode("add","a,acc");
7896 //aopPut(AOP(result),"a",offset++);
7898 // l = aopGet(AOP(result),offset,FALSE,FALSE);
7900 // pic14_emitcode("rlc","a");
7901 // aopPut(AOP(result),"a",offset++);
7903 //reAdjustPreg(AOP(result));
7905 //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7906 //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7909 tlbl = newiTempLabel(NULL);
7910 tlbl1= newiTempLabel(NULL);
7912 size = AOP_SIZE(result);
7915 pctemp = popGetTempReg(); /* grab a temporary working register. */
7917 emitpcode(POC_MOVFW, popGet(AOP(right),0));
7919 /* offset should be 0, 1 or 3 */
7920 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7922 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
7924 emitpcode(POC_MOVWF, pctemp);
7927 emitpLabel(tlbl->key);
7930 emitpcode(POC_RLF, popGet(AOP(result),0));
7932 emitpcode(POC_RLF, popGet(AOP(result),offset++));
7934 emitpcode(POC_DECFSZ, pctemp);
7935 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7936 emitpLabel(tlbl1->key);
7938 popReleaseTempReg(pctemp);
7942 freeAsmop (right,NULL,ic,TRUE);
7943 freeAsmop(left,NULL,ic,TRUE);
7944 freeAsmop(result,NULL,ic,TRUE);
7949 /*-----------------------------------------------------------------*/
7950 /* genrshOne - right shift a one byte quantity by known count */
7951 /*-----------------------------------------------------------------*/
7952 static void genrshOne (operand *result, operand *left,
7953 int shCount, int sign)
7956 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7957 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7960 /*-----------------------------------------------------------------*/
7961 /* genrshTwo - right shift two bytes by known amount != 0 */
7962 /*-----------------------------------------------------------------*/
7963 static void genrshTwo (operand *result,operand *left,
7964 int shCount, int sign)
7967 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7968 /* if shCount >= 8 */
7972 shiftR1Left2Result(left, MSB16, result, LSB,
7975 movLeft2Result(left, MSB16, result, LSB);
7977 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7980 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7981 emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7985 /* 1 <= shCount <= 7 */
7987 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
7990 /*-----------------------------------------------------------------*/
7991 /* shiftRLong - shift right one long from left to result */
7992 /* offl = LSB or MSB16 */
7993 /*-----------------------------------------------------------------*/
7994 static void shiftRLong (operand *left, int offl,
7995 operand *result, int sign)
8000 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8002 size = AOP_SIZE(left);
8003 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
8006 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
8010 assert (offl >= 0 && offl < size);
8012 same = pic14_sameRegs (AOP(left), AOP(result));
8014 /* perform the shift */
8017 if (same && !offl) {
8018 emitpcode (POC_RRF, popGet (AOP(result), size));
8020 emitpcode (POC_RRFW, popGet (AOP(left), size));
8021 emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
8025 addSign (result, AOP_SIZE(left) - offl, sign);
8028 /*-----------------------------------------------------------------*/
8029 /* genrshFour - shift four byte by a known amount != 0 */
8030 /*-----------------------------------------------------------------*/
8031 static void genrshFour (operand *result, operand *left,
8032 int shCount, int sign)
8035 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8036 /* if shifting more that 3 bytes */
8037 if(shCount >= 24 ) {
8040 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8042 movLeft2Result(left, MSB32, result, LSB);
8044 addSign(result, MSB16, sign);
8046 else if(shCount >= 16){
8049 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8051 movLeft2Result(left, MSB24, result, LSB);
8052 movLeft2Result(left, MSB32, result, MSB16);
8054 addSign(result, MSB24, sign);
8056 else if(shCount >= 8){
8059 shiftRLong(left, MSB16, result, sign);
8060 else if(shCount == 0){
8061 movLeft2Result(left, MSB16, result, LSB);
8062 movLeft2Result(left, MSB24, result, MSB16);
8063 movLeft2Result(left, MSB32, result, MSB24);
8064 addSign(result, MSB32, sign);
8067 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8068 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8069 /* the last shift is signed */
8070 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8071 addSign(result, MSB32, sign);
8074 else{ /* 1 <= shCount <= 7 */
8076 shiftRLong(left, LSB, result, sign);
8078 shiftRLong(result, LSB, result, sign);
8081 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8082 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8083 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8088 /*-----------------------------------------------------------------*/
8089 /* genRightShiftLiteral - right shifting by known count */
8090 /*-----------------------------------------------------------------*/
8091 static void genRightShiftLiteral (operand *left,
8097 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8101 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8102 freeAsmop(right,NULL,ic,TRUE);
8104 aopOp(left,ic,FALSE);
8105 aopOp(result,ic,FALSE);
8108 pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8112 lsize = pic14_getDataSize(left);
8113 res_size = pic14_getDataSize(result);
8114 /* test the LEFT size !!! */
8116 /* I suppose that the left size >= result size */
8119 movLeft2Result(left, res_size, result, res_size);
8122 else if(shCount >= (lsize * 8)){
8125 emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8127 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8128 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8133 emitpcode(POC_MOVLW, popGetLit(0));
8134 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8135 emitpcode(POC_MOVLW, popGetLit(0xff));
8137 emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8142 emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8149 genrshOne (result,left,shCount,sign);
8153 genrshTwo (result,left,shCount,sign);
8157 genrshFour (result,left,shCount,sign);
8165 freeAsmop(left,NULL,ic,TRUE);
8166 freeAsmop(result,NULL,ic,TRUE);
8171 /*-----------------------------------------------------------------*/
8172 /* genSignedRightShift - right shift of signed number */
8173 /*-----------------------------------------------------------------*/
8174 static void genSignedRightShift (iCode *ic)
8176 operand *right, *left, *result;
8179 symbol *tlbl, *tlbl1 ;
8182 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8184 /* we do it the hard way put the shift count in b
8185 and loop thru preserving the sign */
8187 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8189 right = IC_RIGHT(ic);
8191 result = IC_RESULT(ic);
8193 aopOp(right,ic,FALSE);
8194 aopOp(left,ic,FALSE);
8195 aopOp(result,ic,FALSE);
8198 if ( AOP_TYPE(right) == AOP_LIT) {
8199 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8200 //genRightShiftLiteral (left,right,result,ic,1);
8203 /* shift count is unknown then we have to form
8204 a loop get the loop count in B : Note: we take
8205 only the lower order byte since shifting
8206 more that 32 bits make no sense anyway, ( the
8207 largest size of an object can be only 32 bits ) */
8209 //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8210 //pic14_emitcode("inc","b");
8211 //freeAsmop (right,NULL,ic,TRUE);
8212 //aopOp(left,ic,FALSE);
8213 //aopOp(result,ic,FALSE);
8215 /* now move the left to the result if they are not the
8217 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
8218 AOP_SIZE(result) > 1) {
8220 size = AOP_SIZE(result);
8224 l = aopGet(AOP(left),offset,FALSE,TRUE);
8225 if (*l == '@' && IS_AOP_PREG(result)) {
8226 pic14_emitcode("mov","a,%s",l);
8227 aopPut(AOP(result),"a",offset);
8229 aopPut(AOP(result),l,offset);
8231 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8232 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8238 /* mov the highest order bit to OVR */
8239 tlbl = newiTempLabel(NULL);
8240 tlbl1= newiTempLabel(NULL);
8242 size = AOP_SIZE(result);
8245 pctemp = popGetTempReg(); /* grab a temporary working register. */
8247 emitpcode(POC_MOVFW, popGet(AOP(right),0));
8249 /* offset should be 0, 1 or 3 */
8250 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8252 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8254 emitpcode(POC_MOVWF, pctemp);
8257 emitpLabel(tlbl->key);
8259 emitpcode(POC_RLFW, popGet(AOP(result),offset));
8260 emitpcode(POC_RRF, popGet(AOP(result),offset));
8263 emitpcode(POC_RRF, popGet(AOP(result),--offset));
8266 emitpcode(POC_DECFSZ, pctemp);
8267 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8268 emitpLabel(tlbl1->key);
8270 popReleaseTempReg(pctemp);
8272 size = AOP_SIZE(result);
8274 pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8275 pic14_emitcode("rlc","a");
8276 pic14_emitcode("mov","ov,c");
8277 /* if it is only one byte then */
8279 l = aopGet(AOP(left),0,FALSE,FALSE);
8281 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8282 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8283 pic14_emitcode("mov","c,ov");
8284 pic14_emitcode("rrc","a");
8285 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8286 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8287 aopPut(AOP(result),"a",0);
8291 reAdjustPreg(AOP(result));
8292 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8293 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8294 pic14_emitcode("mov","c,ov");
8296 l = aopGet(AOP(result),offset,FALSE,FALSE);
8298 pic14_emitcode("rrc","a");
8299 aopPut(AOP(result),"a",offset--);
8301 reAdjustPreg(AOP(result));
8302 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8303 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8308 freeAsmop(left,NULL,ic,TRUE);
8309 freeAsmop(result,NULL,ic,TRUE);
8310 freeAsmop(right,NULL,ic,TRUE);
8314 /*-----------------------------------------------------------------*/
8315 /* loadSignToC - load the operand's sign bit into CARRY */
8316 /*-----------------------------------------------------------------*/
8318 static void loadSignToC (operand *op)
8321 assert (op && AOP(op) && AOP_SIZE(op));
8324 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8328 /*-----------------------------------------------------------------*/
8329 /* genRightShift - generate code for right shifting */
8330 /*-----------------------------------------------------------------*/
8331 static void genGenericShift (iCode *ic, int shiftRight)
8333 operand *right, *left, *result;
8336 symbol *tlbl, *tlbl1, *inverselbl;
8339 /* if signed then we do it the hard way preserve the
8340 sign bit moving it inwards */
8341 retype = getSpec(operandType(IC_RESULT(ic)));
8342 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8344 /* signed & unsigned types are treated the same : i.e. the
8345 signed is NOT propagated inwards : quoting from the
8346 ANSI - standard : "for E1 >> E2, is equivalent to division
8347 by 2**E2 if unsigned or if it has a non-negative value,
8348 otherwise the result is implementation defined ", MY definition
8349 is that the sign does not get propagated */
8351 right = IC_RIGHT(ic);
8353 result = IC_RESULT(ic);
8355 aopOp(right,ic,FALSE);
8356 aopOp(left,ic,FALSE);
8357 aopOp(result,ic,FALSE);
8359 /* if the shift count is known then do it
8360 as efficiently as possible */
8361 if (AOP_TYPE(right) == AOP_LIT) {
8362 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8366 shiftRight = !shiftRight;
8370 shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8372 shiftLeft_Left2ResultLit (left, result, lit);
8373 //genRightShiftLiteral (left,right,result,ic, 0);
8377 /* shift count is unknown then we have to form
8378 a loop get the loop count in B : Note: we take
8379 only the lower order byte since shifting
8380 more that 32 bits make no sense anyway, ( the
8381 largest size of an object can be only 32 bits ) */
8383 /* we must not overwrite the shift counter */
8384 assert (!pic14_sameRegs(AOP(right),AOP(result)));
8386 /* now move the left to the result if they are not the
8388 if (!pic14_sameRegs(AOP(left),AOP(result)))
8390 size = min(AOP_SIZE(result), AOP_SIZE(left));
8392 mov2w(AOP(left), size);
8393 movwf(AOP(result), size);
8395 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8398 tlbl = newiTempLabel(NULL);
8399 tlbl1= newiTempLabel(NULL);
8401 size = AOP_SIZE(result);
8403 mov2w(AOP(right),0);
8404 if (!SPEC_USIGN(operandType(right)))
8406 inverselbl = newiTempLabel(NULL);
8407 /* signed shift count -- invert shift direction for c<0 */
8408 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8409 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8411 emitpcode(POC_SUBLW, popGetLit(0)); /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8412 /* check for `a = b >> c' with `-c == 0' */
8414 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8415 emitpLabel(tlbl->key);
8416 /* propagate the sign bit inwards for SIGNED result */
8417 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8418 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8419 emitpcode(POC_ADDLW, popGetLit(1)); /* clears CARRY (unless W==0 afterwards) */
8421 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8423 if (!SPEC_USIGN(operandType(right)))
8425 symbol *inv_loop = newiTempLabel(NULL);
8427 shiftRight = !shiftRight; /* invert shift direction */
8429 /* we came here from the code above -- we are done */
8430 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8432 /* emit code for shifting N<0 steps, count is already in W */
8433 emitpLabel(inverselbl->key);
8434 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8435 emitpLabel(inv_loop->key);
8436 /* propagate the sign bit inwards for SIGNED result */
8437 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8438 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8439 emitpcode(POC_ADDLW, popGetLit(1));
8441 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8444 emitpLabel(tlbl1->key);
8446 freeAsmop(left,NULL,ic,TRUE);
8447 freeAsmop (right,NULL,ic,TRUE);
8448 freeAsmop(result,NULL,ic,TRUE);
8451 static void genRightShift (iCode *ic)
8453 genGenericShift(ic, 1);
8456 static void genLeftShift (iCode *ic)
8458 genGenericShift(ic, 0);
8461 /*-----------------------------------------------------------------*/
8462 /* SetIrp - Set IRP bit */
8463 /*-----------------------------------------------------------------*/
8464 void SetIrp(operand *result) {
8466 if (AOP_TYPE(result) == AOP_LIT) {
8467 unsigned lit = (unsigned)operandLitValue(result);
8473 if (PCOP(AOP(result))->type == PO_LITERAL) {
8474 int addrs = PCOL(AOP(result))->lit;
8480 emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8481 if(AOP_SIZE(result) > 1) {
8482 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8490 setup_fsr (operand *ptr)
8493 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8495 /* also setup-up IRP */
8499 /*-----------------------------------------------------------------*/
8500 /* emitPtrByteGet - emits code to get a byte into WREG from an */
8501 /* arbitrary pointer (__code, __data, generic) */
8502 /*-----------------------------------------------------------------*/
8504 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8511 if (!alreadyAddressed) setup_fsr (src);
8512 emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8516 assert( AOP_SIZE(src) == 2 );
8518 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8520 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8521 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
8522 call_libraryfunc ("__gptrget1");
8526 assert( AOP_SIZE(src) == 3 );
8528 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8530 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8532 call_libraryfunc ("__gptrget1");
8536 assert( !"unhandled pointer type" );
8541 /*-----------------------------------------------------------------*/
8542 /* emitPtrByteSet - emits code to set a byte from src through a */
8543 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR). */
8544 /*-----------------------------------------------------------------*/
8546 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8553 if (!alreadyAddressed) setup_fsr (dst);
8554 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8558 assert( !"trying to assign to __code pointer" );
8562 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8564 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8566 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8568 call_libraryfunc ("__gptrput1");
8572 assert( !"unhandled pointer type" );
8577 /*-----------------------------------------------------------------*/
8578 /* genUnpackBits - generates code for unpacking bits */
8579 /*-----------------------------------------------------------------*/
8580 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8582 int rsize; /* result size */
8583 sym_link *etype; /* bitfield type information */
8584 int blen; /* bitfield length */
8585 int bstr; /* bitfield starting bit within byte */
8588 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8589 etype = getSpec(operandType(result));
8590 rsize = getSize (operandType (result));
8591 blen = SPEC_BLEN (etype);
8592 bstr = SPEC_BSTR (etype);
8594 /* single bit field case */
8596 if (ifx) { /* that is for an if statement */
8599 resolveIfx(&rIfx,ifx);
8600 if (ptype == -1) /* direct */
8601 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8603 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8604 emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8605 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8609 assert (!pic14_sameRegs (AOP(result), AOP(left)));
8610 for (i=0; i < AOP_SIZE(result); i++)
8611 emitpcode (POC_CLRF, popGet (AOP(result), i));
8616 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8617 /* adjust result below */
8624 emitPtrByteGet (left, ptype, FALSE);
8625 emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8627 /* adjust result below */
8631 assert( !"unhandled pointer type" );
8634 /* move sign-/zero extended bit to result */
8635 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8636 emitpcode (POC_INCF, popGet (AOP(result), 0));
8638 emitpcode (POC_DECF, popGet (AOP(result), 0));
8640 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8644 else if (blen <= 8 && ((blen + bstr) <= 8))
8649 for (i=0; i < AOP_SIZE(result); i++)
8650 emitpcode (POC_CLRF, popGet (AOP(result), i));
8655 mov2w(AOP(left), 0);
8662 emitPtrByteGet (left, ptype, FALSE);
8666 assert( !"unhandled pointer type" );
8670 emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8671 movwf(AOP(result), 0);
8672 AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8674 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8676 /* signed bitfield */
8677 assert (bstr + blen > 0);
8678 emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8679 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8680 emitpcode(POC_IORWF, popGet(AOP(result),0));
8682 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8686 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8690 /*-----------------------------------------------------------------*/
8691 /* genDataPointerGet - generates code when ptr offset is known */
8692 /*-----------------------------------------------------------------*/
8693 static void genDataPointerGet (operand *left,
8697 int size , offset = 0;
8700 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8703 /* optimization - most of the time, left and result are the same
8704 * address, but different types. for the pic code, we could omit
8707 aopOp(result,ic,TRUE);
8709 if (pic14_sameRegs (AOP(left), AOP(result)))
8712 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8714 //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8716 size = AOP_SIZE(result);
8717 if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8721 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8722 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8726 freeAsmop(left,NULL,ic,TRUE);
8727 freeAsmop(result,NULL,ic,TRUE);
8731 /*-----------------------------------------------------------------*/
8732 /* genNearPointerGet - pic14_emitcode for near pointer fetch */
8733 /*-----------------------------------------------------------------*/
8734 static void genNearPointerGet (operand *left,
8739 sym_link *ltype = operandType(left);
8740 sym_link *rtype = operandType(result);
8741 sym_link *retype= getSpec(rtype); /* bitfield type information */
8745 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8748 aopOp(left,ic,FALSE);
8750 /* if left is rematerialisable and
8751 result is not bit variable type and
8752 the left is pointer to data space i.e
8753 lower 128 bytes of space */
8754 if (AOP_TYPE(left) == AOP_PCODE && //AOP_TYPE(left) == AOP_IMMD &&
8755 !IS_BITVAR(retype) &&
8756 PIC_IS_DATA_PTR(ltype)) {
8757 genDataPointerGet (left,result,ic);
8761 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8762 aopOp (result,ic,FALSE);
8764 /* Check if can access directly instead of via a pointer */
8765 if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8766 && AOP_SIZE(result) == 1)
8771 if (IS_BITFIELD(getSpec(operandType(result))))
8773 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8777 /* If the pointer value is not in a the FSR then need to put it in */
8778 /* Must set/reset IRP bit for use with FSR. */
8783 /* if bitfield then unpack the bits */
8785 /* we have can just get the values */
8786 int size = AOP_SIZE(result);
8789 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8793 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8795 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8796 if (AOP_TYPE(result) == AOP_LIT) {
8797 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8799 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8801 if (size && !direct)
8802 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8807 /* now some housekeeping stuff */
8809 /* we had to allocate for this iCode */
8810 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8811 freeAsmop(NULL,aop,ic,TRUE);
8813 /* we did not allocate which means left
8814 already in a pointer register, then
8815 if size > 0 && this could be used again
8816 we have to point it back to where it
8818 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8819 if (AOP_SIZE(result) > 1 &&
8820 !OP_SYMBOL(left)->remat &&
8821 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8823 int size = AOP_SIZE(result) - 1;
8825 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8831 freeAsmop(left,NULL,ic,TRUE);
8832 freeAsmop(result,NULL,ic,TRUE);
8837 /*-----------------------------------------------------------------*/
8838 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch */
8839 /*-----------------------------------------------------------------*/
8840 static void genPagedPointerGet (operand *left,
8847 sym_link *rtype, *retype;
8850 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8852 rtype = operandType(result);
8853 retype= getSpec(rtype);
8855 aopOp(left,ic,FALSE);
8857 /* if the value is already in a pointer register
8858 then don't need anything more */
8859 if (!AOP_INPREG(AOP(left))) {
8860 /* otherwise get a free pointer register */
8862 preg = getFreePtr(ic,&aop,FALSE);
8863 pic14_emitcode("mov","%s,%s",
8865 aopGet(AOP(left),0,FALSE,TRUE));
8866 rname = preg->name ;
8868 rname = aopGet(AOP(left),0,FALSE,FALSE);
8870 freeAsmop(left,NULL,ic,TRUE);
8871 aopOp (result,ic,FALSE);
8873 /* if bitfield then unpack the bits */
8874 if (IS_BITFIELD(retype))
8875 genUnpackBits (result,left,rname,PPOINTER,0);
8877 /* we have can just get the values */
8878 int size = AOP_SIZE(result);
8883 pic14_emitcode("movx","a,@%s",rname);
8884 aopPut(AOP(result),"a",offset);
8889 pic14_emitcode("inc","%s",rname);
8893 /* now some housekeeping stuff */
8895 /* we had to allocate for this iCode */
8896 freeAsmop(NULL,aop,ic,TRUE);
8898 /* we did not allocate which means left
8899 already in a pointer register, then
8900 if size > 0 && this could be used again
8901 we have to point it back to where it
8903 if (AOP_SIZE(result) > 1 &&
8904 !OP_SYMBOL(left)->remat &&
8905 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8907 int size = AOP_SIZE(result) - 1;
8909 pic14_emitcode("dec","%s",rname);
8914 freeAsmop(result,NULL,ic,TRUE);
8919 /*-----------------------------------------------------------------*/
8920 /* genFarPointerGet - gget value from far space */
8921 /*-----------------------------------------------------------------*/
8922 static void genFarPointerGet (operand *left,
8923 operand *result, iCode *ic)
8926 sym_link *retype = getSpec(operandType(result));
8929 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8931 aopOp(left,ic,FALSE);
8933 /* if the operand is already in dptr
8934 then we do nothing else we move the value to dptr */
8935 if (AOP_TYPE(left) != AOP_STR) {
8936 /* if this is remateriazable */
8937 if (AOP_TYPE(left) == AOP_IMMD)
8938 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8939 else { /* we need to get it byte by byte */
8940 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8941 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8942 if (options.model == MODEL_FLAT24)
8944 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8948 /* so dptr know contains the address */
8949 freeAsmop(left,NULL,ic,TRUE);
8950 aopOp(result,ic,FALSE);
8952 /* if bit then unpack */
8953 if (IS_BITFIELD(retype))
8954 genUnpackBits(result,left,"dptr",FPOINTER,0);
8956 size = AOP_SIZE(result);
8960 pic14_emitcode("movx","a,@dptr");
8961 aopPut(AOP(result),"a",offset++);
8963 pic14_emitcode("inc","dptr");
8967 freeAsmop(result,NULL,ic,TRUE);
8972 /*-----------------------------------------------------------------*/
8973 /* genCodePointerGet - get value from code space */
8974 /*-----------------------------------------------------------------*/
8975 static void genCodePointerGet (operand *left,
8976 operand *result, iCode *ic)
8979 sym_link *retype = getSpec(operandType(result));
8981 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8983 aopOp(left,ic,FALSE);
8985 /* if the operand is already in dptr
8986 then we do nothing else we move the value to dptr */
8987 if (AOP_TYPE(left) != AOP_STR) {
8988 /* if this is remateriazable */
8989 if (AOP_TYPE(left) == AOP_IMMD)
8990 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8991 else { /* we need to get it byte by byte */
8992 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8993 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8994 if (options.model == MODEL_FLAT24)
8996 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
9000 /* so dptr know contains the address */
9001 freeAsmop(left,NULL,ic,TRUE);
9002 aopOp(result,ic,FALSE);
9004 /* if bit then unpack */
9005 if (IS_BITFIELD(retype))
9006 genUnpackBits(result,left,"dptr",CPOINTER,0);
9008 size = AOP_SIZE(result);
9012 pic14_emitcode("clr","a");
9013 pic14_emitcode("movc","a,@a+dptr");
9014 aopPut(AOP(result),"a",offset++);
9016 pic14_emitcode("inc","dptr");
9020 freeAsmop(result,NULL,ic,TRUE);
9023 /*-----------------------------------------------------------------*/
9024 /* genGenPointerGet - gget value from generic pointer space */
9025 /*-----------------------------------------------------------------*/
9026 static void genGenPointerGet (operand *left,
9027 operand *result, iCode *ic)
9030 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9031 aopOp(left,ic,FALSE);
9032 aopOp(result,ic,FALSE);
9035 DEBUGpic14_AopType(__LINE__,left,NULL,result);
9037 if (IS_BITFIELD(getSpec(operandType(result))))
9039 genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
9044 /* emit call to __gptrget */
9045 char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
9046 int size = AOP_SIZE(result);
9049 assert (size > 0 && size <= 4);
9051 /* pass arguments */
9052 assert (AOP_SIZE(left) == 3);
9053 mov2w(AOP(left), 0);
9054 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9055 mov2w(AOP(left), 1);
9056 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9057 mov2w(AOP(left), 2);
9058 call_libraryfunc (func[size]);
9061 movwf (AOP(result), --size);
9063 emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
9064 movwf (AOP(result), size);
9068 freeAsmop(left,NULL,ic,TRUE);
9069 freeAsmop(result,NULL,ic,TRUE);
9073 /*-----------------------------------------------------------------*/
9074 /* genConstPointerGet - get value from const generic pointer space */
9075 /*-----------------------------------------------------------------*/
9076 static void genConstPointerGet (operand *left,
9077 operand *result, iCode *ic)
9079 //sym_link *retype = getSpec(operandType(result));
9081 symbol *albl, *blbl;//, *clbl;
9088 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9089 aopOp(left,ic,FALSE);
9090 aopOp(result,ic,FALSE);
9092 size = AOP_SIZE(result);
9094 DEBUGpic14_AopType(__LINE__,left,NULL,result);
9096 DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
9098 lit = op_isLitLike (left);
9099 poc = lit ? POC_MOVLW : POC_MOVFW;
9101 if (IS_BITFIELD(getSpec(operandType(result))))
9103 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
9108 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
9109 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
9110 assert (size > 0 && size <= 4);
9113 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9115 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9116 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
9117 call_libraryfunc (func[size]);
9119 movwf(AOP(result),size-1);
9120 for (i = 1; i < size; i++)
9122 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
9123 movwf(AOP(result),size - 1 - i);
9128 freeAsmop(left,NULL,ic,TRUE);
9129 freeAsmop(result,NULL,ic,TRUE);
9132 /*-----------------------------------------------------------------*/
9133 /* genPointerGet - generate code for pointer get */
9134 /*-----------------------------------------------------------------*/
9135 static void genPointerGet (iCode *ic)
9137 operand *left, *result ;
9138 sym_link *type, *etype;
9142 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9145 result = IC_RESULT(ic) ;
9147 /* depending on the type of pointer we need to
9148 move it to the correct pointer register */
9149 type = operandType(left);
9150 etype = getSpec(type);
9152 if (IS_PTR_CONST(type))
9153 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9155 /* if left is of type of pointer then it is simple */
9156 if (IS_PTR(type) && !IS_FUNC(type->next))
9157 p_type = DCL_TYPE(type);
9159 /* we have to go by the storage class */
9160 p_type = PTR_TYPE(SPEC_OCLS(etype));
9162 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9164 if (SPEC_OCLS(etype)->codesp ) {
9165 DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9166 //p_type = CPOINTER ;
9169 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9170 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9171 /*p_type = FPOINTER ;*/
9173 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9174 DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9175 /* p_type = PPOINTER; */
9177 if (SPEC_OCLS(etype) == idata )
9178 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9179 /* p_type = IPOINTER; */
9181 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9182 /* p_type = POINTER ; */
9185 /* now that we have the pointer type we assign
9186 the pointer values */
9192 genNearPointerGet (left,result,ic);
9196 genPagedPointerGet(left,result,ic);
9200 genFarPointerGet (left,result,ic);
9204 genConstPointerGet (left,result,ic);
9208 genGenPointerGet (left,result,ic);
9211 assert ( !"unhandled pointer type" );
9217 /*-----------------------------------------------------------------*/
9218 /* genPackBits - generates code for packed bit storage */
9219 /*-----------------------------------------------------------------*/
9220 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9222 int blen; /* bitfield length */
9223 int bstr; /* bitfield starting bit within byte */
9224 int litval; /* source literal value (if AOP_LIT) */
9225 unsigned char mask; /* bitmask within current byte */
9228 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9230 blen = SPEC_BLEN (etype);
9231 bstr = SPEC_BSTR (etype);
9233 /* If the bitfield length is less than a byte and does not cross byte boundaries */
9234 if ((blen <= 8) && ((bstr + blen) <= 8))
9236 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9237 (unsigned char) (0xFF >> (8 - bstr)));
9239 if (AOP_TYPE (right) == AOP_LIT)
9241 /* Case with a bitfield length <8 and literal source */
9242 int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9249 if (AOP(result)->type == AOP_PCODE)
9250 pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9252 pcop = popGet(AOP(result),0);
9253 emitpcode(lit?POC_BSF:POC_BCF,pcop);
9259 emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9263 assert( !"trying to assign to bitfield via pointer to __code space" );
9267 emitPtrByteGet(result, p_type, FALSE);
9269 emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9271 emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9273 emitPtrByteSet(result, p_type, TRUE);
9277 assert( !"unhandled pointer type" );
9279 } // switch (p_type)
9282 litval = lit << bstr;
9283 litval &= (~mask) & 0x00ff;
9288 mov2w (AOP(result), 0);
9289 if ((litval|mask) != 0x00ff)
9290 emitpcode(POC_ANDLW, popGetLit (mask));
9292 emitpcode(POC_IORLW, popGetLit (litval));
9293 movwf (AOP(result), 0);
9299 emitPtrByteGet(result, p_type, FALSE);
9300 if ((litval|mask) != 0x00ff)
9301 emitpcode(POC_ANDLW, popGetLit (mask));
9303 emitpcode(POC_IORLW, popGetLit (litval));
9304 emitPtrByteSet(result, p_type, TRUE);
9308 assert( !"trying to assign to bitfield via pointer to __code space" );
9312 assert( !"unhandled pointer type" );
9319 /* right is no literal */
9324 /* Note more efficient code, of pre clearing bit then only setting it if required,
9325 * can only be done if it is known that the result is not a SFR */
9326 emitpcode(POC_RRFW,popGet(AOP(right),0));
9328 emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9330 emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9336 emitPtrByteGet (result, p_type, FALSE);
9337 emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9338 emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9339 emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9340 emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9341 emitPtrByteSet (result, p_type, TRUE);
9345 assert( !"trying to assign to bitfield via pointer to __code space" );
9349 assert( !"unhandled pointer type" );
9354 /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9355 pCodeOp *temp = popGetTempReg ();
9357 mov2w (AOP(right), 0);
9359 emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9361 emitpcode(POC_MOVWF, temp);
9363 AccLsh (temp, bstr);
9369 mov2w (AOP(result), 0);
9370 emitpcode(POC_ANDLW, popGetLit (mask));
9371 emitpcode(POC_IORFW, temp);
9372 movwf (AOP(result), 0);
9378 emitPtrByteGet (result, p_type, FALSE);
9379 emitpcode(POC_ANDLW, popGetLit (mask));
9380 emitpcode(POC_IORFW, temp);
9381 emitPtrByteSet (result, p_type, TRUE);
9385 assert( !"trying to assign to bitfield via pointer to __code space" );
9389 assert( !"unhandled pointer type" );
9393 popReleaseTempReg (temp);
9395 } // if (AOP(right)->type != AOP_LIT)
9397 } // if (blen <= 8 && ((blen + bstr) <= 8))
9399 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9402 /*-----------------------------------------------------------------*/
9403 /* genDataPointerSet - remat pointer to data space */
9404 /*-----------------------------------------------------------------*/
9405 static void genDataPointerSet(operand *right,
9409 int size, offset = 0 ;
9413 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9414 aopOp(right,ic,FALSE);
9415 aopOp(result,ic,FALSE);
9417 assert (IS_SYMOP(result));
9418 assert (IS_PTR(OP_SYM_TYPE(result)));
9420 if (AOP_TYPE(right) == AOP_LIT)
9423 size = AOP_SIZE(right);
9424 ressize = getSize(OP_SYM_ETYPE(result));
9425 if (size > ressize) size = ressize;
9426 //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9428 //assert( !"what's going on here?" );
9431 if ( AOP_TYPE(result) == AOP_PCODE) {
9432 fprintf(stderr,"genDataPointerSet %s, %d\n",
9433 AOP(result)->aopu.pcop->name,
9434 PCOI(AOP(result)->aopu.pcop)->offset);
9438 // tsd, was l+1 - the underline `_' prefix was being stripped
9440 emitpComment ("%s:%u: size=%d/%d, offset=%d, AOP_TYPE(res)=%d", __FILE__,__LINE__, size, ressize, offset, AOP_TYPE(result));
9442 if (AOP_TYPE(right) == AOP_LIT) {
9443 unsigned int lit = pic14aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
9444 //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9446 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9447 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9449 emitpcode(POC_CLRF, popGet(AOP(result), offset));
9452 //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9453 emitpcode(POC_MOVFW, popGet(AOP(right), offset));
9454 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9460 freeAsmop(right,NULL,ic,TRUE);
9461 freeAsmop(result,NULL,ic,TRUE);
9464 /*-----------------------------------------------------------------*/
9465 /* genNearPointerSet - pic14_emitcode for near pointer put */
9466 /*-----------------------------------------------------------------*/
9467 static void genNearPointerSet (operand *right,
9472 sym_link *ptype = operandType(result);
9473 sym_link *retype = getSpec(operandType(right));
9474 sym_link *letype = getSpec(ptype);
9479 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9480 aopOp(result,ic,FALSE);
9483 /* if the result is rematerializable &
9484 in data space & not a bit variable */
9485 //if (AOP_TYPE(result) == AOP_IMMD &&
9486 if (AOP_TYPE(result) == AOP_PCODE &&
9487 PIC_IS_DATA_PTR(ptype) &&
9488 !IS_BITVAR (retype) &&
9489 !IS_BITVAR (letype)) {
9490 genDataPointerSet (right,result,ic);
9491 freeAsmop(result,NULL,ic,TRUE);
9496 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9497 aopOp(right,ic,FALSE);
9498 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9500 /* Check if can access directly instead of via a pointer */
9501 if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9505 if (IS_BITFIELD (letype))
9507 genPackBits (letype, result, right, direct?-1:POINTER);
9511 /* If the pointer value is not in a the FSR then need to put it in */
9512 /* Must set/reset IRP bit for use with FSR. */
9513 /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9518 /* we have can just get the values */
9519 int size = AOP_SIZE(right);
9522 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9524 char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9526 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9528 if (AOP_TYPE(right) == AOP_LIT) {
9529 emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9531 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9534 emitpcode(POC_MOVWF,popGet(AOP(result),0));
9536 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9538 if (size && !direct)
9539 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9544 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9545 /* now some housekeeping stuff */
9547 /* we had to allocate for this iCode */
9548 freeAsmop(NULL,aop,ic,TRUE);
9550 /* we did not allocate which means left
9551 already in a pointer register, then
9552 if size > 0 && this could be used again
9553 we have to point it back to where it
9555 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9556 if (AOP_SIZE(right) > 1 &&
9557 !OP_SYMBOL(result)->remat &&
9558 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9560 int size = AOP_SIZE(right) - 1;
9562 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9566 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9569 freeAsmop(right,NULL,ic,TRUE);
9570 freeAsmop(result,NULL,ic,TRUE);
9574 /*-----------------------------------------------------------------*/
9575 /* genPagedPointerSet - pic14_emitcode for Paged pointer put */
9576 /*-----------------------------------------------------------------*/
9577 static void genPagedPointerSet (operand *right,
9587 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9589 retype= getSpec(operandType(right));
9591 aopOp(result,ic,FALSE);
9593 /* if the value is already in a pointer register
9594 then don't need anything more */
9595 if (!AOP_INPREG(AOP(result))) {
9596 /* otherwise get a free pointer register */
9598 preg = getFreePtr(ic,&aop,FALSE);
9599 pic14_emitcode("mov","%s,%s",
9601 aopGet(AOP(result),0,FALSE,TRUE));
9602 rname = preg->name ;
9604 rname = aopGet(AOP(result),0,FALSE,FALSE);
9606 freeAsmop(result,NULL,ic,TRUE);
9607 aopOp (right,ic,FALSE);
9609 /* if bitfield then unpack the bits */
9610 if (IS_BITFIELD(retype))
9611 genPackBits (retype,result,right,rname,PPOINTER);
9613 /* we have can just get the values */
9614 int size = AOP_SIZE(right);
9618 l = aopGet(AOP(right),offset,FALSE,TRUE);
9621 pic14_emitcode("movx","@%s,a",rname);
9624 pic14_emitcode("inc","%s",rname);
9630 /* now some housekeeping stuff */
9632 /* we had to allocate for this iCode */
9633 freeAsmop(NULL,aop,ic,TRUE);
9635 /* we did not allocate which means left
9636 already in a pointer register, then
9637 if size > 0 && this could be used again
9638 we have to point it back to where it
9640 if (AOP_SIZE(right) > 1 &&
9641 !OP_SYMBOL(result)->remat &&
9642 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9644 int size = AOP_SIZE(right) - 1;
9646 pic14_emitcode("dec","%s",rname);
9651 freeAsmop(right,NULL,ic,TRUE);
9656 /*-----------------------------------------------------------------*/
9657 /* genFarPointerSet - set value from far space */
9658 /*-----------------------------------------------------------------*/
9659 static void genFarPointerSet (operand *right,
9660 operand *result, iCode *ic)
9663 sym_link *retype = getSpec(operandType(right));
9666 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9667 aopOp(result,ic,FALSE);
9669 /* if the operand is already in dptr
9670 then we do nothing else we move the value to dptr */
9671 if (AOP_TYPE(result) != AOP_STR) {
9672 /* if this is remateriazable */
9673 if (AOP_TYPE(result) == AOP_IMMD)
9674 pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9675 else { /* we need to get it byte by byte */
9676 pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9677 pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9678 if (options.model == MODEL_FLAT24)
9680 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9684 /* so dptr know contains the address */
9685 freeAsmop(result,NULL,ic,TRUE);
9686 aopOp(right,ic,FALSE);
9688 /* if bit then unpack */
9689 if (IS_BITFIELD(retype))
9690 genPackBits(retype,result,right,"dptr",FPOINTER);
9692 size = AOP_SIZE(right);
9696 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9698 pic14_emitcode("movx","@dptr,a");
9700 pic14_emitcode("inc","dptr");
9704 freeAsmop(right,NULL,ic,TRUE);
9708 /*-----------------------------------------------------------------*/
9709 /* genGenPointerSet - set value from generic pointer space */
9710 /*-----------------------------------------------------------------*/
9711 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9713 sym_link *retype = getSpec(operandType(result));
9716 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9717 aopOp(right,ic,FALSE);
9718 aopOp(result,ic,FALSE);
9721 DEBUGpic14_AopType(__LINE__,right,NULL,result);
9723 if (IS_BITFIELD(retype))
9725 genPackBits (retype, result, right, GPOINTER);
9730 /* emit call to __gptrput */
9731 char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9732 int size = AOP_SIZE(right);
9735 assert (size == getSize(OP_SYM_ETYPE(result)));
9736 assert (size > 0 && size <= 4);
9738 /* pass arguments */
9739 /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9745 mov2w_op (right, off);
9746 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9751 assert (AOP_SIZE(result) == 3);
9752 mov2w(AOP(result), 0);
9753 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9754 mov2w(AOP(result), 1);
9755 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9756 mov2w(AOP(result), 2);
9757 call_libraryfunc (func[size]);
9760 freeAsmop(right,NULL,ic,TRUE);
9761 freeAsmop(result,NULL,ic,TRUE);
9764 /*-----------------------------------------------------------------*/
9765 /* genPointerSet - stores the value into a pointer location */
9766 /*-----------------------------------------------------------------*/
9767 static void genPointerSet (iCode *ic)
9769 operand *right, *result ;
9770 sym_link *type, *etype;
9774 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9776 right = IC_RIGHT(ic);
9777 result = IC_RESULT(ic) ;
9779 /* depending on the type of pointer we need to
9780 move it to the correct pointer register */
9781 type = operandType(result);
9782 etype = getSpec(type);
9783 /* if left is of type of pointer then it is simple */
9784 if (IS_PTR(type) && !IS_FUNC(type->next)) {
9785 p_type = DCL_TYPE(type);
9788 /* we have to go by the storage class */
9789 p_type = PTR_TYPE(SPEC_OCLS(etype));
9791 /* if (SPEC_OCLS(etype)->codesp ) { */
9792 /* p_type = CPOINTER ; */
9795 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9796 /* p_type = FPOINTER ; */
9798 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9799 /* p_type = PPOINTER ; */
9801 /* if (SPEC_OCLS(etype) == idata ) */
9802 /* p_type = IPOINTER ; */
9804 /* p_type = POINTER ; */
9807 /* now that we have the pointer type we assign
9808 the pointer values */
9814 genNearPointerSet (right,result,ic);
9818 genPagedPointerSet (right,result,ic);
9822 genFarPointerSet (right,result,ic);
9826 genGenPointerSet (right,result,ic);
9830 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9831 "genPointerSet: illegal pointer type");
9835 /*-----------------------------------------------------------------*/
9836 /* genIfx - generate code for Ifx statement */
9837 /*-----------------------------------------------------------------*/
9838 static void genIfx (iCode *ic, iCode *popIc)
9840 operand *cond = IC_COND(ic);
9844 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9846 aopOp(cond,ic,FALSE);
9848 /* get the value into acc */
9849 if (AOP_TYPE(cond) != AOP_CRY)
9850 pic14_toBoolean(cond);
9854 /* if there was something to be popped then do it */
9860 /* This assumes that CARRY is set iff cond is true */
9863 assert (!IC_FALSE(ic));
9864 emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
9866 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9868 assert (IC_FALSE(ic));
9869 emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
9871 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9875 static int hasWarned = 0;
9878 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
9885 /* now Z is set iff !cond */
9888 assert (!IC_FALSE(ic));
9890 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9893 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9899 /* the result is now in the accumulator */
9900 freeAsmop(cond,NULL,ic,TRUE);
9903 /*-----------------------------------------------------------------*/
9904 /* genAddrOf - generates code for address of */
9905 /*-----------------------------------------------------------------*/
9906 static void genAddrOf (iCode *ic)
9908 operand *right, *result, *left;
9912 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9915 //aopOp(IC_RESULT(ic),ic,FALSE);
9917 aopOp((left=IC_LEFT(ic)),ic,FALSE);
9918 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9919 aopOp((result=IC_RESULT(ic)),ic,TRUE);
9921 DEBUGpic14_AopType(__LINE__,left,right,result);
9922 assert (IS_SYMOP (left));
9924 /* sanity check: generic pointers to code space are not yet supported,
9925 * pionters to codespace must not be assigned addresses of __data values. */
9927 fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9928 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)));
9929 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)));
9930 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)));
9931 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)));
9934 if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9935 fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9936 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9937 OP_SYMBOL(left)->name);
9938 } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9939 fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9940 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9941 OP_SYMBOL(left)->name);
9944 size = AOP_SIZE(IC_RESULT(ic));
9945 if (IS_GENPTR(OP_SYM_TYPE(result))) {
9947 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9952 /* fixing bug #863624, reported from (errolv) */
9953 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9954 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9957 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9958 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9963 if (IS_GENPTR(OP_SYM_TYPE(result)))
9965 /* provide correct tag */
9966 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9967 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9968 movwf (AOP(result), 2);
9971 freeAsmop(left,NULL,ic,FALSE);
9972 freeAsmop(result,NULL,ic,TRUE);
9977 /*-----------------------------------------------------------------*/
9978 /* genFarFarAssign - assignment when both are in far space */
9979 /*-----------------------------------------------------------------*/
9980 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9982 int size = AOP_SIZE(right);
9985 /* first push the right side on to the stack */
9987 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9989 pic14_emitcode ("push","acc");
9992 freeAsmop(right,NULL,ic,FALSE);
9993 /* now assign DPTR to result */
9994 aopOp(result,ic,FALSE);
9995 size = AOP_SIZE(result);
9997 pic14_emitcode ("pop","acc");
9998 aopPut(AOP(result),"a",--offset);
10000 freeAsmop(result,NULL,ic,FALSE);
10005 /*-----------------------------------------------------------------*/
10006 /* genAssign - generate code for assignment */
10007 /*-----------------------------------------------------------------*/
10008 static void genAssign (iCode *ic)
10010 operand *result, *right;
10011 int size, offset,know_W;
10012 unsigned long lit = 0L;
10014 result = IC_RESULT(ic);
10015 right = IC_RIGHT(ic) ;
10018 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10020 /* if they are the same */
10021 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10024 aopOp(right,ic,FALSE);
10025 aopOp(result,ic,TRUE);
10027 DEBUGpic14_AopType(__LINE__,NULL,right,result);
10029 /* if they are the same registers */
10030 if (pic14_sameRegs(AOP(right),AOP(result)))
10033 /* special case: assign from __code */
10034 if (!IS_ITEMP(right) /* --> iTemps never reside in __code */
10035 && IS_SYMOP (right) /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
10036 && !IS_FUNC(OP_SYM_TYPE(right)) /* --> we would want its address instead of the first instruction */
10037 && !IS_CODEPTR(OP_SYM_TYPE(right)) /* --> get symbols address instread */
10038 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
10040 emitpComment ("genAssign from CODESPACE");
10041 genConstPointerGet (right, result, ic);
10045 /* just for symmetry reasons... */
10046 if (!IS_ITEMP(result)
10047 && IS_SYMOP (result)
10048 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
10050 assert ( !"cannot write to CODESPACE" );
10053 /* if the result is a bit */
10054 if (AOP_TYPE(result) == AOP_CRY) {
10056 /* if the right size is a literal then
10057 we know what the value is */
10058 if (AOP_TYPE(right) == AOP_LIT) {
10060 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10061 popGet(AOP(result),0));
10063 if (((int) operandLitValue(right)))
10064 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10065 AOP(result)->aopu.aop_dir,
10066 AOP(result)->aopu.aop_dir);
10068 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10069 AOP(result)->aopu.aop_dir,
10070 AOP(result)->aopu.aop_dir);
10074 /* the right is also a bit variable */
10075 if (AOP_TYPE(right) == AOP_CRY) {
10076 emitpcode(POC_BCF, popGet(AOP(result),0));
10077 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10078 emitpcode(POC_BSF, popGet(AOP(result),0));
10080 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10081 AOP(result)->aopu.aop_dir,
10082 AOP(result)->aopu.aop_dir);
10083 pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
10084 AOP(right)->aopu.aop_dir,
10085 AOP(right)->aopu.aop_dir);
10086 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10087 AOP(result)->aopu.aop_dir,
10088 AOP(result)->aopu.aop_dir);
10092 /* we need to or */
10093 emitpcode(POC_BCF, popGet(AOP(result),0));
10094 pic14_toBoolean(right);
10096 emitpcode(POC_BSF, popGet(AOP(result),0));
10097 //aopPut(AOP(result),"a",0);
10101 /* bit variables done */
10103 size = AOP_SIZE(result);
10105 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
10106 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10107 if(aopIdx(AOP(result),0) == 4) {
10108 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10109 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10110 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10113 DEBUGpic14_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
10119 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10120 if(AOP_TYPE(right) == AOP_LIT) {
10121 lit = (unsigned long)pic14aopLiteral(AOP(right)->aopu.aop_lit, offset) & 0x0ff;
10123 if(know_W != (int)(lit&0xff))
10124 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10126 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10128 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10130 } else if (AOP_TYPE(right) == AOP_CRY) {
10131 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10133 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10134 emitpcode(POC_INCF, popGet(AOP(result),0));
10137 mov2w_op (right, offset);
10138 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10146 freeAsmop (right,NULL,ic,FALSE);
10147 freeAsmop (result,NULL,ic,TRUE);
10150 /*-----------------------------------------------------------------*/
10151 /* genJumpTab - genrates code for jump table */
10152 /*-----------------------------------------------------------------*/
10153 static void genJumpTab (iCode *ic)
10159 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10161 aopOp(IC_JTCOND(ic),ic,FALSE);
10162 /* get the condition into accumulator */
10163 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10165 /* multiply by three */
10166 pic14_emitcode("add","a,acc");
10167 pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10169 jtab = newiTempLabel(NULL);
10170 pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10171 pic14_emitcode("jmp","@a+dptr");
10172 pic14_emitcode("","%05d_DS_:",jtab->key+100);
10174 emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10175 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10176 emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10177 emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10179 emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10180 emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10181 emitpLabel(jtab->key);
10183 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10185 /* now generate the jump labels */
10186 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10187 jtab = setNextItem(IC_JTLABELS(ic))) {
10188 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10189 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10195 /*-----------------------------------------------------------------*/
10196 /* genMixedOperation - gen code for operators between mixed types */
10197 /*-----------------------------------------------------------------*/
10199 TSD - Written for the PIC port - but this unfortunately is buggy.
10200 This routine is good in that it is able to efficiently promote
10201 types to different (larger) sizes. Unfortunately, the temporary
10202 variables that are optimized out by this routine are sometimes
10203 used in other places. So until I know how to really parse the
10204 iCode tree, I'm going to not be using this routine :(.
10206 static int genMixedOperation (iCode *ic)
10210 operand *result = IC_RESULT(ic);
10211 sym_link *ctype = operandType(IC_LEFT(ic));
10212 operand *right = IC_RIGHT(ic);
10218 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10220 pic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10226 nextright = IC_RIGHT(nextic);
10227 nextleft = IC_LEFT(nextic);
10228 nextresult = IC_RESULT(nextic);
10230 aopOp(right,ic,FALSE);
10231 aopOp(result,ic,FALSE);
10232 aopOp(nextright, nextic, FALSE);
10233 aopOp(nextleft, nextic, FALSE);
10234 aopOp(nextresult, nextic, FALSE);
10236 if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10238 operand *t = right;
10242 pic14_emitcode(";remove right +","");
10244 } else if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10246 operand *t = right;
10250 pic14_emitcode(";remove left +","");
10254 big = AOP_SIZE(nextleft);
10255 small = AOP_SIZE(nextright);
10257 switch(nextic->op) {
10260 pic14_emitcode(";optimize a +","");
10261 /* if unsigned or not an integral type */
10262 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10263 pic14_emitcode(";add a bit to something","");
10266 pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10268 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10269 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10270 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10272 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10280 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10281 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10282 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10285 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10287 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10288 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10289 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10290 pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10291 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10294 pic14_emitcode("rlf","known_zero,w");
10301 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10302 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10303 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10305 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10315 freeAsmop(right,NULL,ic,TRUE);
10316 freeAsmop(result,NULL,ic,TRUE);
10317 freeAsmop(nextright,NULL,ic,TRUE);
10318 freeAsmop(nextleft,NULL,ic,TRUE);
10320 nextic->generated = 1;
10327 /*-----------------------------------------------------------------*/
10328 /* genCast - gen code for casting */
10329 /*-----------------------------------------------------------------*/
10330 static void genCast (iCode *ic)
10332 operand *result = IC_RESULT(ic);
10333 sym_link *restype = operandType(result);
10334 sym_link *rtype = operandType(IC_RIGHT(ic));
10335 operand *right = IC_RIGHT(ic);
10339 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10340 /* if they are equivalent then do nothing */
10341 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10344 aopOp(right,ic,FALSE) ;
10345 aopOp(result,ic,FALSE);
10347 DEBUGpic14_AopType(__LINE__,NULL,right,result);
10349 /* if the result is a bit */
10350 if (AOP_TYPE(result) == AOP_CRY) {
10351 assert(!"assigning to bit variables is not supported");
10354 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10356 size = AOP_SIZE(result);
10358 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10360 emitpcode(POC_CLRF, popGet(AOP(result),0));
10361 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10362 emitpcode(POC_INCF, popGet(AOP(result),0));
10365 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
10370 if (IS_PTR(restype))
10372 operand *result = IC_RESULT(ic);
10373 //operand *left = IC_LEFT(ic);
10374 operand *right = IC_RIGHT(ic);
10377 /* copy common part */
10378 int max, size = AOP_SIZE(result);
10379 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10380 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10382 /* warn if we discard generic opinter tag */
10383 if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10385 //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10391 mov2w_op (right, size);
10392 movwf (AOP(result), size);
10395 /* upcast into generic pointer type? */
10396 if (IS_GENPTR(restype)
10397 && (size < AOP_SIZE(result))
10398 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10400 //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10403 switch (DCL_TYPE(rtype))
10405 case POINTER: /* __data */
10406 case FPOINTER: /* __data */
10407 assert (AOP_SIZE(right) == 2);
10408 tag = GPTRTAG_DATA;
10411 case CPOINTER: /* __code */
10412 assert (AOP_SIZE(right) == 2);
10413 tag = GPTRTAG_CODE;
10416 case GPOINTER: /* unknown destination, __data or __code */
10417 /* assume __data space (address of immediate) */
10418 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10419 if (AOP(right)->code)
10420 tag = GPTRTAG_CODE;
10422 tag = GPTRTAG_DATA;
10426 assert (!"unhandled pointer type");
10429 /* convert other values into pointers to __data space */
10430 tag = GPTRTAG_DATA;
10433 assert (AOP_SIZE(result) == 3);
10435 emitpcode(POC_CLRF, popGet(AOP(result), 2));
10437 emitpcode(POC_MOVLW, popGetLit(tag));
10438 movwf(AOP(result), 2);
10441 addSign(result, max, 0);
10446 /* if they are the same size : or less */
10447 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10449 /* if they are in the same place */
10450 if (pic14_sameRegs(AOP(right),AOP(result)))
10453 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10454 if (IS_PTR_CONST(rtype))
10455 DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10456 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10457 DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10459 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10460 emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10461 emitpcode(POC_MOVWF, popGet(AOP(result),0));
10462 emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10463 emitpcode(POC_MOVWF, popGet(AOP(result),1));
10464 if(AOP_SIZE(result) <2)
10465 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10469 /* if they in different places then copy */
10470 size = AOP_SIZE(result);
10473 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10474 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10476 //aopPut(AOP(result),
10477 // aopGet(AOP(right),offset,FALSE,FALSE),
10486 /* so we now know that the size of destination is greater
10487 than the size of the source.
10488 Now, if the next iCode is an operator then we might be
10489 able to optimize the operation without performing a cast.
10491 if(0 && genMixedOperation(ic)) {
10492 /* XXX: cannot optimize: must copy regs! */
10496 /* we move to result for the size of source */
10497 size = AOP_SIZE(right);
10500 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10501 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10505 addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10508 freeAsmop(right,NULL,ic,TRUE);
10509 freeAsmop(result,NULL,ic,TRUE);
10513 /*-----------------------------------------------------------------*/
10514 /* genDjnz - generate decrement & jump if not zero instrucion */
10515 /*-----------------------------------------------------------------*/
10516 static int genDjnz (iCode *ic, iCode *ifx)
10518 symbol *lbl, *lbl1;
10520 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10525 /* if the if condition has a false label
10526 then we cannot save */
10530 /* if the minus is not of the form
10532 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10533 !IS_OP_LITERAL(IC_RIGHT(ic)))
10536 if (operandLitValue(IC_RIGHT(ic)) != 1)
10539 /* if the size of this greater than one then no
10541 if (getSize(operandType(IC_RESULT(ic))) > 1)
10544 /* otherwise we can save BIG */
10545 lbl = newiTempLabel(NULL);
10546 lbl1= newiTempLabel(NULL);
10548 aopOp(IC_RESULT(ic),ic,FALSE);
10550 if (IS_AOP_PREG(IC_RESULT(ic))) {
10551 pic14_emitcode("dec","%s",
10552 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10553 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10554 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10558 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10559 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10561 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10562 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10565 /* pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10566 /* pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10567 /* pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10568 /* pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10571 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10572 ifx->generated = 1;
10576 /*-----------------------------------------------------------------*/
10577 /* genReceive - generate code for a receive iCode */
10578 /*-----------------------------------------------------------------*/
10579 static void genReceive (iCode *ic)
10582 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10584 if (isOperandInFarSpace(IC_RESULT(ic)) &&
10585 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10586 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10588 int size = getSize(operandType(IC_RESULT(ic)));
10589 int offset = fReturnSizePic - size;
10591 pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10592 fReturn[fReturnSizePic - offset - 1] : "acc"));
10595 aopOp(IC_RESULT(ic),ic,FALSE);
10596 size = AOP_SIZE(IC_RESULT(ic));
10599 pic14_emitcode ("pop","acc");
10600 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10605 aopOp(IC_RESULT(ic),ic,FALSE);
10607 GpsuedoStkPtr = ic->parmBytes; // address used arg on stack
10608 assignResultValue(IC_RESULT(ic));
10611 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10614 /*-----------------------------------------------------------------*/
10615 /* genDummyRead - generate code for dummy read of volatiles */
10616 /*-----------------------------------------------------------------*/
10618 genDummyRead (iCode * ic)
10621 pic14_emitcode ("; genDummyRead","");
10622 pic14_emitcode ("; not implemented","");
10627 /*-----------------------------------------------------------------*/
10628 /* genpic14Code - generate code for pic14 based controllers */
10629 /*-----------------------------------------------------------------*/
10631 * At this point, ralloc.c has gone through the iCode and attempted
10632 * to optimize in a way suitable for a PIC. Now we've got to generate
10633 * PIC instructions that correspond to the iCode.
10635 * Once the instructions are generated, we'll pass through both the
10636 * peep hole optimizer and the pCode optimizer.
10637 *-----------------------------------------------------------------*/
10639 void genpic14Code (iCode *lic)
10646 lineHead = lineCurr = NULL;
10648 pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10651 /* if debug information required */
10652 if (options.debug && currFunc) {
10654 debugFile->writeFunction (currFunc, lic);
10659 for (ic = lic ; ic ; ic = ic->next ) {
10661 //DEBUGpic14_emitcode(";ic","");
10662 //fprintf (stderr, "in ic loop\n");
10663 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10664 //ic->lineno, printCLine(ic->filename, ic->lineno));
10666 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10668 //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10669 cline = printCLine (ic->filename, ic->lineno);
10670 if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10671 addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10672 //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10675 if (options.iCodeInAsm) {
10676 emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10678 /* if the result is marked as
10679 spilt and rematerializable or code for
10680 this has already been generated then
10682 if (resultRemat(ic) || ic->generated )
10685 /* depending on the operation */
10704 /* IPOP happens only when trying to restore a
10705 spilt live range, if there is an ifx statement
10706 following this pop then the if statement might
10707 be using some of the registers being popped which
10708 would destory the contents of the register so
10709 we need to check for this condition and handle it */
10711 ic->next->op == IFX &&
10712 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10713 genIfx (ic->next,ic);
10731 genEndFunction (ic);
10751 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10768 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
10772 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10779 /* note these two are xlated by algebraic equivalence
10780 during parsing SDCC.y */
10781 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10782 "got '>=' or '<=' shouldn't have come here");
10786 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10798 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10802 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10806 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10830 genRightShift (ic);
10833 case GET_VALUE_AT_ADDRESS:
10838 if (POINTER_SET(ic))
10865 addSet(&_G.sendSet,ic);
10868 case DUMMY_READ_VOLATILE:
10873 fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10880 /* now we are ready to call the
10881 peep hole optimizer */
10882 if (!options.nopeep) {
10883 peepHole (&lineHead);
10885 /* now do the actual printing */
10886 printLine (lineHead,codeOutFile);
10889 DFPRINTF((stderr,"printing pBlock\n\n"));
10890 printpBlock(stdout,pb);
10896 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10897 * (meaning: representing its own address) or not (referencing its contents).
10898 * This can only be decided based on the operand's type. */
10900 aop_isLitLike (asmop *aop)
10903 if (aop->type == AOP_LIT) return 1;
10904 if (aop->type == AOP_IMMD) return 1;
10905 if ((aop->type == AOP_PCODE) &&
10906 ((aop->aopu.pcop->type == PO_LITERAL)))
10908 /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10909 * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10916 op_isLitLike (operand *op)
10919 if (aop_isLitLike (AOP(op))) return 1;
10920 if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10921 if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;