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 -------------------------------------------------------------------------*/
44 #include "SDCCglobl.h"
48 #include "SDCCpeeph.h"
53 /* When changing these, you must also update the assembler template
54 * in device/lib/libsdcc/macros.inc */
55 #define GPTRTAG_DATA 0x00
56 #define GPTRTAG_CODE 0x80
58 /* The PIC port(s) need not differentiate between POINTER and FPOINTER. */
59 #define PIC_IS_DATA_PTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
60 #define PIC_IS_FARPTR(x) (PIC_IS_DATA_PTR(x))
62 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
63 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
64 void genMult8X8_8 (operand *, operand *,operand *);
65 extern void printpBlock(FILE *of, pBlock *pb);
67 static int labelOffset=0;
68 extern int debug_verbose;
69 extern int pic14_hasInterrupt;
70 //static int optimized_for_speed = 0;
72 /* max_key keeps track of the largest label number used in
73 a function. This is then used to adjust the label offset
74 for the next function.
77 static int GpsuedoStkPtr=0;
79 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
80 extern char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
81 unsigned int pic14aopLiteral (value *val, int offset);
82 const char *AopType(short type);
84 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0x00ff)
86 /* this is the down and dirty file with all kinds of
87 kludgy & hacky stuff. This is what it is all about
88 CODE GENERATION for a specific MCU . some of the
89 routines may be reusable, will have to see */
91 static char *zero = "#0x00";
92 static char *one = "#0x01";
93 static char *spname = "sp";
95 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
96 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
97 static char **fReturn = fReturnpic14;
99 //static char *accUse[] = {"a","b"};
101 //static short rbank = -1;
113 /* Resolved ifx structure. This structure stores information
114 about an iCode ifx that makes it easier to generate code.
116 typedef struct resolvedIfx {
117 symbol *lbl; /* pointer to a label */
118 int condition; /* true or false ifx */
119 int generated; /* set true when the code associated with the ifx
123 extern int pic14_ptrRegReq ;
124 extern int pic14_nRegs;
125 extern FILE *codeOutFile;
126 static void saverbank (int, iCode *,bool);
128 static lineNode *lineHead = NULL;
129 static lineNode *lineCurr = NULL;
132 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
133 0xE0, 0xC0, 0x80, 0x00};
134 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
135 0x07, 0x03, 0x01, 0x00};
140 /*-----------------------------------------------------------------*/
141 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
142 /* exponent of 2 is returned, otherwise -1 is */
144 /* note that this is similar to the function `powof2' in SDCCsymt */
148 /*-----------------------------------------------------------------*/
149 static int my_powof2 (unsigned long num)
152 if( (num & (num-1)) == 0) {
165 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
168 DEBUGpic14_emitcode ("; ","line = %d result %s=%s, size=%d, left %s=%s, size=%d, right %s=%s, size=%d",
170 ((result) ? AopType(AOP_TYPE(result)) : "-"),
171 ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
172 ((result) ? AOP_SIZE(result) : 0),
173 ((left) ? AopType(AOP_TYPE(left)) : "-"),
174 ((left) ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
175 ((left) ? AOP_SIZE(left) : 0),
176 ((right) ? AopType(AOP_TYPE(right)) : "-"),
177 ((right) ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
178 ((right) ? AOP_SIZE(right) : 0));
182 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
185 DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
187 ((result) ? AopType(AOP_TYPE(result)) : "-"),
188 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
189 ((left) ? AopType(AOP_TYPE(left)) : "-"),
190 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
191 ((right) ? AopType(AOP_TYPE(right)) : "-"),
192 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
196 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
199 char lb[INITIAL_INLINEASM];
200 unsigned char *lbp = (unsigned char *)lb;
202 if(!debug_verbose && !options.debug)
209 sprintf(lb,"%s\t",inst);
211 sprintf(lb,"%s",inst);
212 vsprintf(lb+(strlen(lb)),fmt,ap);
216 while (isspace(*lbp)) lbp++;
219 lineCurr = (lineCurr ?
220 connectLine(lineCurr,newLineNode(lb)) :
221 (lineHead = newLineNode(lb)));
222 lineCurr->isInline = _G.inLine;
223 lineCurr->isDebug = _G.debugLine;
225 addpCode2pBlock(pb,newpCodeCharP(lb));
230 static void Safe_vsnprintf (char *buf, size_t size, const char *fmt, va_list ap)
232 #if defined (HAVE_VSNPRINTF)
233 vsnprintf (buf, size, fmt, ap);
234 #elif defined (HAVE_VSPRINTF)
235 vsprintf (buf, size, fmt, ap);
236 if (strlen (buf) >= size)
238 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
240 #elif defined (HAVE_SNPRINTF)
241 snprintf (buf, size, "vs(n)printf required");
242 #elif defined (HAVE_SRINTF)
243 sprintf (buf, "vs(n)printf required");
244 if (strlen (buf) >= size)
246 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
249 assert ( !"neither vsnprintf nor vsprintf is present -- unable to proceed" );
253 void emitpComment (const char *fmt, ...)
260 Safe_vsnprintf (buffer, 4096, fmt, va);
261 //fprintf (stderr, "%s\n" ,buffer);
262 addpCode2pBlock (pb, newpCodeCharP (buffer));
265 Safe_vsnprintf (buffer, 4096, fmt, va);
266 fprintf (stderr, "No current pBlock -- discarding comment [%s]\n", buffer);
272 void emitpLabel(int key)
274 addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
277 /* gen.h defines a macro emitpcode that should be used to call emitpcode
278 * as this allows for easy debugging (ever asked the question: where was
279 * this instruction geenrated? Here is the answer... */
280 void emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
283 addpCode2pBlock(pb,newpCode(poc,pcop));
285 DEBUGpic14_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
288 void emitpcodeNULLop(PIC_OPCODE poc)
291 addpCode2pBlock(pb,newpCode(poc,NULL));
296 /*-----------------------------------------------------------------*/
297 /* pic14_emitcode - writes the code into a file : for now it is simple */
298 /*-----------------------------------------------------------------*/
299 void pic14_emitcode (char *inst,char *fmt, ...)
302 char lb[INITIAL_INLINEASM];
303 unsigned char *lbp = (unsigned char *)lb;
309 sprintf(lb,"%s\t",inst);
311 sprintf(lb,"%s",inst);
312 vsprintf(lb+(strlen(lb)),fmt,ap);
316 while (isspace(*lbp)) lbp++;
319 lineCurr = (lineCurr ?
320 connectLine(lineCurr,newLineNode(lb)) :
321 (lineHead = newLineNode(lb)));
322 lineCurr->isInline = _G.inLine;
323 lineCurr->isDebug = _G.debugLine;
326 addpCode2pBlock(pb,newpCodeCharP(lb));
331 /*-----------------------------------------------------------------*/
332 /* pic14_emitDebuggerSymbol - associate the current code location */
333 /* with a debugger symbol */
334 /*-----------------------------------------------------------------*/
336 pic14_emitDebuggerSymbol (char * debugSym)
339 pic14_emitcode ("", ";%s ==.", debugSym);
344 /*-----------------------------------------------------------------*/
345 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
346 /*-----------------------------------------------------------------*/
347 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
349 bool r0iu = FALSE , r1iu = FALSE;
350 bool r0ou = FALSE , r1ou = FALSE;
352 /* the logic: if r0 & r1 used in the instruction
353 then we are in trouble otherwise */
355 /* first check if r0 & r1 are used by this
356 instruction, in which case we are in trouble */
357 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
358 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
363 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
364 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
366 /* if no usage of r0 then return it */
367 if (!r0iu && !r0ou) {
368 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
369 (*aopp)->type = AOP_R0;
371 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
374 /* if no usage of r1 then return it */
375 if (!r1iu && !r1ou) {
376 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
377 (*aopp)->type = AOP_R1;
379 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
382 /* now we know they both have usage */
383 /* if r0 not used in this instruction */
385 /* push it if not already pushed */
387 //pic14_emitcode ("push","%s",
388 // pic14_regWithIdx(R0_IDX)->dname);
392 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
393 (*aopp)->type = AOP_R0;
395 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
398 /* if r1 not used then */
401 /* push it if not already pushed */
403 //pic14_emitcode ("push","%s",
404 // pic14_regWithIdx(R1_IDX)->dname);
408 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
409 (*aopp)->type = AOP_R1;
410 return pic14_regWithIdx(R1_IDX);
414 /* I said end of world but not quite end of world yet */
415 /* if this is a result then we can push it on the stack*/
417 (*aopp)->type = AOP_STK;
421 /* other wise this is true end of the world */
422 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
423 "getFreePtr should never reach here");
428 /*-----------------------------------------------------------------*/
429 /* newAsmop - creates a new asmOp */
430 /*-----------------------------------------------------------------*/
431 asmop *newAsmop (short type)
435 aop = Safe_calloc(1,sizeof(asmop));
440 static void genSetDPTR(int n)
444 pic14_emitcode(";", "Select standard DPTR");
445 pic14_emitcode("mov", "dps, #0x00");
449 pic14_emitcode(";", "Select alternate DPTR");
450 pic14_emitcode("mov", "dps, #0x01");
454 /*-----------------------------------------------------------------*/
455 /* resolveIfx - converts an iCode ifx into a form more useful for */
456 /* generating code */
457 /*-----------------------------------------------------------------*/
458 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
463 // DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
465 resIfx->condition = 1; /* assume that the ifx is true */
466 resIfx->generated = 0; /* indicate that the ifx has not been used */
469 resIfx->lbl = NULL; /* this is wrong: newiTempLabel(NULL); / * oops, there is no ifx. so create a label */
471 DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
472 __FUNCTION__,__LINE__,resIfx->lbl->key);
476 resIfx->lbl = IC_TRUE(ifx);
478 resIfx->lbl = IC_FALSE(ifx);
479 resIfx->condition = 0;
483 DEBUGpic14_emitcode("; ***","ifx true is non-null");
485 DEBUGpic14_emitcode("; ***","ifx false is non-null");
489 // DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
492 /*-----------------------------------------------------------------*/
493 /* pointerCode - returns the code for a pointer type */
494 /*-----------------------------------------------------------------*/
496 static int pointerCode (sym_link *etype)
499 return PTR_TYPE(SPEC_OCLS(etype));
504 /*-----------------------------------------------------------------*/
505 /* aopForSym - for a true symbol */
506 /*-----------------------------------------------------------------*/
507 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
510 memmap *space= SPEC_OCLS(sym->etype);
512 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
513 /* if already has one */
518 /* assign depending on the storage class */
519 /* if it is on the stack or indirectly addressable */
520 /* space we need to assign either r0 or r1 to it */
521 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
522 sym->aop = aop = newAsmop(0);
523 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
524 aop->size = getSize(sym->type);
526 /* now assign the address of the variable to
527 the pointer register */
528 if (aop->type != AOP_STK) {
532 pic14_emitcode("push","acc");
534 pic14_emitcode("mov","a,_bp");
535 pic14_emitcode("add","a,#0x%02x",
537 ((char)(sym->stack - _G.nRegsSaved )) :
538 ((char)sym->stack)) & 0xff);
539 pic14_emitcode("mov","%s,a",
540 aop->aopu.aop_ptr->name);
543 pic14_emitcode("pop","acc");
545 pic14_emitcode("mov","%s,#%s",
546 aop->aopu.aop_ptr->name,
548 aop->paged = space->paged;
550 aop->aopu.aop_stk = sym->stack;
554 if (sym->onStack && options.stack10bit)
556 /* It's on the 10 bit stack, which is located in
560 //DEBUGpic14_emitcode(";","%d",__LINE__);
563 pic14_emitcode("push","acc");
565 pic14_emitcode("mov","a,_bp");
566 pic14_emitcode("add","a,#0x%02x",
568 ((char)(sym->stack - _G.nRegsSaved )) :
569 ((char)sym->stack)) & 0xff);
572 pic14_emitcode ("mov","dpx1,#0x40");
573 pic14_emitcode ("mov","dph1,#0x00");
574 pic14_emitcode ("mov","dpl1, a");
578 pic14_emitcode("pop","acc");
580 sym->aop = aop = newAsmop(AOP_DPTR2);
581 aop->size = getSize(sym->type);
586 //DEBUGpic14_emitcode(";","%d",__LINE__);
587 /* if in bit space */
588 if (IN_BITSPACE(space)) {
589 sym->aop = aop = newAsmop (AOP_CRY);
590 aop->aopu.aop_dir = sym->rname ;
591 aop->size = getSize(sym->type);
592 //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
595 /* if it is in direct space */
596 if (IN_DIRSPACE(space)) {
597 sym->aop = aop = newAsmop (AOP_DIR);
598 aop->aopu.aop_dir = sym->rname ;
599 aop->size = getSize(sym->type);
600 DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
604 /* special case for a function */
605 if (IS_FUNC(sym->type)) {
607 sym->aop = aop = newAsmop(AOP_PCODE);
608 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
609 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
610 PCOI(aop->aopu.pcop)->_function = 1;
611 PCOI(aop->aopu.pcop)->index = 0;
612 aop->size = FPTRSIZE;
614 sym->aop = aop = newAsmop(AOP_IMMD);
615 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
616 strcpy(aop->aopu.aop_immd,sym->rname);
617 aop->size = FPTRSIZE;
619 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
623 if (IS_ARRAY(sym->type)) {
624 sym->aop = aop = newAsmop(AOP_PCODE);
625 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
626 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
627 PCOI(aop->aopu.pcop)->_function = 0;
628 PCOI(aop->aopu.pcop)->index = 0;
629 aop->size = getSize(sym->etype) * DCL_ELEM(sym->type);
631 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
635 /* only remaining is far space */
636 /* in which case DPTR gets the address */
637 sym->aop = aop = newAsmop(AOP_PCODE);
639 aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
640 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
641 PCOI(aop->aopu.pcop)->index = 0;
643 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
644 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
646 allocDirReg (IC_LEFT(ic));
648 aop->size = FPTRSIZE;
650 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
651 sym->aop = aop = newAsmop(AOP_DPTR);
652 pic14_emitcode ("mov","dptr,#%s", sym->rname);
653 aop->size = getSize(sym->type);
655 DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
658 /* if it is in code space */
659 if (IN_CODESPACE(space))
665 /*-----------------------------------------------------------------*/
666 /* aopForRemat - rematerialzes an object */
667 /*-----------------------------------------------------------------*/
668 static asmop *aopForRemat (operand *op) // x symbol *sym)
670 symbol *sym = OP_SYMBOL(op);
672 asmop *aop = newAsmop(AOP_PCODE);
676 ic = sym->rematiCode;
678 DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
679 if(IS_OP_POINTER(op)) {
680 DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
684 val += (int) operandLitValue(IC_RIGHT(ic));
685 } else if (ic->op == '-') {
686 val -= (int) operandLitValue(IC_RIGHT(ic));
690 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
693 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
694 aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
695 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
696 PCOI(aop->aopu.pcop)->index = val;
698 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
699 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
700 val, IS_PTR_CONST(operandType(op)));
702 // DEBUGpic14_emitcode(";","aop type %s",AopType(AOP_TYPE(IC_LEFT(ic))));
704 allocDirReg (IC_LEFT(ic));
709 int aopIdx (asmop *aop, int offset)
714 if(aop->type != AOP_REG)
717 return aop->aopu.aop_reg[offset]->rIdx;
720 /*-----------------------------------------------------------------*/
721 /* regsInCommon - two operands have some registers in common */
722 /*-----------------------------------------------------------------*/
723 static bool regsInCommon (operand *op1, operand *op2)
728 /* if they have registers in common */
729 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
732 sym1 = OP_SYMBOL(op1);
733 sym2 = OP_SYMBOL(op2);
735 if (sym1->nRegs == 0 || sym2->nRegs == 0)
738 for (i = 0 ; i < sym1->nRegs ; i++) {
743 for (j = 0 ; j < sym2->nRegs ;j++ ) {
747 if (sym2->regs[j] == sym1->regs[i])
755 /*-----------------------------------------------------------------*/
756 /* operandsEqu - equivalent */
757 /*-----------------------------------------------------------------*/
758 static bool operandsEqu ( operand *op1, operand *op2)
762 /* if they not symbols */
763 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
766 sym1 = OP_SYMBOL(op1);
767 sym2 = OP_SYMBOL(op2);
769 /* if both are itemps & one is spilt
770 and the other is not then false */
771 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
772 sym1->isspilt != sym2->isspilt )
775 /* if they are the same */
779 if (sym1->rname[0] && sym2->rname[0]
780 && strcmp (sym1->rname, sym2->rname) == 0)
784 /* if left is a tmp & right is not */
788 (sym1->usl.spillLoc == sym2))
795 (sym2->usl.spillLoc == sym1))
801 /*-----------------------------------------------------------------*/
802 /* pic14_sameRegs - two asmops have the same registers */
803 /*-----------------------------------------------------------------*/
804 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
811 if (aop1->type != AOP_REG ||
812 aop2->type != AOP_REG )
815 if (aop1->size != aop2->size )
818 for (i = 0 ; i < aop1->size ; i++ )
819 if (aop1->aopu.aop_reg[i] !=
820 aop2->aopu.aop_reg[i] )
826 /*-----------------------------------------------------------------*/
827 /* aopOp - allocates an asmop for an operand : */
828 /*-----------------------------------------------------------------*/
829 void aopOp (operand *op, iCode *ic, bool result)
838 /* if this a literal */
839 if (IS_OP_LITERAL(op)) {
840 op->aop = aop = newAsmop(AOP_LIT);
841 aop->aopu.aop_lit = op->operand.valOperand;
842 aop->size = getSize(operandType(op));
847 sym_link *type = operandType(op);
848 if(IS_PTR_CONST(type))
849 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
852 /* if already has a asmop then continue */
856 /* if the underlying symbol has a aop */
857 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
858 DEBUGpic14_emitcode(";","%d",__LINE__);
859 op->aop = OP_SYMBOL(op)->aop;
863 /* if this is a true symbol */
864 if (IS_TRUE_SYMOP(op)) {
865 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
866 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
870 /* this is a temporary : this has
876 e) can be a return use only */
881 /* if the type is a conditional */
882 if (sym->regType == REG_CND) {
883 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
888 /* if it is spilt then two situations
890 b) has a spill location */
891 if (sym->isspilt || sym->nRegs == 0) {
893 DEBUGpic14_emitcode(";","%d",__LINE__);
894 /* rematerialize it NOW */
897 sym->aop = op->aop = aop = aopForRemat (op);
898 aop->size = getSize(sym->type);
899 //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
904 /* WREG is not usable as an ordinary operand with PIC architecture,
905 * one might introduce a scratch register that can be used to make
906 * WREG accesible as an operand... disable WREG for now */
909 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
910 aop->size = getSize(sym->type);
911 for ( i = 0 ; i < 2 ; i++ )
912 aop->aopu.aop_str[i] = accUse[i];
913 DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
919 if(sym->isptr) { // && sym->uptr
920 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
921 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
923 //PCOI(aop->aopu.pcop)->_const = 0;
924 //PCOI(aop->aopu.pcop)->index = 0;
926 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
927 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
929 //allocDirReg (IC_LEFT(ic));
931 aop->size = getSize(sym->type);
932 DEBUGpic14_emitcode(";","%d",__LINE__);
939 aop = op->aop = sym->aop = newAsmop(AOP_STR);
940 aop->size = getSize(sym->type);
941 for ( i = 0 ; i < fReturnSizePic ; i++ )
942 aop->aopu.aop_str[i] = fReturn[i];
944 DEBUGpic14_emitcode(";","%d",__LINE__);
949 /* else spill location */
950 if (sym->usl.spillLoc)
952 asmop *oldAsmOp = NULL;
954 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
956 /* force a new aop if sizes differ */
957 oldAsmOp = sym->usl.spillLoc->aop;
958 sym->usl.spillLoc->aop = NULL;
960 DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
961 __FUNCTION__,__LINE__,
962 sym->usl.spillLoc->rname,
963 sym->rname, sym->usl.spillLoc->offset);
965 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
966 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
968 /* Don't reuse the new aop, go with the last one */
969 sym->usl.spillLoc->aop = oldAsmOp;
971 //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
972 aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname,
974 sym->usl.spillLoc->offset);
975 aop->size = getSize(sym->type);
982 sym_link *type = operandType(op);
983 if(IS_PTR_CONST(type))
984 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
987 /* must be in a register */
988 DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
989 sym->aop = op->aop = aop = newAsmop(AOP_REG);
990 aop->size = sym->nRegs;
991 for ( i = 0 ; i < sym->nRegs ;i++)
992 aop->aopu.aop_reg[i] = sym->regs[i];
995 /*-----------------------------------------------------------------*/
996 /* freeAsmop - free up the asmop given to an operand */
997 /*----------------------------------------------------------------*/
998 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1015 /* depending on the asmop type only three cases need work AOP_RO
1016 , AOP_R1 && AOP_STK */
1018 switch (aop->type) {
1022 pic14_emitcode ("pop","ar0");
1026 bitVectUnSetBit(ic->rUsed,R0_IDX);
1032 pic14_emitcode ("pop","ar1");
1036 bitVectUnSetBit(ic->rUsed,R1_IDX);
1042 int stk = aop->aopu.aop_stk + aop->size;
1043 bitVectUnSetBit(ic->rUsed,R0_IDX);
1044 bitVectUnSetBit(ic->rUsed,R1_IDX);
1046 getFreePtr(ic,&aop,FALSE);
1048 if (options.stack10bit)
1050 /* I'm not sure what to do here yet... */
1053 "*** Warning: probably generating bad code for "
1054 "10 bit stack mode.\n");
1058 pic14_emitcode ("mov","a,_bp");
1059 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1060 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1062 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1066 pic14_emitcode("pop","acc");
1067 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1069 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1072 freeAsmop(op,NULL,ic,TRUE);
1074 pic14_emitcode("pop","ar0");
1079 pic14_emitcode("pop","ar1");
1087 /* all other cases just dealloc */
1091 OP_SYMBOL(op)->aop = NULL;
1092 /* if the symbol has a spill */
1094 SPIL_LOC(op)->aop = NULL;
1099 /*-----------------------------------------------------------------*/
1100 /* aopGet - for fetching value of the aop */
1101 /*-----------------------------------------------------------------*/
1102 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1107 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1108 /* offset is greater than
1110 if (offset > (aop->size - 1) &&
1111 aop->type != AOP_LIT)
1114 /* depending on type */
1115 switch (aop->type) {
1119 DEBUGpic14_emitcode(";","%d",__LINE__);
1120 /* if we need to increment it */
1121 while (offset > aop->coff) {
1122 pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);
1126 while (offset < aop->coff) {
1127 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1131 aop->coff = offset ;
1133 pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1134 return (dname ? "acc" : "a");
1136 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1137 rs = Safe_calloc(1,strlen(s)+1);
1143 DEBUGpic14_emitcode(";","%d",__LINE__);
1144 if (aop->type == AOP_DPTR2)
1149 while (offset > aop->coff) {
1150 pic14_emitcode ("inc","dptr");
1154 while (offset < aop->coff) {
1155 pic14_emitcode("lcall","__decdptr");
1161 pic14_emitcode("clr","a");
1162 pic14_emitcode("movc","a,@a+dptr");
1165 pic14_emitcode("movx","a,@dptr");
1168 if (aop->type == AOP_DPTR2)
1173 return (dname ? "acc" : "a");
1178 sprintf (s,"%s",aop->aopu.aop_immd);
1181 sprintf(s,"(%s >> %d)",
1186 aop->aopu.aop_immd);
1187 DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1188 rs = Safe_calloc(1,strlen(s)+1);
1194 sprintf(s,"(%s + %d)",
1197 DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1199 sprintf(s,"%s",aop->aopu.aop_dir);
1200 rs = Safe_calloc(1,strlen(s)+1);
1206 // return aop->aopu.aop_reg[offset]->dname;
1208 return aop->aopu.aop_reg[offset]->name;
1211 //pic14_emitcode(";","%d",__LINE__);
1212 return aop->aopu.aop_dir;
1215 DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1216 return "AOP_accumulator_bug";
1219 sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1220 rs = Safe_calloc(1,strlen(s)+1);
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
1446 /* XXX: still needed for BIT operands (AOP_CRY) */
1447 if (offset > (aop->size - 1) &&
1448 aop->type != AOP_LIT)
1449 return NULL; //zero;
1451 /* depending on type */
1452 switch (aop->type) {
1459 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1463 DEBUGpic14_emitcode(";","%d",__LINE__);
1464 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1467 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1469 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1470 pcop->type = PO_DIR;
1472 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1473 strcpy(pcop->name,aop->aopu.aop_dir);
1474 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1475 if(PCOR(pcop)->r == NULL) {
1476 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1477 PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1478 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1480 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1482 PCOR(pcop)->instance = offset;
1490 assert (offset < aop->size);
1491 rIdx = aop->aopu.aop_reg[offset]->rIdx;
1493 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1494 PCOR(pcop)->rIdx = rIdx;
1495 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1496 PCOR(pcop)->r->wasUsed=1;
1497 PCOR(pcop)->r->isFree=0;
1499 PCOR(pcop)->instance = offset;
1500 pcop->type = PCOR(pcop)->r->pc_type;
1501 //rs = aop->aopu.aop_reg[offset]->name;
1502 DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1507 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1508 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1509 //if(PCOR(pcop)->r == NULL)
1510 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1514 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1517 DEBUGpic14_emitcode(";","%d %s",__LINE__,aop->aopu.aop_str[offset]);
1518 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1520 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1521 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1522 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1523 pcop->type = PCOR(pcop)->r->pc_type;
1524 pcop->name = PCOR(pcop)->r->name;
1531 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1533 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1534 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1535 switch (aop->aopu.pcop->type)
1538 pcop = pCodeOpCopy (aop->aopu.pcop);
1539 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1540 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1541 PCOI(pcop)->index += offset;
1542 //PCOI(pcop)->offset = 0;
1545 pcop = pCodeOpCopy (aop->aopu.pcop);
1546 PCOR(pcop)->instance = offset;
1549 assert ( !"unhandled pCode type" );
1555 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1556 "popGet got unsupported aop->type");
1560 /*-----------------------------------------------------------------*/
1561 /* popGetAddr - access the low/high word of a symbol (immediate) */
1562 /* (for non-PO_IMMEDIATEs this is the same as popGet) */
1563 /*-----------------------------------------------------------------*/
1564 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1566 if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1568 pCodeOp *pcop = aop->aopu.pcop;
1569 assert (offset <= GPTRSIZE);
1571 /* special case: index >= 2 should return GPOINTER-style values */
1574 pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1578 pcop = pCodeOpCopy (pcop);
1579 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1580 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1581 PCOI(pcop)->offset += offset;
1582 PCOI(pcop)->index += index;
1583 //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);
1586 return popGet (aop, offset + index);
1590 /*-----------------------------------------------------------------*/
1591 /* aopPut - puts a string for a aop */
1592 /*-----------------------------------------------------------------*/
1593 void aopPut (asmop *aop, char *s, int offset)
1598 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1600 if (aop->size && offset > ( aop->size - 1)) {
1601 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1602 "aopPut got offset > aop->size");
1606 /* will assign value to value */
1607 /* depending on where it is ofcourse */
1608 switch (aop->type) {
1611 sprintf(d,"(%s + %d)",
1612 aop->aopu.aop_dir,offset);
1613 fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1616 sprintf(d,"%s",aop->aopu.aop_dir);
1619 DEBUGpic14_emitcode(";","%d",__LINE__);
1621 pic14_emitcode("movf","%s,w",s);
1622 pic14_emitcode("movwf","%s",d);
1625 pic14_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
1626 if(offset >= aop->size) {
1627 emitpcode(POC_CLRF,popGet(aop,offset));
1630 emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
1633 emitpcode(POC_MOVWF,popGet(aop,offset));
1639 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1640 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1643 strcmp(s,"r0") == 0 ||
1644 strcmp(s,"r1") == 0 ||
1645 strcmp(s,"r2") == 0 ||
1646 strcmp(s,"r3") == 0 ||
1647 strcmp(s,"r4") == 0 ||
1648 strcmp(s,"r5") == 0 ||
1649 strcmp(s,"r6") == 0 ||
1650 strcmp(s,"r7") == 0 )
1651 pic14_emitcode("mov","%s,%s ; %d",
1652 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1656 if(strcmp(s,"W")==0 )
1657 pic14_emitcode("movf","%s,w ; %d",s,__LINE__);
1659 pic14_emitcode("movwf","%s",
1660 aop->aopu.aop_reg[offset]->name);
1662 if(strcmp(s,zero)==0) {
1663 emitpcode(POC_CLRF,popGet(aop,offset));
1665 } else if(strcmp(s,"W")==0) {
1666 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1667 pcop->type = PO_GPR_REGISTER;
1669 PCOR(pcop)->rIdx = -1;
1670 PCOR(pcop)->r = NULL;
1672 DEBUGpic14_emitcode(";","%d",__LINE__);
1673 pcop->name = Safe_strdup(s);
1674 emitpcode(POC_MOVFW,pcop);
1675 emitpcode(POC_MOVWF,popGet(aop,offset));
1676 } else if(strcmp(s,one)==0) {
1677 emitpcode(POC_CLRF,popGet(aop,offset));
1678 emitpcode(POC_INCF,popGet(aop,offset));
1680 emitpcode(POC_MOVWF,popGet(aop,offset));
1688 if (aop->type == AOP_DPTR2)
1694 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1695 "aopPut writting to code space");
1699 while (offset > aop->coff) {
1701 pic14_emitcode ("inc","dptr");
1704 while (offset < aop->coff) {
1706 pic14_emitcode("lcall","__decdptr");
1711 /* if not in accumulater */
1714 pic14_emitcode ("movx","@dptr,a");
1716 if (aop->type == AOP_DPTR2)
1724 while (offset > aop->coff) {
1726 pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1728 while (offset < aop->coff) {
1730 pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1736 pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1741 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1743 if (strcmp(s,"r0") == 0 ||
1744 strcmp(s,"r1") == 0 ||
1745 strcmp(s,"r2") == 0 ||
1746 strcmp(s,"r3") == 0 ||
1747 strcmp(s,"r4") == 0 ||
1748 strcmp(s,"r5") == 0 ||
1749 strcmp(s,"r6") == 0 ||
1750 strcmp(s,"r7") == 0 ) {
1752 sprintf(buffer,"a%s",s);
1753 pic14_emitcode("mov","@%s,%s",
1754 aop->aopu.aop_ptr->name,buffer);
1756 pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1761 if (strcmp(s,"a") == 0)
1762 pic14_emitcode("push","acc");
1764 pic14_emitcode("push","%s",s);
1769 /* if bit variable */
1770 if (!aop->aopu.aop_dir) {
1771 pic14_emitcode("clr","a");
1772 pic14_emitcode("rlc","a");
1775 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1778 pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1781 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1783 lbl = newiTempLabel(NULL);
1785 if (strcmp(s,"a")) {
1788 pic14_emitcode("clr","c");
1789 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1790 pic14_emitcode("cpl","c");
1791 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1792 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1799 if (strcmp(aop->aopu.aop_str[offset],s))
1800 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1805 if (!offset && (strcmp(s,"acc") == 0))
1808 if (strcmp(aop->aopu.aop_str[offset],s))
1809 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1813 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1814 "aopPut got unsupported aop->type");
1820 /*-----------------------------------------------------------------*/
1821 /* mov2w_op - generate either a MOVLW or MOVFW based operand type */
1822 /*-----------------------------------------------------------------*/
1823 static void mov2w_op (operand *op, int offset)
1828 /* for PO_IMMEDIATEs: use address or value? */
1829 if (op_isLitLike (op))
1831 /* access address of op */
1832 if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
1833 if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
1835 if (offset == GPTRSIZE-1)
1836 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1838 emitpcode (POC_MOVLW, popGetLit (0));
1841 emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
1843 /* access value stored in op */
1844 mov2w (AOP(op), offset);
1849 /*-----------------------------------------------------------------*/
1850 /* mov2w - generate either a MOVLW or MOVFW based operand type */
1851 /*-----------------------------------------------------------------*/
1852 void mov2w (asmop *aop, int offset)
1858 DEBUGpic14_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
1860 if ( aop_isLitLike (aop) )
1861 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1863 emitpcode(POC_MOVFW,popGet(aop,offset));
1867 static void movwf (asmop *op, int offset)
1869 emitpcode (POC_MOVWF, popGet(op, offset));
1872 static pCodeOp *get_argument_pcop (int idx)
1874 assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1875 return popRegFromIdx (Gstack_base_addr - (idx - 1));
1878 static pCodeOp *get_return_val_pcop (int offset)
1880 assert (offset > 0 && "the most significant byte is returned via WREG");
1881 return popRegFromIdx (Gstack_base_addr - (offset - 1));
1884 static void pass_argument (operand *op, int offset, int idx)
1887 mov2w_op (op, offset);
1889 emitpcode(POC_MOVWF, get_argument_pcop (idx));
1892 static void get_returnvalue (operand *op, int offset, int idx)
1895 emitpcode(POC_MOVFW, get_return_val_pcop (idx));
1896 movwf(AOP(op), offset);
1899 static void call_libraryfunc (char *name)
1901 /* library code might reside in different page... */
1902 emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1903 /* call the library function */
1904 emitpcode (POC_CALL, popGetExternal (name));
1905 /* might return from different page... */
1906 emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1909 /*-----------------------------------------------------------------*/
1910 /* reAdjustPreg - points a register back to where it should */
1911 /*-----------------------------------------------------------------*/
1912 static void reAdjustPreg (asmop *aop)
1916 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1918 if ((size = aop->size) <= 1)
1921 switch (aop->type) {
1925 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1929 if (aop->type == AOP_DPTR2)
1935 pic14_emitcode("lcall","__decdptr");
1938 if (aop->type == AOP_DPTR2)
1951 /*-----------------------------------------------------------------*/
1952 /* opIsGptr: returns non-zero if the passed operand is */
1953 /* a generic pointer type. */
1954 /*-----------------------------------------------------------------*/
1955 static int opIsGptr(operand *op)
1957 sym_link *type = operandType(op);
1959 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1960 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1968 /*-----------------------------------------------------------------*/
1969 /* pic14_getDataSize - get the operand data size */
1970 /*-----------------------------------------------------------------*/
1971 int pic14_getDataSize(operand *op)
1975 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1978 size = getSize(OP_SYM_ETYPE(op));
1980 //return AOP_SIZE(op);
1982 // tsd- in the pic port, the genptr size is 1, so this code here
1983 // fails. ( in the 8051 port, the size was 4).
1985 size = AOP_SIZE(op);
1986 if (IS_GENPTR(OP_SYM_TYPE(op)))
1988 sym_link *type = operandType(op);
1989 if (IS_GENPTR(type))
1991 /* generic pointer; arithmetic operations
1992 * should ignore the high byte (pointer type).
1995 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2002 /*-----------------------------------------------------------------*/
2003 /* pic14_outAcc - output Acc */
2004 /*-----------------------------------------------------------------*/
2005 void pic14_outAcc(operand *result)
2008 DEBUGpic14_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2009 DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
2012 size = pic14_getDataSize(result);
2014 emitpcode(POC_MOVWF,popGet(AOP(result),0));
2017 /* unsigned or positive */
2019 emitpcode(POC_CLRF,popGet(AOP(result),offset++));
2024 /*-----------------------------------------------------------------*/
2025 /* pic14_outBitC - output a bit C */
2026 /*-----------------------------------------------------------------*/
2027 void pic14_outBitC(operand *result)
2030 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2031 /* if the result is bit */
2032 if (AOP_TYPE(result) == AOP_CRY)
2033 aopPut(AOP(result),"c",0);
2035 pic14_emitcode("clr","a ; %d", __LINE__);
2036 pic14_emitcode("rlc","a");
2037 pic14_outAcc(result);
2041 /*-----------------------------------------------------------------*/
2042 /* pic14_toBoolean - emit code for orl a,operator(sizeop) */
2043 /*-----------------------------------------------------------------*/
2044 void pic14_toBoolean(operand *oper)
2046 int size = AOP_SIZE(oper);
2049 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2054 /* MOVFW does not load the flags... */
2055 if (AOP_TYPE(oper) == AOP_ACC) {
2056 emitpcode(POC_IORLW, popGetLit(0));
2059 emitpcode(POC_MOVLW, popGetLit(0));
2063 if ( AOP_TYPE(oper) != AOP_ACC) {
2064 emitpcode(POC_MOVFW,popGet(AOP(oper),0));
2069 while (offset < size) {
2070 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
2072 /* Z is set iff (oper == 0) */
2076 /*-----------------------------------------------------------------*/
2077 /* genNot - generate code for ! operation */
2078 /*-----------------------------------------------------------------*/
2079 static void genNot (iCode *ic)
2086 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2087 /* assign asmOps to operand & result */
2088 aopOp (IC_LEFT(ic),ic,FALSE);
2089 aopOp (IC_RESULT(ic),ic,TRUE);
2091 DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2092 /* if in bit space then a special case */
2093 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2094 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2095 emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
2096 emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
2098 emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
2099 emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
2100 emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
2105 size = AOP_SIZE(IC_LEFT(ic));
2106 mov2w (AOP(IC_LEFT(ic)),0);
2109 if (op_isLitLike (IC_LEFT(ic)))
2110 emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
2112 emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
2114 emitpcode(POC_MOVLW, popGetLit (0));
2116 emitpcode(POC_MOVLW, popGetLit (1));
2117 movwf(AOP(IC_RESULT(ic)), 0);
2119 for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
2121 emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
2126 /* release the aops */
2127 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2128 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2132 /*-----------------------------------------------------------------*/
2133 /* genCpl - generate code for complement */
2134 /*-----------------------------------------------------------------*/
2135 static void genCpl (iCode *ic)
2137 operand *left, *result;
2142 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2143 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2144 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2146 /* if both are in bit space then
2148 if (AOP_TYPE(result) == AOP_CRY &&
2149 AOP_TYPE(left) == AOP_CRY ) {
2151 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir);
2152 pic14_emitcode("cpl","c");
2153 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir);
2157 size = AOP_SIZE(result);
2158 if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
2161 if(AOP_TYPE(left) == AOP_ACC)
2162 emitpcode(POC_XORLW, popGetLit(0xff));
2164 emitpcode(POC_COMFW,popGet(AOP(left),offset));
2166 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
2169 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2173 /* release the aops */
2174 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2175 freeAsmop(result,NULL,ic,TRUE);
2178 /*-----------------------------------------------------------------*/
2179 /* genUminusFloat - unary minus for floating points */
2180 /*-----------------------------------------------------------------*/
2181 static void genUminusFloat(operand *op,operand *result)
2183 int size ,offset =0 ;
2188 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2189 /* for this we just need to flip the
2190 first it then copy the rest in place */
2191 size = AOP_SIZE(op) - 1;
2192 l = aopGet(AOP(op),3,FALSE,FALSE);
2196 pic14_emitcode("cpl","acc.7");
2197 aopPut(AOP(result),"a",3);
2201 aopGet(AOP(op),offset,FALSE,FALSE),
2207 /*-----------------------------------------------------------------*/
2208 /* genUminus - unary minus code generation */
2209 /*-----------------------------------------------------------------*/
2210 static void genUminus (iCode *ic)
2213 sym_link *optype, *rtype;
2217 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2219 aopOp(IC_LEFT(ic),ic,FALSE);
2220 aopOp(IC_RESULT(ic),ic,TRUE);
2222 /* if both in bit space then special
2224 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2225 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2227 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0));
2228 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2229 emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0));
2234 optype = operandType(IC_LEFT(ic));
2235 rtype = operandType(IC_RESULT(ic));
2237 /* if float then do float stuff */
2238 if (IS_FLOAT(optype)) {
2239 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2243 /* otherwise subtract from zero by taking the 2's complement */
2244 size = AOP_SIZE(IC_LEFT(ic));
2246 for(i=0; i<size; i++) {
2247 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2248 emitpcode(POC_COMF, popGet(AOP(IC_LEFT(ic)),i));
2250 emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2251 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2255 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0));
2256 for(i=1; i<size; i++) {
2258 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),i));
2262 /* release the aops */
2263 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2264 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2267 /*-----------------------------------------------------------------*/
2268 /* saveRegisters - will look for a call and save the registers */
2269 /*-----------------------------------------------------------------*/
2270 static void saveRegisters(iCode *lic)
2279 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2281 for (ic = lic ; ic ; ic = ic->next)
2282 if (ic->op == CALL || ic->op == PCALL)
2286 fprintf(stderr,"found parameter push with no function call\n");
2290 /* if the registers have been saved already then
2292 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2295 /* find the registers in use at this time
2296 and push them away to safety */
2297 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2301 if (options.useXstack) {
2302 if (bitVectBitValue(rsave,R0_IDX))
2303 pic14_emitcode("mov","b,r0");
2304 pic14_emitcode("mov","r0,%s",spname);
2305 for (i = 0 ; i < pic14_nRegs ; i++) {
2306 if (bitVectBitValue(rsave,i)) {
2308 pic14_emitcode("mov","a,b");
2310 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2311 pic14_emitcode("movx","@r0,a");
2312 pic14_emitcode("inc","r0");
2315 pic14_emitcode("mov","%s,r0",spname);
2316 if (bitVectBitValue(rsave,R0_IDX))
2317 pic14_emitcode("mov","r0,b");
2319 //for (i = 0 ; i < pic14_nRegs ; i++) {
2320 // if (bitVectBitValue(rsave,i))
2321 // pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2324 dtype = operandType(IC_LEFT(ic));
2325 if (currFunc && dtype &&
2326 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2327 IFFUNC_ISISR(currFunc->type) &&
2330 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2333 /*-----------------------------------------------------------------*/
2334 /* unsaveRegisters - pop the pushed registers */
2335 /*-----------------------------------------------------------------*/
2336 static void unsaveRegisters (iCode *ic)
2343 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2344 /* find the registers in use at this time
2345 and push them away to safety */
2346 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2349 if (options.useXstack) {
2350 pic14_emitcode("mov","r0,%s",spname);
2351 for (i = pic14_nRegs ; i >= 0 ; i--) {
2352 if (bitVectBitValue(rsave,i)) {
2353 pic14_emitcode("dec","r0");
2354 pic14_emitcode("movx","a,@r0");
2356 pic14_emitcode("mov","b,a");
2358 pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2362 pic14_emitcode("mov","%s,r0",spname);
2363 if (bitVectBitValue(rsave,R0_IDX))
2364 pic14_emitcode("mov","r0,b");
2366 //for (i = pic14_nRegs ; i >= 0 ; i--) {
2367 // if (bitVectBitValue(rsave,i))
2368 // pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2374 /*-----------------------------------------------------------------*/
2376 /*-----------------------------------------------------------------*/
2377 static void pushSide(operand * oper, int size)
2381 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2383 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2384 if (AOP_TYPE(oper) != AOP_REG &&
2385 AOP_TYPE(oper) != AOP_DIR &&
2387 pic14_emitcode("mov","a,%s",l);
2388 pic14_emitcode("push","acc");
2390 pic14_emitcode("push","%s",l);
2395 /*-----------------------------------------------------------------*/
2396 /* assignResultValue - */
2397 /*-----------------------------------------------------------------*/
2398 static void assignResultValue(operand * oper)
2400 int size = AOP_SIZE(oper);
2405 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2407 DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2409 /* assign MSB first (passed via WREG) */
2411 get_returnvalue (oper, size, offset + GpsuedoStkPtr);
2417 /*-----------------------------------------------------------------*/
2418 /* genIpush - genrate code for pushing this gets a little complex */
2419 /*-----------------------------------------------------------------*/
2420 static void genIpush (iCode *ic)
2424 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2426 int size, offset = 0 ;
2430 /* if this is not a parm push : ie. it is spill push
2431 and spill push is always done on the local stack */
2432 if (!ic->parmPush) {
2434 /* and the item is spilt then do nothing */
2435 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2438 aopOp(IC_LEFT(ic),ic,FALSE);
2439 size = AOP_SIZE(IC_LEFT(ic));
2440 /* push it on the stack */
2442 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2447 pic14_emitcode("push","%s",l);
2452 /* this is a paramter push: in this case we call
2453 the routine to find the call and save those
2454 registers that need to be saved */
2457 /* then do the push */
2458 aopOp(IC_LEFT(ic),ic,FALSE);
2461 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2462 size = AOP_SIZE(IC_LEFT(ic));
2465 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2466 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
2467 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2469 pic14_emitcode("mov","a,%s",l);
2470 pic14_emitcode("push","acc");
2472 pic14_emitcode("push","%s",l);
2475 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2479 /*-----------------------------------------------------------------*/
2480 /* genIpop - recover the registers: can happen only for spilling */
2481 /*-----------------------------------------------------------------*/
2482 static void genIpop (iCode *ic)
2486 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2487 assert (!"genIpop -- unimplemented");
2492 /* if the temp was not pushed then */
2493 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2496 aopOp(IC_LEFT(ic),ic,FALSE);
2497 size = AOP_SIZE(IC_LEFT(ic));
2500 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2503 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2507 /*-----------------------------------------------------------------*/
2508 /* unsaverbank - restores the resgister bank from stack */
2509 /*-----------------------------------------------------------------*/
2510 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2514 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2520 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2522 if (options.useXstack) {
2524 r = getFreePtr(ic,&aop,FALSE);
2527 pic14_emitcode("mov","%s,_spx",r->name);
2528 pic14_emitcode("movx","a,@%s",r->name);
2529 pic14_emitcode("mov","psw,a");
2530 pic14_emitcode("dec","%s",r->name);
2533 pic14_emitcode ("pop","psw");
2536 for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2537 if (options.useXstack) {
2538 pic14_emitcode("movx","a,@%s",r->name);
2539 //pic14_emitcode("mov","(%s+%d),a",
2540 // regspic14[i].base,8*bank+regspic14[i].offset);
2541 pic14_emitcode("dec","%s",r->name);
2544 pic14_emitcode("pop",""); //"(%s+%d)",
2545 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2548 if (options.useXstack) {
2550 pic14_emitcode("mov","_spx,%s",r->name);
2551 freeAsmop(NULL,aop,ic,TRUE);
2557 /*-----------------------------------------------------------------*/
2558 /* saverbank - saves an entire register bank on the stack */
2559 /*-----------------------------------------------------------------*/
2560 static void saverbank (int bank, iCode *ic, bool pushPsw)
2564 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2570 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2571 if (options.useXstack) {
2574 r = getFreePtr(ic,&aop,FALSE);
2575 pic14_emitcode("mov","%s,_spx",r->name);
2579 for (i = 0 ; i < pic14_nRegs ;i++) {
2580 if (options.useXstack) {
2581 pic14_emitcode("inc","%s",r->name);
2582 //pic14_emitcode("mov","a,(%s+%d)",
2583 // regspic14[i].base,8*bank+regspic14[i].offset);
2584 pic14_emitcode("movx","@%s,a",r->name);
2586 pic14_emitcode("push","");// "(%s+%d)",
2587 //regspic14[i].base,8*bank+regspic14[i].offset);
2591 if (options.useXstack) {
2592 pic14_emitcode("mov","a,psw");
2593 pic14_emitcode("movx","@%s,a",r->name);
2594 pic14_emitcode("inc","%s",r->name);
2595 pic14_emitcode("mov","_spx,%s",r->name);
2596 freeAsmop (NULL,aop,ic,TRUE);
2599 pic14_emitcode("push","psw");
2601 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2607 /*-----------------------------------------------------------------*/
2608 /* genCall - generates a call statement */
2609 /*-----------------------------------------------------------------*/
2610 static void genCall (iCode *ic)
2619 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2621 /* if caller saves & we have not saved then */
2625 /* if we are calling a function that is not using
2626 the same register bank then we need to save the
2627 destination registers on the stack */
2628 dtype = operandType(IC_LEFT(ic));
2629 if (currFunc && dtype &&
2630 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2631 IFFUNC_ISISR(currFunc->type) &&
2634 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2636 /* if send set is not empty the assign */
2639 /* For the Pic port, there is no data stack.
2640 * So parameters passed to functions are stored
2641 * in registers. (The pCode optimizer will get
2642 * rid of most of these :).
2644 int psuedoStkPtr=-1;
2645 int firstTimeThruLoop = 1;
2647 _G.sendSet = reverseSet(_G.sendSet);
2649 /* First figure how many parameters are getting passed */
2650 for (sic = setFirstItem(_G.sendSet) ; sic ;
2651 sic = setNextItem(_G.sendSet)) {
2653 aopOp(IC_LEFT(sic),sic,FALSE);
2654 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2655 freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2658 for (sic = setFirstItem(_G.sendSet) ; sic ;
2659 sic = setNextItem(_G.sendSet)) {
2660 int size, offset = 0;
2662 aopOp(IC_LEFT(sic),sic,FALSE);
2663 size = AOP_SIZE(IC_LEFT(sic));
2666 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2667 AopType(AOP_TYPE(IC_LEFT(sic))));
2669 if(!firstTimeThruLoop) {
2670 /* If this is not the first time we've been through the loop
2671 * then we need to save the parameter in a temporary
2672 * register. The last byte of the last parameter is
2674 emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2677 firstTimeThruLoop=0;
2679 mov2w_op (IC_LEFT(sic), offset);
2682 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2687 sym = OP_SYMBOL(IC_LEFT(ic));
2688 name = sym->rname[0] ? sym->rname : sym->name;
2689 isExtern = IS_EXTERN(sym->etype);
2691 emitpcode(POC_PAGESEL,popGetWithString(name,1)); /* Extern functions maybe on another page - must call pagesel */
2693 emitpcode(POC_CALL,popGetWithString(name,isExtern));
2695 emitpcode(POC_PAGESEL,popGetWithString("$",0)); /* May have returned from another page - must call pagesel to restore PCLATH before next goto or call instruction */
2698 /* if we need assign a result value */
2699 if ((IS_ITEMP(IC_RESULT(ic)) &&
2700 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2701 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2702 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2705 aopOp(IC_RESULT(ic),ic,FALSE);
2708 assignResultValue(IC_RESULT(ic));
2710 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2711 AopType(AOP_TYPE(IC_RESULT(ic))));
2713 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2716 /* if register bank was saved then pop them */
2718 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2720 /* if we hade saved some registers then unsave them */
2721 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2722 unsaveRegisters (ic);
2727 /*-----------------------------------------------------------------*/
2728 /* genPcall - generates a call by pointer statement */
2729 /*-----------------------------------------------------------------*/
2730 static void genPcall (iCode *ic)
2733 symbol *albl = newiTempLabel(NULL);
2734 symbol *blbl = newiTempLabel(NULL);
2741 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2742 /* if caller saves & we have not saved then */
2746 /* if we are calling a function that is not using
2747 the same register bank then we need to save the
2748 destination registers on the stack */
2749 dtype = operandType(IC_LEFT(ic));
2750 if (currFunc && dtype &&
2751 IFFUNC_ISISR(currFunc->type) &&
2752 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2753 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2756 aopOp(left,ic,FALSE);
2757 DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2759 poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2761 pushSide(IC_LEFT(ic), FPTRSIZE);
2763 /* if send set is not empty, assign parameters */
2766 DEBUGpic14_emitcode ("; ***","%s %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2767 /* no way to pass args - W always gets used to make the call */
2769 /* first idea - factor out a common helper function and call it.
2770 But don't know how to get it generated only once in its own block
2772 if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2775 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2776 DEBUGpic14_emitcode ("; ***","%s %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2777 buffer = Safe_calloc(1,strlen(rname)+16);
2778 sprintf(buffer, "%s_goto_helper", rname);
2779 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2783 emitpcode(POC_CALL,popGetLabel(albl->key));
2784 pcop = popGetLabel(blbl->key);
2785 emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
2786 emitpcode(POC_GOTO,pcop);
2787 emitpLabel(albl->key);
2789 emitpcode(poc,popGetAddr(AOP(left),1,0));
2790 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2791 emitpcode(poc,popGetAddr(AOP(left),0,0));
2792 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2794 emitpLabel(blbl->key);
2796 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2798 /* if we need to assign a result value */
2799 if ((IS_ITEMP(IC_RESULT(ic)) &&
2800 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2801 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2802 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2805 aopOp(IC_RESULT(ic),ic,FALSE);
2810 assignResultValue(IC_RESULT(ic));
2812 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2815 /* if register bank was saved then unsave them */
2816 if (currFunc && dtype &&
2817 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2818 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2820 /* if we hade saved some registers then
2823 unsaveRegisters (ic);
2827 /*-----------------------------------------------------------------*/
2828 /* resultRemat - result is rematerializable */
2829 /*-----------------------------------------------------------------*/
2830 static int resultRemat (iCode *ic)
2832 // DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2835 if (SKIP_IC(ic) || ic->op == IFX)
2838 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2839 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2840 if (sym->remat && !POINTER_SET(ic))
2847 #if defined(__BORLANDC__) || defined(_MSC_VER)
2848 #define STRCASECMP stricmp
2850 #define STRCASECMP strcasecmp
2854 /*-----------------------------------------------------------------*/
2855 /* inExcludeList - return 1 if the string is in exclude Reg list */
2856 /*-----------------------------------------------------------------*/
2857 static bool inExcludeList(char *s)
2859 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2862 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2863 if (options.excludeRegs[i] &&
2864 STRCASECMP(options.excludeRegs[i],"none") == 0)
2867 for ( i = 0 ; options.excludeRegs[i]; i++) {
2868 if (options.excludeRegs[i] &&
2869 STRCASECMP(s,options.excludeRegs[i]) == 0)
2876 /*-----------------------------------------------------------------*/
2877 /* genFunction - generated code for function entry */
2878 /*-----------------------------------------------------------------*/
2879 static void genFunction (iCode *ic)
2886 DEBUGpic14_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2888 labelOffset += (max_key+4);
2892 /* create the function header */
2893 pic14_emitcode(";","-----------------------------------------");
2894 pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2895 pic14_emitcode(";","-----------------------------------------");
2897 pic14_emitcode("","%s:",sym->rname);
2898 addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2900 ftype = operandType(IC_LEFT(ic));
2902 /* if critical function then turn interrupts off */
2903 if (IFFUNC_ISCRITICAL(ftype))
2904 pic14_emitcode("clr","ea");
2906 /* here we need to generate the equates for the
2907 register bank if required */
2909 if (FUNC_REGBANK(ftype) != rbank) {
2912 rbank = FUNC_REGBANK(ftype);
2913 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2914 if (strcmp(regspic14[i].base,"0") == 0)
2915 pic14_emitcode("","%s = 0x%02x",
2917 8*rbank+regspic14[i].offset);
2919 pic14_emitcode ("","%s = %s + 0x%02x",
2922 8*rbank+regspic14[i].offset);
2927 /* if this is an interrupt service routine */
2928 if (IFFUNC_ISISR(sym->type)) {
2929 /* already done in pic14createInterruptVect() - delete me
2930 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2931 emitpcodeNULLop(POC_NOP);
2932 emitpcodeNULLop(POC_NOP);
2933 emitpcodeNULLop(POC_NOP);
2935 emitpcode(POC_MOVWF, popCopyReg(&pc_wsave));
2936 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2937 emitpcode(POC_CLRF, popCopyReg(&pc_status));
2938 emitpcode(POC_MOVWF, popCopyReg(&pc_ssave));
2939 emitpcode(POC_MOVFW, popCopyReg(&pc_pclath));
2940 emitpcode(POC_MOVWF, popCopyReg(&pc_psave));
2941 emitpcode(POC_CLRF, popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2943 pBlockConvert2ISR(pb);
2944 pic14_hasInterrupt = 1;
2946 if (!inExcludeList("acc"))
2947 pic14_emitcode ("push","acc");
2948 if (!inExcludeList("b"))
2949 pic14_emitcode ("push","b");
2950 if (!inExcludeList("dpl"))
2951 pic14_emitcode ("push","dpl");
2952 if (!inExcludeList("dph"))
2953 pic14_emitcode ("push","dph");
2954 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2956 pic14_emitcode ("push", "dpx");
2957 /* Make sure we're using standard DPTR */
2958 pic14_emitcode ("push", "dps");
2959 pic14_emitcode ("mov", "dps, #0x00");
2960 if (options.stack10bit)
2962 /* This ISR could conceivably use DPTR2. Better save it. */
2963 pic14_emitcode ("push", "dpl1");
2964 pic14_emitcode ("push", "dph1");
2965 pic14_emitcode ("push", "dpx1");
2968 /* if this isr has no bank i.e. is going to
2969 run with bank 0 , then we need to save more
2971 if (!FUNC_REGBANK(sym->type)) {
2973 /* if this function does not call any other
2974 function then we can be economical and
2975 save only those registers that are used */
2976 if (! IFFUNC_HASFCALL(sym->type)) {
2979 /* if any registers used */
2980 if (sym->regsUsed) {
2981 /* save the registers used */
2982 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2983 if (bitVectBitValue(sym->regsUsed,i) ||
2984 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2985 pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);
2990 /* this function has a function call cannot
2991 determines register usage so we will have the
2993 saverbank(0,ic,FALSE);
2998 /* if callee-save to be used for this function
2999 then save the registers being used in this function */
3000 if (IFFUNC_CALLEESAVES(sym->type)) {
3003 /* if any registers used */
3004 if (sym->regsUsed) {
3005 /* save the registers used */
3006 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3007 if (bitVectBitValue(sym->regsUsed,i) ||
3008 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
3009 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
3017 /* set the register bank to the desired value */
3018 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
3019 pic14_emitcode("push","psw");
3020 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);
3023 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3025 if (options.useXstack) {
3026 pic14_emitcode("mov","r0,%s",spname);
3027 pic14_emitcode("mov","a,_bp");
3028 pic14_emitcode("movx","@r0,a");
3029 pic14_emitcode("inc","%s",spname);
3033 /* set up the stack */
3034 pic14_emitcode ("push","_bp"); /* save the callers stack */
3036 pic14_emitcode ("mov","_bp,%s",spname);
3039 /* adjust the stack for the function */
3044 werror(W_STACK_OVERFLOW,sym->name);
3046 if (i > 3 && sym->recvSize < 4) {
3048 pic14_emitcode ("mov","a,sp");
3049 pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3050 pic14_emitcode ("mov","sp,a");
3055 pic14_emitcode("inc","sp");
3060 pic14_emitcode ("mov","a,_spx");
3061 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3062 pic14_emitcode ("mov","_spx,a");
3067 /*-----------------------------------------------------------------*/
3068 /* genEndFunction - generates epilogue for functions */
3069 /*-----------------------------------------------------------------*/
3070 static void genEndFunction (iCode *ic)
3072 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3076 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3078 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3080 pic14_emitcode ("mov","%s,_bp",spname);
3083 /* if use external stack but some variables were
3084 added to the local stack then decrement the
3086 if (options.useXstack && sym->stack) {
3087 pic14_emitcode("mov","a,sp");
3088 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3089 pic14_emitcode("mov","sp,a");
3093 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3094 if (options.useXstack) {
3095 pic14_emitcode("mov","r0,%s",spname);
3096 pic14_emitcode("movx","a,@r0");
3097 pic14_emitcode("mov","_bp,a");
3098 pic14_emitcode("dec","%s",spname);
3102 pic14_emitcode ("pop","_bp");
3106 /* restore the register bank */
3107 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3108 pic14_emitcode ("pop","psw");
3110 if (IFFUNC_ISISR(sym->type)) {
3112 /* now we need to restore the registers */
3113 /* if this isr has no bank i.e. is going to
3114 run with bank 0 , then we need to save more
3116 if (!FUNC_REGBANK(sym->type)) {
3118 /* if this function does not call any other
3119 function then we can be economical and
3120 save only those registers that are used */
3121 if (! IFFUNC_HASFCALL(sym->type)) {
3124 /* if any registers used */
3125 if (sym->regsUsed) {
3126 /* save the registers used */
3127 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3128 if (bitVectBitValue(sym->regsUsed,i) ||
3129 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3130 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3135 /* this function has a function call cannot
3136 determines register usage so we will have the
3138 unsaverbank(0,ic,FALSE);
3142 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3144 if (options.stack10bit)
3146 pic14_emitcode ("pop", "dpx1");
3147 pic14_emitcode ("pop", "dph1");
3148 pic14_emitcode ("pop", "dpl1");
3150 pic14_emitcode ("pop", "dps");
3151 pic14_emitcode ("pop", "dpx");
3153 if (!inExcludeList("dph"))
3154 pic14_emitcode ("pop","dph");
3155 if (!inExcludeList("dpl"))
3156 pic14_emitcode ("pop","dpl");
3157 if (!inExcludeList("b"))
3158 pic14_emitcode ("pop","b");
3159 if (!inExcludeList("acc"))
3160 pic14_emitcode ("pop","acc");
3162 if (IFFUNC_ISCRITICAL(sym->type))
3163 pic14_emitcode("setb","ea");
3166 /* if debug then send end of function */
3167 /* if (options.debug && currFunc) { */
3169 debugFile->writeEndFunction (currFunc, ic, 1);
3172 pic14_emitcode ("reti","");
3173 emitpcode(POC_MOVFW, popCopyReg(&pc_psave));
3174 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
3175 emitpcode(POC_CLRF, popCopyReg(&pc_status));
3176 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3177 emitpcode(POC_MOVWF, popCopyReg(&pc_status));
3178 emitpcode(POC_SWAPF, popCopyReg(&pc_wsave));
3179 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3180 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3181 emitpcodeNULLop(POC_RETFIE);
3184 if (IFFUNC_ISCRITICAL(sym->type))
3185 pic14_emitcode("setb","ea");
3187 if (IFFUNC_CALLEESAVES(sym->type)) {
3190 /* if any registers used */
3191 if (sym->regsUsed) {
3192 /* save the registers used */
3193 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3194 if (bitVectBitValue(sym->regsUsed,i) ||
3195 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3196 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3202 /* if debug then send end of function */
3204 debugFile->writeEndFunction (currFunc, ic, 1);
3207 pic14_emitcode ("return","");
3208 emitpcodeNULLop(POC_RETURN);
3210 /* Mark the end of a function */
3211 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3216 /*-----------------------------------------------------------------*/
3217 /* genRet - generate code for return statement */
3218 /*-----------------------------------------------------------------*/
3219 static void genRet (iCode *ic)
3221 int size,offset = 0;
3225 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3226 /* if we have no return value then
3227 just generate the "ret" */
3231 /* we have something to return then
3232 move the return value into place */
3233 aopOp(IC_LEFT(ic),ic,FALSE);
3234 size = AOP_SIZE(IC_LEFT(ic));
3236 for (offset = 0; offset < size; offset++)
3238 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
3241 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3244 /* generate a jump to the return label
3245 if the next is not the return statement */
3246 if (!(ic->next && ic->next->op == LABEL &&
3247 IC_LABEL(ic->next) == returnLabel)) {
3249 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3254 /*-----------------------------------------------------------------*/
3255 /* genLabel - generates a label */
3256 /*-----------------------------------------------------------------*/
3257 static void genLabel (iCode *ic)
3261 /* special case never generate */
3262 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3263 if (IC_LABEL(ic) == entryLabel)
3266 emitpLabel(IC_LABEL(ic)->key);
3267 pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3270 /*-----------------------------------------------------------------*/
3271 /* genGoto - generates a goto */
3272 /*-----------------------------------------------------------------*/
3274 static void genGoto (iCode *ic)
3278 emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3279 pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3283 /*-----------------------------------------------------------------*/
3284 /* genMultbits :- multiplication of bits */
3285 /*-----------------------------------------------------------------*/
3286 static void genMultbits (operand *left,
3291 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3293 if(!pic14_sameRegs(AOP(result),AOP(right)))
3294 emitpcode(POC_BSF, popGet(AOP(result),0));
3296 emitpcode(POC_BTFSC,popGet(AOP(right),0));
3297 emitpcode(POC_BTFSS,popGet(AOP(left),0));
3298 emitpcode(POC_BCF, popGet(AOP(result),0));
3303 /*-----------------------------------------------------------------*/
3304 /* genMultOneByte : 8 bit multiplication & division */
3305 /*-----------------------------------------------------------------*/
3306 static void genMultOneByte (operand *left,
3310 char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
3318 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3319 DEBUGpic14_AopType(__LINE__,left,right,result);
3320 DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3322 /* (if two literals, the value is computed before) */
3323 /* if one literal, literal on the right */
3324 if (AOP_TYPE(left) == AOP_LIT){
3330 assert (AOP_SIZE(left) == AOP_SIZE(right));
3332 size = min(AOP_SIZE(result),AOP_SIZE(left));
3333 offset = Gstack_base_addr - (2*size - 1);
3335 /* pass right operand as argument */
3336 for (i=0; i < size; i++)
3338 mov2w (AOP(right), i);
3339 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3342 /* pass left operand as argument */
3343 for (i=0; i < size; i++)
3345 mov2w (AOP(left), i);
3346 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3348 assert (offset == Gstack_base_addr);
3350 /* call library routine */
3351 assert (size > 0 && size <= 4);
3352 call_libraryfunc (func[size]);
3355 movwf (AOP(result), size-1);
3356 for (i=0; i < size - 1; i++)
3358 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
3359 movwf (AOP(result), size - 2 - i);
3362 /* now (zero-/sign) extend the result to its size */
3363 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
3366 /*-----------------------------------------------------------------*/
3367 /* genMult - generates code for multiplication */
3368 /*-----------------------------------------------------------------*/
3369 static void genMult (iCode *ic)
3371 operand *left = IC_LEFT(ic);
3372 operand *right = IC_RIGHT(ic);
3373 operand *result= IC_RESULT(ic);
3377 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3378 /* assign the amsops */
3379 aopOp (left,ic,FALSE);
3380 aopOp (right,ic,FALSE);
3381 aopOp (result,ic,TRUE);
3383 DEBUGpic14_AopType(__LINE__,left,right,result);
3385 /* special cases first */
3387 if (AOP_TYPE(left) == AOP_CRY &&
3388 AOP_TYPE(right)== AOP_CRY) {
3389 genMultbits(left,right,result);
3393 /* if both are of size == 1 */
3394 if (AOP_SIZE(left) == 1 &&
3395 AOP_SIZE(right) == 1 ) {
3396 genMultOneByte(left,right,result);
3400 /* should have been converted to function call */
3404 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3405 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3406 freeAsmop(result,NULL,ic,TRUE);
3409 /*-----------------------------------------------------------------*/
3410 /* genDivbits :- division of bits */
3411 /*-----------------------------------------------------------------*/
3412 static void genDivbits (operand *left,
3421 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3422 /* the result must be bit */
3423 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3424 l = aopGet(AOP(left),0,FALSE,FALSE);
3428 pic14_emitcode("div","ab");
3429 pic14_emitcode("rrc","a");
3430 aopPut(AOP(result),"c",0);
3433 /*-----------------------------------------------------------------*/
3434 /* genDivOneByte : 8 bit division */
3435 /*-----------------------------------------------------------------*/
3436 static void genDivOneByte (operand *left,
3443 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3445 assert (AOP_SIZE(result) == 1);
3446 assert (AOP_SIZE(right) == 1);
3447 assert (AOP_SIZE(left) == 1);
3449 size = min(AOP_SIZE(result),AOP_SIZE(left));
3451 if (AOP_TYPE(right) == AOP_LIT)
3453 /* XXX: might add specialized code */
3456 if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3458 /* unsigned division */
3460 mov2w(AOP(right),0);
3461 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3463 call_libraryfunc("__divuchar");
3464 movwf(AOP(result),0);
3469 temp = popGetTempReg();
3470 lbl = newiTempLabel(NULL);
3472 /* XXX: improve this naive approach:
3473 [result] = [a] / [b]
3474 ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
3478 movwf temp // temp <-- left
3479 movf right,W // W <-- right
3483 subwf temp,F // temp <-- temp - W
3484 skipNC // subwf clears CARRY (i.e. sets BORROW) if temp < W
3486 decf result // we just subtract once too often
3489 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3490 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
3493 emitpcode(POC_MOVWF, temp);
3494 mov2w(AOP(right),0);
3495 emitpcode(POC_CLRF, popGet(AOP(result),0));
3497 emitpLabel(lbl->key);
3498 emitpcode(POC_INCF, popGet(AOP(result),0));
3499 emitpcode(POC_SUBWF, temp);
3501 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3502 emitpcode(POC_DECF, popGet(AOP(result),0));
3507 /* signed division */
3508 mov2w(AOP(right),0);
3509 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3511 call_libraryfunc("__divschar");
3512 movwf(AOP(result),0);
3515 /* now performed the signed/unsigned division -- extend result */
3516 addSign(result, 1, !SPEC_USIGN(operandType(result)));
3519 /*-----------------------------------------------------------------*/
3520 /* genDiv - generates code for division */
3521 /*-----------------------------------------------------------------*/
3522 static void genDiv (iCode *ic)
3524 operand *left = IC_LEFT(ic);
3525 operand *right = IC_RIGHT(ic);
3526 operand *result= IC_RESULT(ic);
3529 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3530 /* assign the amsops */
3531 aopOp (left,ic,FALSE);
3532 aopOp (right,ic,FALSE);
3533 aopOp (result,ic,TRUE);
3535 /* special cases first */
3537 if (AOP_TYPE(left) == AOP_CRY &&
3538 AOP_TYPE(right)== AOP_CRY) {
3539 genDivbits(left,right,result);
3543 /* if both are of size == 1 */
3544 if (AOP_SIZE(left) == 1 &&
3545 AOP_SIZE(right) == 1 ) {
3546 genDivOneByte(left,right,result);
3550 /* should have been converted to function call */
3553 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3554 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3555 freeAsmop(result,NULL,ic,TRUE);
3558 /*-----------------------------------------------------------------*/
3559 /* genModbits :- modulus of bits */
3560 /*-----------------------------------------------------------------*/
3561 static void genModbits (operand *left,
3569 /* the result must be bit */
3570 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3571 l = aopGet(AOP(left),0,FALSE,FALSE);
3575 pic14_emitcode("div","ab");
3576 pic14_emitcode("mov","a,b");
3577 pic14_emitcode("rrc","a");
3578 aopPut(AOP(result),"c",0);
3581 /*-----------------------------------------------------------------*/
3582 /* genModOneByte : 8 bit modulus */
3583 /*-----------------------------------------------------------------*/
3584 static void genModOneByte (operand *left,
3591 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3593 assert (AOP_SIZE(result) == 1);
3594 assert (AOP_SIZE(right) == 1);
3595 assert (AOP_SIZE(left) == 1);
3597 size = min(AOP_SIZE(result),AOP_SIZE(left));
3599 if (AOP_TYPE(right) == AOP_LIT)
3601 /* XXX: might add specialized code */
3604 if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3606 /* unsigned division */
3608 mov2w(AOP(right),0);
3609 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3611 call_libraryfunc("__moduchar");
3612 movwf(AOP(result),0);
3617 lbl = newiTempLabel(NULL);
3619 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3621 /* XXX: improve this naive approach:
3622 [result] = [a] % [b]
3623 ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3627 movwf result // result <-- left
3628 movf right,W // W <-- right
3630 subwf result,F // result <-- result - W
3631 skipNC // subwf clears CARRY (i.e. sets BORROW) if result < W
3633 addwf result, F // we just subtract once too often
3636 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3637 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3639 if (!pic14_sameRegs(AOP(left), AOP(result)))
3642 emitpcode(POC_MOVWF, popGet(AOP(result),0));
3644 mov2w(AOP(right),0);
3646 emitpLabel(lbl->key);
3647 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3649 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3650 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3655 /* signed division */
3656 mov2w(AOP(right),0);
3657 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3659 call_libraryfunc("__modschar");
3660 movwf(AOP(result),0);
3663 /* now we performed the signed/unsigned modulus -- extend result */
3664 addSign(result, 1, !SPEC_USIGN(operandType(result)));
3667 /*-----------------------------------------------------------------*/
3668 /* genMod - generates code for division */
3669 /*-----------------------------------------------------------------*/
3670 static void genMod (iCode *ic)
3672 operand *left = IC_LEFT(ic);
3673 operand *right = IC_RIGHT(ic);
3674 operand *result= IC_RESULT(ic);
3677 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3678 /* assign the amsops */
3679 aopOp (left,ic,FALSE);
3680 aopOp (right,ic,FALSE);
3681 aopOp (result,ic,TRUE);
3683 /* special cases first */
3685 if (AOP_TYPE(left) == AOP_CRY &&
3686 AOP_TYPE(right)== AOP_CRY) {
3687 genModbits(left,right,result);
3691 /* if both are of size == 1 */
3692 if (AOP_SIZE(left) == 1 &&
3693 AOP_SIZE(right) == 1 ) {
3694 genModOneByte(left,right,result);
3698 /* should have been converted to function call */
3702 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3703 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3704 freeAsmop(result,NULL,ic,TRUE);
3707 /*-----------------------------------------------------------------*/
3708 /* genIfxJump :- will create a jump depending on the ifx */
3709 /*-----------------------------------------------------------------*/
3711 note: May need to add parameter to indicate when a variable is in bit space.
3713 static void genIfxJump (iCode *ic, char *jval)
3717 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3718 /* if true label then we jump if condition
3720 if ( IC_TRUE(ic) ) {
3722 if(strcmp(jval,"a") == 0)
3724 else if (strcmp(jval,"c") == 0)
3727 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3728 emitpcode(POC_BTFSC, newpCodeOpBit(jval,-1,1));
3731 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3732 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3736 /* false label is present */
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_BTFSS, newpCodeOpBit(jval,-1,1));
3746 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3747 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3752 /* mark the icode as generated */
3757 /*-----------------------------------------------------------------*/
3759 /*-----------------------------------------------------------------*/
3760 static void genSkip(iCode *ifx,int status_bit)
3766 if ( IC_TRUE(ifx) ) {
3767 switch(status_bit) {
3782 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3783 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3787 switch(status_bit) {
3801 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3802 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3809 /*-----------------------------------------------------------------*/
3811 /*-----------------------------------------------------------------*/
3812 static void genSkipc(resolvedIfx *rifx)
3823 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3824 emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3825 rifx->generated = 1;
3829 /*-----------------------------------------------------------------*/
3831 /*-----------------------------------------------------------------*/
3832 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3838 if( (rifx->condition ^ invert_condition) & 1)
3843 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3844 rifx->generated = 1;
3849 /*-----------------------------------------------------------------*/
3851 /*-----------------------------------------------------------------*/
3852 static void genSkipz(iCode *ifx, int condition)
3855 assert (ifx != NULL);
3863 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3865 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3868 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3870 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3876 /*-----------------------------------------------------------------*/
3878 /*-----------------------------------------------------------------*/
3879 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3886 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3888 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3891 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3892 rifx->generated = 1;
3897 /*-----------------------------------------------------------------*/
3898 /* genChkZeroes :- greater or less than comparison */
3899 /* For each byte in a literal that is zero, inclusive or the */
3900 /* the corresponding byte in the operand with W */
3901 /* returns true if any of the bytes are zero */
3902 /*-----------------------------------------------------------------*/
3903 static int genChkZeroes(operand *op, int lit, int size)
3910 i = (lit >> (size*8)) & 0xff;
3914 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3916 emitpcode(POC_IORFW, popGet(AOP(op),size));
3926 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3927 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
3928 #define DEBUGpc emitpComment
3930 /*-----------------------------------------------------------------*/
3931 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
3932 /* aop (if it's NOT a literal) or from lit (if */
3933 /* aop is a literal) */
3934 /*-----------------------------------------------------------------*/
3935 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3936 if (aop->type == AOP_LIT) {
3937 emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3939 emitpcode (POC_MOVFW, popGet (aop, offset));
3943 /* genCmp performs a left < right comparison, stores
3944 * the outcome in result (if != NULL) and generates
3945 * control flow code for the ifx (if != NULL).
3947 * This version leaves in sequences like
3948 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3949 * which should be optmized by the peephole
3950 * optimizer - RN 2005-01-01 */
3951 static void genCmp (operand *left,operand *right,
3952 operand *result, iCode *ifx, int sign)
3962 int invert_result = 0;
3966 assert (AOP_SIZE(left) == AOP_SIZE(right));
3967 assert (left && right);
3969 size = AOP_SIZE(right) - 1;
3970 mask = (0x100UL << (size*8)) - 1;
3971 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3976 resolveIfx (&rIfx, ifx);
3978 /**********************************************************************
3979 * handle bits - bit compares are promoted to int compares seemingly! *
3980 **********************************************************************/
3982 // THIS IS COMPLETELY UNTESTED!
3983 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3984 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3985 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3986 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3989 // 1 < {0,1} is false --> clear C by skipping the next instruction
3990 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3991 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3992 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3993 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3994 emitCLRC; // only skipped for left=0 && right=1
3996 goto correct_result_in_carry;
4000 /*************************************************
4001 * make sure that left is register (or the like) *
4002 *************************************************/
4003 if (!isAOP_REGlike(left)) {
4004 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4005 assert (isAOP_LIT(left));
4006 assert (isAOP_REGlike(right));
4007 // swap left and right
4008 // left < right <==> right > left <==> (right >= left + 1)
4009 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4011 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4012 // MAXVALUE < right? always false
4013 if (performedLt) emitCLRC; else emitSETC;
4014 goto correct_result_in_carry;
4017 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4018 // that's why we handled it above.
4025 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4026 } else if (isAOP_LIT(right)) {
4027 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4030 assert (isAOP_REGlike(left)); // left must be register or the like
4031 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4033 /*************************************************
4034 * special cases go here *
4035 *************************************************/
4037 if (isAOP_LIT(right)) {
4039 // unsigned comparison to a literal
4040 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4042 // unsigned left < 0? always false
4043 if (performedLt) emitCLRC; else emitSETC;
4044 goto correct_result_in_carry;
4047 // signed comparison to a literal
4048 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4049 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4050 // signed left < 0x80000000? always false
4051 if (performedLt) emitCLRC; else emitSETC;
4052 goto correct_result_in_carry;
4053 } else if (lit == 0) {
4054 // compare left < 0; set CARRY if SIGNBIT(left) is set
4055 if (performedLt) emitSETC; else emitCLRC;
4056 emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
4057 if (performedLt) emitCLRC; else emitSETC;
4058 goto correct_result_in_carry;
4061 } // right is literal
4063 /*************************************************
4064 * perform a general case comparison *
4065 * make sure we get CARRY==1 <==> left >= right *
4066 *************************************************/
4067 // compare most significant bytes
4068 //DEBUGpc ("comparing bytes at offset %d", size);
4070 // unsigned comparison
4071 pic14_mov2w_regOrLit (AOP(right), lit, size);
4072 emitpcode (POC_SUBFW, popGet (AOP(left), size));
4074 // signed comparison
4075 // (add 2^n to both operands then perform an unsigned comparison)
4076 if (isAOP_LIT(right)) {
4077 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4078 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4080 if (litbyte == 0x80) {
4081 // left >= 0x80 -- always true, but more bytes to come
4082 mov2w (AOP(left), size);
4083 emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
4086 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4087 mov2w (AOP(left), size);
4088 emitpcode (POC_ADDLW, popGetLit (0x80));
4089 emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4092 pCodeOp *pctemp = popGetTempReg();
4093 mov2w (AOP(left), size);
4094 emitpcode (POC_ADDLW, popGetLit (0x80));
4095 emitpcode (POC_MOVWF, pctemp);
4096 mov2w (AOP(right), size);
4097 emitpcode (POC_ADDLW, popGetLit (0x80));
4098 emitpcode (POC_SUBFW, pctemp);
4099 popReleaseTempReg(pctemp);
4103 // compare remaining bytes (treat as unsigned case from above)
4104 templbl = newiTempLabel ( NULL );
4107 //DEBUGpc ("comparing bytes at offset %d", offs);
4109 emitpcode (POC_GOTO, popGetLabel (templbl->key));
4110 pic14_mov2w_regOrLit (AOP(right), lit, offs);
4111 emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4113 emitpLabel (templbl->key);
4114 goto result_in_carry;
4118 /****************************************************
4119 * now CARRY contains the result of the comparison: *
4120 * SUBWF sets CARRY iff *
4121 * F-W >= 0 <==> F >= W <==> !(F < W) *
4122 * (F=left, W=right) *
4123 ****************************************************/
4127 // value will be used in the following genSkipc()
4128 rIfx.condition ^= 1;
4131 correct_result_in_carry:
4133 // assign result to variable (if neccessary)
4134 if (result && AOP_TYPE(result) != AOP_CRY) {
4135 //DEBUGpc ("assign result");
4136 size = AOP_SIZE(result);
4138 emitpcode (POC_CLRF, popGet (AOP(result), size));
4140 if (invert_result) {
4142 emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4144 emitpcode (POC_RLF, popGet (AOP(result), 0));
4148 // perform conditional jump
4150 //DEBUGpc ("generate control flow");
4158 /* OLD VERSION -- BUGGY, DO NOT USE */
4160 /*-----------------------------------------------------------------*/
4161 /* genCmp :- greater or less than comparison */
4162 /*-----------------------------------------------------------------*/
4163 static void genCmp (operand *left,operand *right,
4164 operand *result, iCode *ifx, int sign)
4166 int size; //, offset = 0 ;
4167 unsigned long lit = 0L,i = 0;
4168 resolvedIfx rFalseIfx;
4169 // resolvedIfx rTrueIfx;
4173 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4176 DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4177 DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4181 resolveIfx(&rFalseIfx,ifx);
4182 truelbl = newiTempLabel(NULL);
4183 size = max(AOP_SIZE(left),AOP_SIZE(right));
4185 DEBUGpic14_AopType(__LINE__,left,right,result);
4189 /* if literal is on the right then swap with left */
4190 if ((AOP_TYPE(right) == AOP_LIT)) {
4191 operand *tmp = right ;
4192 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4193 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4196 lit = (lit - 1) & mask;
4199 rFalseIfx.condition ^= 1;
4202 } else if ((AOP_TYPE(left) == AOP_LIT)) {
4203 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4207 //if(IC_TRUE(ifx) == NULL)
4208 /* if left & right are bit variables */
4209 if (AOP_TYPE(left) == AOP_CRY &&
4210 AOP_TYPE(right) == AOP_CRY ) {
4211 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4212 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4214 /* subtract right from left if at the
4215 end the carry flag is set then we know that
4216 left is greater than right */
4218 symbol *lbl = newiTempLabel(NULL);
4221 if(AOP_TYPE(right) == AOP_LIT) {
4223 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4225 DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4232 genSkipCond(&rFalseIfx,left,size-1,7);
4234 /* no need to compare to 0...*/
4235 /* NOTE: this is a de-generate compare that most certainly
4236 * creates some dead code. */
4237 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4239 if(ifx) ifx->generated = 1;
4246 //i = (lit >> (size*8)) & 0xff;
4247 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4249 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4251 i = ((0-lit) & 0xff);
4254 /* lit is 0x7f, all signed chars are less than
4255 * this except for 0x7f itself */
4256 emitpcode(POC_XORLW, popGetLit(0x7f));
4257 genSkipz2(&rFalseIfx,0);
4259 emitpcode(POC_ADDLW, popGetLit(0x80));
4260 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4261 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4266 genSkipz2(&rFalseIfx,1);
4268 emitpcode(POC_ADDLW, popGetLit(i));
4269 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4273 if(ifx) ifx->generated = 1;
4277 /* chars are out of the way. now do ints and longs */
4280 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4287 genSkipCond(&rFalseIfx,left,size,7);
4288 if(ifx) ifx->generated = 1;
4293 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4295 //rFalseIfx.condition ^= 1;
4296 //genSkipCond(&rFalseIfx,left,size,7);
4297 //rFalseIfx.condition ^= 1;
4299 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4300 if(rFalseIfx.condition)
4301 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4303 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4305 emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4306 emitpcode(POC_ADDFW, popGet(AOP(left),0));
4307 emitpcode(POC_MOVFW, popGet(AOP(left),1));
4310 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4312 if(rFalseIfx.condition) {
4314 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4320 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4321 emitpLabel(truelbl->key);
4322 if(ifx) ifx->generated = 1;
4329 if( (lit & 0xff) == 0) {
4330 /* lower byte is zero */
4331 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4332 i = ((lit >> 8) & 0xff) ^0x80;
4333 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4334 emitpcode(POC_ADDLW, popGetLit( 0x80));
4335 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4336 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4339 if(ifx) ifx->generated = 1;
4344 /* Special cases for signed longs */
4345 if( (lit & 0xffffff) == 0) {
4346 /* lower byte is zero */
4347 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4348 i = ((lit >> 8*3) & 0xff) ^0x80;
4349 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4350 emitpcode(POC_ADDLW, popGetLit( 0x80));
4351 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4352 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4355 if(ifx) ifx->generated = 1;
4363 if(lit & (0x80 << (size*8))) {
4364 /* lit is negative */
4365 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4367 //genSkipCond(&rFalseIfx,left,size,7);
4369 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4371 if(rFalseIfx.condition)
4372 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4374 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4378 /* lit is positive */
4379 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4380 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4381 if(rFalseIfx.condition)
4382 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4384 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4388 /* There are no more special cases, so perform a general compare */
4390 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4391 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4395 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4397 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4399 //rFalseIfx.condition ^= 1;
4400 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4402 emitpLabel(truelbl->key);
4404 if(ifx) ifx->generated = 1;
4411 /* sign is out of the way. So now do an unsigned compare */
4412 DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4415 /* General case - compare to an unsigned literal on the right.*/
4417 i = (lit >> (size*8)) & 0xff;
4418 emitpcode(POC_MOVLW, popGetLit(i));
4419 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4421 i = (lit >> (size*8)) & 0xff;
4424 emitpcode(POC_MOVLW, popGetLit(i));
4426 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4428 /* this byte of the lit is zero,
4429 *if it's not the last then OR in the variable */
4431 emitpcode(POC_IORFW, popGet(AOP(left),size));
4436 emitpLabel(lbl->key);
4437 //if(emitFinalCheck)
4438 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4440 emitpLabel(truelbl->key);
4442 if(ifx) ifx->generated = 1;
4449 if(AOP_TYPE(left) == AOP_LIT) {
4450 //symbol *lbl = newiTempLabel(NULL);
4452 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4455 DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4458 if((lit == 0) && (sign == 0)){
4461 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4463 emitpcode(POC_IORFW, popGet(AOP(right),--size));
4465 genSkipz2(&rFalseIfx,0);
4466 if(ifx) ifx->generated = 1;
4473 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4474 /* degenerate compare can never be true */
4475 if(rFalseIfx.condition == 0)
4476 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4478 if(ifx) ifx->generated = 1;
4483 /* signed comparisons to a literal byte */
4485 int lp1 = (lit+1) & 0xff;
4487 DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4490 rFalseIfx.condition ^= 1;
4491 genSkipCond(&rFalseIfx,right,0,7);
4494 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4495 emitpcode(POC_XORLW, popGetLit(0x7f));
4496 genSkipz2(&rFalseIfx,1);
4499 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4500 emitpcode(POC_ADDLW, popGetLit(0x80));
4501 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4502 rFalseIfx.condition ^= 1;
4503 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4506 if(ifx) ifx->generated = 1;
4508 /* unsigned comparisons to a literal byte */
4510 switch(lit & 0xff ) {
4512 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4513 genSkipz2(&rFalseIfx,0);
4514 if(ifx) ifx->generated = 1;
4517 genSkipCond(&rFalseIfx,right,0,7);
4518 if(ifx) ifx->generated = 1;
4522 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4523 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4524 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4525 rFalseIfx.condition ^= 1;
4526 if (AOP_TYPE(result) == AOP_CRY) {
4527 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4528 if(ifx) ifx->generated = 1;
4530 DEBUGpic14_emitcode ("; ***","%s %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4531 emitpcode(POC_CLRF, popGet(AOP(result),0));
4532 emitpcode(POC_RLF, popGet(AOP(result),0));
4533 emitpcode(POC_MOVLW, popGetLit(0x01));
4534 emitpcode(POC_XORWF, popGet(AOP(result),0));
4545 /* Size is greater than 1 */
4553 /* this means lit = 0xffffffff, or -1 */
4556 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4557 rFalseIfx.condition ^= 1;
4558 genSkipCond(&rFalseIfx,right,size,7);
4559 if(ifx) ifx->generated = 1;
4566 if(rFalseIfx.condition) {
4567 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4568 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4571 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4573 emitpcode(POC_IORFW, popGet(AOP(right),size));
4577 if(rFalseIfx.condition) {
4578 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4579 emitpLabel(truelbl->key);
4581 rFalseIfx.condition ^= 1;
4582 genSkipCond(&rFalseIfx,right,s,7);
4585 if(ifx) ifx->generated = 1;
4589 if((size == 1) && (0 == (lp1&0xff))) {
4590 /* lower byte of signed word is zero */
4591 DEBUGpic14_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
4592 i = ((lp1 >> 8) & 0xff) ^0x80;
4593 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4594 emitpcode(POC_ADDLW, popGetLit( 0x80));
4595 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4596 rFalseIfx.condition ^= 1;
4597 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4600 if(ifx) ifx->generated = 1;
4604 if(lit & (0x80 << (size*8))) {
4605 /* Lit is less than zero */
4606 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
4607 //rFalseIfx.condition ^= 1;
4608 //genSkipCond(&rFalseIfx,left,size,7);
4609 //rFalseIfx.condition ^= 1;
4610 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4611 //emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4613 if(rFalseIfx.condition)
4614 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4616 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4620 /* Lit is greater than or equal to zero */
4621 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
4622 //rFalseIfx.condition ^= 1;
4623 //genSkipCond(&rFalseIfx,right,size,7);
4624 //rFalseIfx.condition ^= 1;
4626 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4627 //emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4629 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4630 if(rFalseIfx.condition)
4631 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4633 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4638 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4639 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4643 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4645 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4647 rFalseIfx.condition ^= 1;
4648 //rFalseIfx.condition = 1;
4649 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4651 emitpLabel(truelbl->key);
4653 if(ifx) ifx->generated = 1;
4658 /* compare word or long to an unsigned literal on the right.*/
4663 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4666 break; /* handled above */
4669 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4671 emitpcode(POC_IORFW, popGet(AOP(right),size));
4672 genSkipz2(&rFalseIfx,0);
4676 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4678 emitpcode(POC_IORFW, popGet(AOP(right),size));
4681 if(rFalseIfx.condition)
4682 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4684 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4687 emitpcode(POC_MOVLW, popGetLit(lit+1));
4688 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4690 rFalseIfx.condition ^= 1;
4691 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4694 emitpLabel(truelbl->key);
4696 if(ifx) ifx->generated = 1;
4702 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4703 i = (lit >> (size*8)) & 0xff;
4705 emitpcode(POC_MOVLW, popGetLit(i));
4706 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4709 i = (lit >> (size*8)) & 0xff;
4712 emitpcode(POC_MOVLW, popGetLit(i));
4714 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4716 /* this byte of the lit is zero,
4717 *if it's not the last then OR in the variable */
4719 emitpcode(POC_IORFW, popGet(AOP(right),size));
4724 emitpLabel(lbl->key);
4726 rFalseIfx.condition ^= 1;
4727 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4731 emitpLabel(truelbl->key);
4732 if(ifx) ifx->generated = 1;
4736 /* Compare two variables */
4738 DEBUGpic14_emitcode(";sign","%d",sign);
4742 /* Sigh. thus sucks... */
4744 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4745 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4746 emitpcode(POC_MOVLW, popGetLit(0x80));
4747 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4748 emitpcode(POC_XORFW, popGet(AOP(right),size));
4749 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4751 /* Signed char comparison */
4752 /* Special thanks to Nikolai Golovchenko for this snippet */
4753 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4754 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4755 emitpcode(POC_RRFW, popGet(AOP(left),0)); /* could be any register */
4756 emitpcode(POC_XORFW, popGet(AOP(left),0));
4757 emitpcode(POC_XORFW, popGet(AOP(right),0));
4758 emitpcode(POC_ADDLW, popGetLit(0x80));
4760 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4761 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4763 if(ifx) ifx->generated = 1;
4769 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4770 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4774 /* The rest of the bytes of a multi-byte compare */
4778 emitpcode(POC_GOTO, popGetLabel(lbl->key));
4781 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4782 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4787 emitpLabel(lbl->key);
4789 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4790 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
4791 (AOP_TYPE(result) == AOP_REG)) {
4792 emitpcode(POC_CLRF, popGet(AOP(result),0));
4793 emitpcode(POC_RLF, popGet(AOP(result),0));
4795 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4797 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4798 if(ifx) ifx->generated = 1;
4805 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4806 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4807 pic14_outBitC(result);
4809 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4810 /* if the result is used in the next
4811 ifx conditional branch then generate
4812 code a little differently */
4814 genIfxJump (ifx,"c");
4816 pic14_outBitC(result);
4817 /* leave the result in acc */
4823 /*-----------------------------------------------------------------*/
4824 /* genCmpGt :- greater than comparison */
4825 /*-----------------------------------------------------------------*/
4826 static void genCmpGt (iCode *ic, iCode *ifx)
4828 operand *left, *right, *result;
4829 sym_link *letype , *retype;
4833 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4835 right= IC_RIGHT(ic);
4836 result = IC_RESULT(ic);
4838 letype = getSpec(operandType(left));
4839 retype =getSpec(operandType(right));
4840 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4841 /* assign the amsops */
4842 aopOp (left,ic,FALSE);
4843 aopOp (right,ic,FALSE);
4844 aopOp (result,ic,TRUE);
4846 genCmp(right, left, result, ifx, sign);
4848 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4849 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4850 freeAsmop(result,NULL,ic,TRUE);
4853 /*-----------------------------------------------------------------*/
4854 /* genCmpLt - less than comparisons */
4855 /*-----------------------------------------------------------------*/
4856 static void genCmpLt (iCode *ic, iCode *ifx)
4858 operand *left, *right, *result;
4859 sym_link *letype , *retype;
4863 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4865 right= IC_RIGHT(ic);
4866 result = IC_RESULT(ic);
4868 letype = getSpec(operandType(left));
4869 retype =getSpec(operandType(right));
4870 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4872 /* assign the amsops */
4873 aopOp (left,ic,FALSE);
4874 aopOp (right,ic,FALSE);
4875 aopOp (result,ic,TRUE);
4877 genCmp(left, right, result, ifx, sign);
4879 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4880 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4881 freeAsmop(result,NULL,ic,TRUE);
4885 /*-----------------------------------------------------------------*/
4886 /* genc16bit2lit - compare a 16 bit value to a literal */
4887 /*-----------------------------------------------------------------*/
4888 static void genc16bit2lit(operand *op, int lit, int offset)
4893 DEBUGpic14_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
4894 if( (lit&0xff) == 0)
4899 switch( BYTEofLONG(lit,i)) {
4901 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4904 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4907 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4910 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4911 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4916 switch( BYTEofLONG(lit,i)) {
4918 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4922 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4926 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4929 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4931 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4939 /*-----------------------------------------------------------------*/
4940 /* gencjneshort - compare and jump if not equal */
4941 /*-----------------------------------------------------------------*/
4942 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4944 int size = min(AOP_SIZE(left),AOP_SIZE(right));
4949 //unsigned long lit = 0L;
4951 if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4952 emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4955 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4956 DEBUGpic14_AopType(__LINE__,left,right,result);
4958 assert (!pic14_sameRegs (AOP(left), AOP(result)));
4959 assert (!pic14_sameRegs (AOP(right), AOP(result)));
4960 if (AOP_SIZE(result)) {
4961 for (offset = 0; offset < AOP_SIZE(result); offset++)
4962 emitpcode (POC_CLRF, popGet (AOP(result), offset));
4965 assert (AOP_SIZE(left) == AOP_SIZE(right));
4966 //resolveIfx(&rIfx,ifx);
4967 lbl = newiTempLabel (NULL);
4970 mov2w (AOP(right),size);
4971 emitpcode (POC_XORFW, popGet (AOP(left), size));
4975 emitpcode (POC_GOTO, popGetLabel (lbl->key));
4978 emitpLabel (lbl->key);
4979 if (AOP_SIZE(result)) {
4981 emitpcode (POC_INCF, popGet (AOP(result), 0));
4984 genSkipz (ifx, NULL != IC_TRUE(ifx));
4991 DEBUGpic14_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
4992 assert (!pic14_sameRegs (AOP(result), AOP(left)));
4993 assert (!pic14_sameRegs (AOP(result), AOP(right)));
4994 for (offset=0; offset < AOP_SIZE(result); offset++)
4996 emitpcode (POC_CLRF, popGet (AOP(result), offset));
5001 /* if the left side is a literal or
5002 if the right is in a pointer register and left
5004 if ((AOP_TYPE(left) == AOP_LIT) ||
5005 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5010 if(AOP_TYPE(right) == AOP_LIT)
5011 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5013 /* if the right side is a literal then anything goes */
5014 if (AOP_TYPE(right) == AOP_LIT &&
5015 AOP_TYPE(left) != AOP_DIR ) {
5018 genc16bit2lit(left, lit, 0);
5020 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5026 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5027 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5029 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5033 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5041 /* if the right side is in a register or in direct space or
5042 if the left is a pointer register & right is not */
5043 else if (AOP_TYPE(right) == AOP_REG ||
5044 AOP_TYPE(right) == AOP_DIR ||
5045 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5046 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5047 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5048 int lbl_key = lbl->key;
5051 DEBUGpic14_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
5052 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
5053 __FUNCTION__,__LINE__);
5057 /* switch(size) { */
5059 /* genc16bit2lit(left, lit, 0); */
5061 /* emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
5067 if((AOP_TYPE(left) == AOP_DIR) &&
5068 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5070 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5071 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5073 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5075 switch (lit & 0xff) {
5077 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5080 emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
5081 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5082 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5086 emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5087 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5088 //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5089 emitpcode(POC_GOTO,popGetLabel(lbl_key));
5093 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5094 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5099 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5102 if(AOP_TYPE(result) == AOP_CRY) {
5103 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5108 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5110 /* fix me. probably need to check result size too */
5111 //emitpcode(POC_CLRF,popGet(AOP(result),0));
5116 emitpcode(POC_GOTO,popGetLabel(lbl_key));
5126 } else if(AOP_TYPE(right) == AOP_REG &&
5127 AOP_TYPE(left) != AOP_DIR){
5131 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5132 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5133 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5138 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5143 /* right is a pointer reg need both a & b */
5146 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5148 pic14_emitcode("mov","b,%s",l);
5149 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5150 pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
5155 emitpcode(POC_INCF,popGet(AOP(result),0));
5157 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5159 emitpLabel(lbl->key);
5161 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5170 /*-----------------------------------------------------------------*/
5171 /* gencjne - compare and jump if not equal */
5172 /*-----------------------------------------------------------------*/
5173 static void gencjne(operand *left, operand *right, iCode *ifx)
5175 symbol *tlbl = newiTempLabel(NULL);
5177 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5178 gencjneshort(left, right, lbl);
5180 pic14_emitcode("mov","a,%s",one);
5181 pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5182 pic14_emitcode("","%05d_DS_:",lbl->key+100);
5183 pic14_emitcode("clr","a");
5184 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5186 emitpLabel(lbl->key);
5187 emitpLabel(tlbl->key);
5192 /*-----------------------------------------------------------------*/
5193 /* genCmpEq - generates code for equal to */
5194 /*-----------------------------------------------------------------*/
5195 static void genCmpEq (iCode *ic, iCode *ifx)
5197 operand *left, *right, *result;
5199 symbol *false_label;
5202 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5205 DEBUGpic14_emitcode ("; ifx is non-null","");
5207 DEBUGpic14_emitcode ("; ifx is null","");
5209 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5210 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5211 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5213 DEBUGpic14_AopType(__LINE__,left,right,result);
5215 /* if literal, move literal to right */
5216 if (op_isLitLike (IC_LEFT(ic))) {
5217 operand *tmp = right ;
5223 if (ifx && !IC_TRUE(ifx))
5225 assert (IC_FALSE(ifx));
5226 false_label = IC_FALSE(ifx);
5229 size = min(AOP_SIZE(left),AOP_SIZE(right));
5230 assert(!pic14_sameRegs(AOP(result),AOP(left)));
5231 assert(!pic14_sameRegs(AOP(result),AOP(right)));
5233 /* assume left != right */
5236 for (i=0; i < AOP_SIZE(result); i++)
5238 emitpcode(POC_CLRF, popGet(AOP(result),i));
5242 if (AOP_TYPE(right) == AOP_LIT)
5244 unsigned long lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
5246 size = AOP_SIZE(left);
5247 assert(!op_isLitLike(left));
5252 mov2w(AOP(left), 0);
5253 for (i=1; i < size; i++)
5254 emitpcode(POC_IORFW,popGet(AOP(left),i));
5255 /* now Z is set iff `left == right' */
5257 if (!false_label) false_label = newiTempLabel(NULL);
5258 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5262 for (i=0; i < size; i++)
5265 emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
5266 /* now Z is cleared if `left != right' */
5268 if (!false_label) false_label = newiTempLabel(NULL);
5269 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5276 /* right is no literal */
5279 for (i=0; i < size; i++)
5281 mov2w(AOP(right),i);
5282 emitpcode(POC_XORFW,popGet(AOP(left),i));
5283 /* now Z is cleared if `left != right' */
5285 if (!false_label) false_label = newiTempLabel(NULL);
5286 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5290 /* if we reach here, left == right */
5292 if (AOP_SIZE(result) > 0)
5294 emitpcode(POC_INCF, popGet(AOP(result),0));
5297 if (ifx && IC_TRUE(ifx))
5299 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5302 if (false_label && (!ifx || IC_TRUE(ifx)))
5303 emitpLabel(false_label->key);
5305 if (ifx) ifx->generated = 1;
5307 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5308 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5309 freeAsmop(result,NULL,ic,TRUE);
5312 /*-----------------------------------------------------------------*/
5313 /* ifxForOp - returns the icode containing the ifx for operand */
5314 /*-----------------------------------------------------------------*/
5315 static iCode *ifxForOp ( operand *op, iCode *ic )
5318 /* if true symbol then needs to be assigned */
5319 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5320 if (IS_TRUE_SYMOP(op))
5323 /* if this has register type condition and
5324 the next instruction is ifx with the same operand
5325 and live to of the operand is upto the ifx only then */
5327 ic->next->op == IFX &&
5328 IC_COND(ic->next)->key == op->key &&
5329 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5333 ic->next->op == IFX &&
5334 IC_COND(ic->next)->key == op->key) {
5335 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5339 DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5341 ic->next->op == IFX)
5342 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5345 ic->next->op == IFX &&
5346 IC_COND(ic->next)->key == op->key) {
5347 DEBUGpic14_emitcode ("; "," key is okay");
5348 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5349 OP_SYMBOL(op)->liveTo,
5356 /*-----------------------------------------------------------------*/
5357 /* genAndOp - for && operation */
5358 /*-----------------------------------------------------------------*/
5359 static void genAndOp (iCode *ic)
5361 operand *left,*right, *result;
5365 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5366 /* note here that && operations that are in an
5367 if statement are taken away by backPatchLabels
5368 only those used in arthmetic operations remain */
5369 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5370 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5371 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5373 DEBUGpic14_AopType(__LINE__,left,right,result);
5375 emitpcode(POC_MOVFW,popGet(AOP(left),0));
5376 emitpcode(POC_ANDFW,popGet(AOP(right),0));
5377 emitpcode(POC_MOVWF,popGet(AOP(result),0));
5379 /* if both are bit variables */
5380 /* if (AOP_TYPE(left) == AOP_CRY && */
5381 /* AOP_TYPE(right) == AOP_CRY ) { */
5382 /* pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5383 /* pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5384 /* pic14_outBitC(result); */
5386 /* tlbl = newiTempLabel(NULL); */
5387 /* pic14_toBoolean(left); */
5388 /* pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5389 /* pic14_toBoolean(right); */
5390 /* pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5391 /* pic14_outBitAcc(result); */
5394 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5395 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5396 freeAsmop(result,NULL,ic,TRUE);
5400 /*-----------------------------------------------------------------*/
5401 /* genOrOp - for || operation */
5402 /*-----------------------------------------------------------------*/
5405 modified this code, but it doesn't appear to ever get called
5408 static void genOrOp (iCode *ic)
5410 operand *left,*right, *result;
5414 /* note here that || operations that are in an
5415 if statement are taken away by backPatchLabels
5416 only those used in arthmetic operations remain */
5418 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5419 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5420 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5421 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5423 DEBUGpic14_AopType(__LINE__,left,right,result);
5425 for (i=0; i < AOP_SIZE(result); i++)
5427 emitpcode(POC_CLRF, popGet(AOP(result), i));
5430 tlbl = newiTempLabel(NULL);
5431 pic14_toBoolean(left);
5433 emitpcode(POC_GOTO, popGetLabel(tlbl->key));
5434 pic14_toBoolean(right);
5435 emitpLabel(tlbl->key);
5436 /* here Z is clear IFF `left || right' */
5438 emitpcode(POC_INCF, popGet(AOP(result), 0));
5440 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5441 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5442 freeAsmop(result,NULL,ic,TRUE);
5445 /*-----------------------------------------------------------------*/
5446 /* isLiteralBit - test if lit == 2^n */
5447 /*-----------------------------------------------------------------*/
5448 static int isLiteralBit(unsigned long lit)
5450 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5451 0x100L,0x200L,0x400L,0x800L,
5452 0x1000L,0x2000L,0x4000L,0x8000L,
5453 0x10000L,0x20000L,0x40000L,0x80000L,
5454 0x100000L,0x200000L,0x400000L,0x800000L,
5455 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5456 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5460 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5461 for(idx = 0; idx < 32; idx++)
5467 /*-----------------------------------------------------------------*/
5468 /* continueIfTrue - */
5469 /*-----------------------------------------------------------------*/
5470 static void continueIfTrue (iCode *ic)
5473 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5475 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5479 /*-----------------------------------------------------------------*/
5481 /*-----------------------------------------------------------------*/
5482 static void jumpIfTrue (iCode *ic)
5485 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5487 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5491 /*-----------------------------------------------------------------*/
5492 /* jmpTrueOrFalse - */
5493 /*-----------------------------------------------------------------*/
5494 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5497 // ugly but optimized by peephole
5498 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5500 symbol *nlbl = newiTempLabel(NULL);
5501 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5502 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5503 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5504 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5507 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5508 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5513 /*-----------------------------------------------------------------*/
5514 /* genAnd - code for and */
5515 /*-----------------------------------------------------------------*/
5516 static void genAnd (iCode *ic, iCode *ifx)
5518 operand *left, *right, *result;
5520 unsigned long lit = 0L;
5525 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5526 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5527 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5528 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5530 resolveIfx(&rIfx,ifx);
5532 /* if left is a literal & right is not then exchange them */
5533 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5534 AOP_NEEDSACC(left)) {
5535 operand *tmp = right ;
5540 /* if result = right then exchange them */
5541 if(pic14_sameRegs(AOP(result),AOP(right))){
5542 operand *tmp = right ;
5547 /* if right is bit then exchange them */
5548 if (AOP_TYPE(right) == AOP_CRY &&
5549 AOP_TYPE(left) != AOP_CRY){
5550 operand *tmp = right ;
5554 if(AOP_TYPE(right) == AOP_LIT)
5555 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5557 size = AOP_SIZE(result);
5559 DEBUGpic14_AopType(__LINE__,left,right,result);
5562 // result = bit & yy;
5563 if (AOP_TYPE(left) == AOP_CRY){
5564 // c = bit & literal;
5565 if(AOP_TYPE(right) == AOP_LIT){
5567 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5570 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5573 if(size && (AOP_TYPE(result) == AOP_CRY)){
5574 pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5577 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5581 pic14_emitcode("clr","c");
5584 if (AOP_TYPE(right) == AOP_CRY){
5586 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5587 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5590 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5592 pic14_emitcode("rrc","a");
5593 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5599 pic14_outBitC(result);
5601 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5602 genIfxJump(ifx, "c");
5606 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5607 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5608 if((AOP_TYPE(right) == AOP_LIT) &&
5609 (AOP_TYPE(result) == AOP_CRY) &&
5610 (AOP_TYPE(left) != AOP_CRY)){
5611 int posbit = isLiteralBit(lit);
5615 //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5618 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5623 while (posbit > 7) {
5627 emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5628 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5629 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5636 symbol *tlbl = newiTempLabel(NULL);
5637 int sizel = AOP_SIZE(left);
5639 pic14_emitcode("setb","c");
5641 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5642 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5644 if((posbit = isLiteralBit(bytelit)) != 0)
5645 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5647 if(bytelit != 0x0FFL)
5648 pic14_emitcode("anl","a,%s",
5649 aopGet(AOP(right),offset,FALSE,TRUE));
5650 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5655 // bit = left & literal
5657 pic14_emitcode("clr","c");
5658 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5660 // if(left & literal)
5663 jmpTrueOrFalse(ifx, tlbl);
5667 pic14_outBitC(result);
5671 /* if left is same as result */
5672 if(pic14_sameRegs(AOP(result),AOP(left))){
5674 for(;size--; offset++,lit>>=8) {
5675 if(AOP_TYPE(right) == AOP_LIT){
5676 switch(lit & 0xff) {
5678 /* and'ing with 0 has clears the result */
5679 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5682 /* and'ing with 0xff is a nop when the result and left are the same */
5687 int p = my_powof2( (~lit) & 0xff );
5689 /* only one bit is set in the literal, so use a bcf instruction */
5690 emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5693 if(know_W != (int)(lit&0xff))
5694 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5696 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5701 if (AOP_TYPE(left) == AOP_ACC) {
5702 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5704 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5705 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5712 // left & result in different registers
5713 if(AOP_TYPE(result) == AOP_CRY){
5715 // if(size), result in bit
5716 // if(!size && ifx), conditional oper: if(left & right)
5717 symbol *tlbl = newiTempLabel(NULL);
5718 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5720 pic14_emitcode("setb","c");
5722 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5723 pic14_emitcode("anl","a,%s",
5724 aopGet(AOP(left),offset,FALSE,FALSE));
5725 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5730 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5731 pic14_outBitC(result);
5733 jmpTrueOrFalse(ifx, tlbl);
5735 for(;(size--);offset++) {
5737 // result = left & right
5738 if(AOP_TYPE(right) == AOP_LIT){
5739 int t = (lit >> (offset*8)) & 0x0FFL;
5742 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5745 if(AOP_TYPE(left) != AOP_ACC) {
5746 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5748 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5751 if(AOP_TYPE(left) == AOP_ACC) {
5752 emitpcode(POC_ANDLW, popGetLit(t));
5754 emitpcode(POC_MOVLW, popGetLit(t));
5755 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5757 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5762 if (AOP_TYPE(left) == AOP_ACC) {
5763 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5765 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5766 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5768 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5774 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5775 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5776 freeAsmop(result,NULL,ic,TRUE);
5779 /*-----------------------------------------------------------------*/
5780 /* genOr - code for or */
5781 /*-----------------------------------------------------------------*/
5782 static void genOr (iCode *ic, iCode *ifx)
5784 operand *left, *right, *result;
5786 unsigned long lit = 0L;
5789 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5791 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5792 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5793 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5795 DEBUGpic14_AopType(__LINE__,left,right,result);
5797 /* if left is a literal & right is not then exchange them */
5798 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5799 AOP_NEEDSACC(left)) {
5800 operand *tmp = right ;
5805 /* if result = right then exchange them */
5806 if(pic14_sameRegs(AOP(result),AOP(right))){
5807 operand *tmp = right ;
5812 /* if right is bit then exchange them */
5813 if (AOP_TYPE(right) == AOP_CRY &&
5814 AOP_TYPE(left) != AOP_CRY){
5815 operand *tmp = right ;
5820 DEBUGpic14_AopType(__LINE__,left,right,result);
5822 if(AOP_TYPE(right) == AOP_LIT)
5823 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5825 size = AOP_SIZE(result);
5829 if (AOP_TYPE(left) == AOP_CRY){
5830 if(AOP_TYPE(right) == AOP_LIT){
5831 // c = bit & literal;
5833 // lit != 0 => result = 1
5834 if(AOP_TYPE(result) == AOP_CRY){
5836 emitpcode(POC_BSF, popGet(AOP(result),0));
5837 //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5838 // AOP(result)->aopu.aop_dir,
5839 // AOP(result)->aopu.aop_dir);
5841 continueIfTrue(ifx);
5845 // lit == 0 => result = left
5846 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5848 pic14_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5851 if (AOP_TYPE(right) == AOP_CRY){
5852 if(pic14_sameRegs(AOP(result),AOP(left))){
5854 emitpcode(POC_BCF, popGet(AOP(result),0));
5855 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5856 emitpcode(POC_BSF, popGet(AOP(result),0));
5858 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5859 AOP(result)->aopu.aop_dir,
5860 AOP(result)->aopu.aop_dir);
5861 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5862 AOP(right)->aopu.aop_dir,
5863 AOP(right)->aopu.aop_dir);
5864 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5865 AOP(result)->aopu.aop_dir,
5866 AOP(result)->aopu.aop_dir);
5868 if( AOP_TYPE(result) == AOP_ACC) {
5869 emitpcode(POC_MOVLW, popGetLit(0));
5870 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5871 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5872 emitpcode(POC_MOVLW, popGetLit(1));
5876 emitpcode(POC_BCF, popGet(AOP(result),0));
5877 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5878 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5879 emitpcode(POC_BSF, popGet(AOP(result),0));
5881 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5882 AOP(result)->aopu.aop_dir,
5883 AOP(result)->aopu.aop_dir);
5884 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5885 AOP(right)->aopu.aop_dir,
5886 AOP(right)->aopu.aop_dir);
5887 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5888 AOP(left)->aopu.aop_dir,
5889 AOP(left)->aopu.aop_dir);
5890 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5891 AOP(result)->aopu.aop_dir,
5892 AOP(result)->aopu.aop_dir);
5897 symbol *tlbl = newiTempLabel(NULL);
5898 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5901 emitpcode(POC_BCF, popGet(AOP(result),0));
5902 if( AOP_TYPE(right) == AOP_ACC) {
5903 emitpcode(POC_IORLW, popGetLit(0));
5905 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5906 emitpcode(POC_BSF, popGet(AOP(result),0));
5911 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5912 pic14_emitcode(";XXX setb","c");
5913 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5914 AOP(left)->aopu.aop_dir,tlbl->key+100);
5915 pic14_toBoolean(right);
5916 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5917 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5918 jmpTrueOrFalse(ifx, tlbl);
5922 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5929 pic14_outBitC(result);
5931 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5932 genIfxJump(ifx, "c");
5936 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5937 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5938 if((AOP_TYPE(right) == AOP_LIT) &&
5939 (AOP_TYPE(result) == AOP_CRY) &&
5940 (AOP_TYPE(left) != AOP_CRY)){
5942 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5945 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5947 continueIfTrue(ifx);
5950 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5951 // lit = 0, result = boolean(left)
5953 pic14_emitcode(";XXX setb","c");
5954 pic14_toBoolean(right);
5956 symbol *tlbl = newiTempLabel(NULL);
5957 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5959 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5961 genIfxJump (ifx,"a");
5965 pic14_outBitC(result);
5969 /* if left is same as result */
5970 if(pic14_sameRegs(AOP(result),AOP(left))){
5972 for(;size--; offset++,lit>>=8) {
5973 if(AOP_TYPE(right) == AOP_LIT){
5974 if((lit & 0xff) == 0)
5975 /* or'ing with 0 has no effect */
5978 int p = my_powof2(lit & 0xff);
5980 /* only one bit is set in the literal, so use a bsf instruction */
5982 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5984 if(know_W != (int)(lit & 0xff))
5985 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5986 know_W = lit & 0xff;
5987 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5992 if (AOP_TYPE(left) == AOP_ACC) {
5993 emitpcode(POC_IORFW, popGet(AOP(right),offset));
5994 pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5996 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
5997 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5999 pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6000 pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
6006 // left & result in different registers
6007 if(AOP_TYPE(result) == AOP_CRY){
6009 // if(size), result in bit
6010 // if(!size && ifx), conditional oper: if(left | right)
6011 symbol *tlbl = newiTempLabel(NULL);
6012 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6013 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6017 pic14_emitcode(";XXX setb","c");
6019 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6020 pic14_emitcode(";XXX orl","a,%s",
6021 aopGet(AOP(left),offset,FALSE,FALSE));
6022 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6027 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6028 pic14_outBitC(result);
6030 jmpTrueOrFalse(ifx, tlbl);
6031 } else for(;(size--);offset++){
6033 // result = left | right
6034 if(AOP_TYPE(right) == AOP_LIT){
6035 int t = (lit >> (offset*8)) & 0x0FFL;
6038 if (AOP_TYPE(left) != AOP_ACC) {
6039 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
6041 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6045 if (AOP_TYPE(left) == AOP_ACC) {
6046 emitpcode(POC_IORLW, popGetLit(t));
6048 emitpcode(POC_MOVLW, popGetLit(t));
6049 emitpcode(POC_IORFW, popGet(AOP(left),offset));
6051 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6056 // faster than result <- left, anl result,right
6057 // and better if result is SFR
6058 if (AOP_TYPE(left) == AOP_ACC) {
6059 emitpcode(POC_IORFW,popGet(AOP(right),offset));
6061 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6062 emitpcode(POC_IORFW,popGet(AOP(left),offset));
6064 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6069 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6070 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6071 freeAsmop(result,NULL,ic,TRUE);
6074 /*-----------------------------------------------------------------*/
6075 /* genXor - code for xclusive or */
6076 /*-----------------------------------------------------------------*/
6077 static void genXor (iCode *ic, iCode *ifx)
6079 operand *left, *right, *result;
6081 unsigned long lit = 0L;
6084 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6086 aopOp((left = IC_LEFT(ic)),ic,FALSE);
6087 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6088 aopOp((result=IC_RESULT(ic)),ic,TRUE);
6090 /* if left is a literal & right is not ||
6091 if left needs acc & right does not */
6092 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6093 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6094 operand *tmp = right ;
6099 /* if result = right then exchange them */
6100 if(pic14_sameRegs(AOP(result),AOP(right))){
6101 operand *tmp = right ;
6106 /* if right is bit then exchange them */
6107 if (AOP_TYPE(right) == AOP_CRY &&
6108 AOP_TYPE(left) != AOP_CRY){
6109 operand *tmp = right ;
6113 if(AOP_TYPE(right) == AOP_LIT)
6114 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6116 size = AOP_SIZE(result);
6120 if (AOP_TYPE(left) == AOP_CRY){
6121 if(AOP_TYPE(right) == AOP_LIT){
6122 // c = bit & literal;
6124 // lit>>1 != 0 => result = 1
6125 if(AOP_TYPE(result) == AOP_CRY){
6127 {emitpcode(POC_BSF, popGet(AOP(result),offset));
6128 pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6130 continueIfTrue(ifx);
6133 pic14_emitcode("setb","c");
6137 // lit == 0, result = left
6138 if(size && pic14_sameRegs(AOP(result),AOP(left)))
6140 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6142 // lit == 1, result = not(left)
6143 if(size && pic14_sameRegs(AOP(result),AOP(left))){
6144 emitpcode(POC_MOVLW, popGet(AOP(result),offset));
6145 emitpcode(POC_XORWF, popGet(AOP(result),offset));
6146 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6149 assert ( !"incomplete genXor" );
6150 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6151 pic14_emitcode("cpl","c");
6158 symbol *tlbl = newiTempLabel(NULL);
6159 if (AOP_TYPE(right) == AOP_CRY){
6161 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6164 int sizer = AOP_SIZE(right);
6166 // if val>>1 != 0, result = 1
6167 pic14_emitcode("setb","c");
6169 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6171 // test the msb of the lsb
6172 pic14_emitcode("anl","a,#0xfe");
6173 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6177 pic14_emitcode("rrc","a");
6179 pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6180 pic14_emitcode("cpl","c");
6181 pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6186 pic14_outBitC(result);
6188 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6189 genIfxJump(ifx, "c");
6193 if(pic14_sameRegs(AOP(result),AOP(left))){
6194 /* if left is same as result */
6195 for(;size--; offset++) {
6196 if(AOP_TYPE(right) == AOP_LIT){
6197 int t = (lit >> (offset*8)) & 0x0FFL;
6201 if (IS_AOP_PREG(left)) {
6202 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6203 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6204 aopPut(AOP(result),"a",offset);
6206 emitpcode(POC_MOVLW, popGetLit(t));
6207 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6208 pic14_emitcode("xrl","%s,%s",
6209 aopGet(AOP(left),offset,FALSE,TRUE),
6210 aopGet(AOP(right),offset,FALSE,FALSE));
6213 if (AOP_TYPE(left) == AOP_ACC)
6214 pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6216 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6217 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6219 if (IS_AOP_PREG(left)) {
6220 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6221 aopPut(AOP(result),"a",offset);
6223 pic14_emitcode("xrl","%s,a",
6224 aopGet(AOP(left),offset,FALSE,TRUE));
6230 // left & result in different registers
6231 if(AOP_TYPE(result) == AOP_CRY){
6233 // if(size), result in bit
6234 // if(!size && ifx), conditional oper: if(left ^ right)
6235 symbol *tlbl = newiTempLabel(NULL);
6236 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6238 pic14_emitcode("setb","c");
6240 if((AOP_TYPE(right) == AOP_LIT) &&
6241 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6242 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6244 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6245 pic14_emitcode("xrl","a,%s",
6246 aopGet(AOP(left),offset,FALSE,FALSE));
6248 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6253 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6254 pic14_outBitC(result);
6256 jmpTrueOrFalse(ifx, tlbl);
6257 } else for(;(size--);offset++){
6259 // result = left & right
6260 if(AOP_TYPE(right) == AOP_LIT){
6261 int t = (lit >> (offset*8)) & 0x0FFL;
6264 if (AOP_TYPE(left) != AOP_ACC) {
6265 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6267 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6268 pic14_emitcode("movf","%s,w",
6269 aopGet(AOP(left),offset,FALSE,FALSE));
6270 pic14_emitcode("movwf","%s",
6271 aopGet(AOP(result),offset,FALSE,FALSE));
6274 if (AOP_TYPE(left) == AOP_ACC) {
6275 emitpcode(POC_XORLW, popGetLit(t));
6277 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6279 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6282 if (AOP_TYPE(left) == AOP_ACC) {
6283 emitpcode(POC_XORLW, popGetLit(t));
6285 emitpcode(POC_MOVLW, popGetLit(t));
6286 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6288 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6289 pic14_emitcode("movlw","0x%x",t);
6290 pic14_emitcode("xorwf","%s,w",
6291 aopGet(AOP(left),offset,FALSE,FALSE));
6292 pic14_emitcode("movwf","%s",
6293 aopGet(AOP(result),offset,FALSE,FALSE));
6299 // faster than result <- left, anl result,right
6300 // and better if result is SFR
6301 if (AOP_TYPE(left) == AOP_ACC) {
6302 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6304 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6305 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6307 if ( AOP_TYPE(result) != AOP_ACC){
6308 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6314 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6315 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6316 freeAsmop(result,NULL,ic,TRUE);
6319 /*-----------------------------------------------------------------*/
6320 /* genInline - write the inline code out */
6321 /*-----------------------------------------------------------------*/
6322 static void genInline (iCode *ic)
6324 char *buffer, *bp, *bp1;
6327 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6329 _G.inLine += (!options.asmpeep);
6331 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6332 strcpy(buffer,IC_INLINE(ic));
6334 /* emit each line as a code */
6340 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6348 /* print label, use this special format with NULL directive
6349 * to denote that the argument should not be indented with tab */
6350 addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6357 if ((bp1 != bp) && *bp1)
6358 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6362 _G.inLine -= (!options.asmpeep);
6365 /*-----------------------------------------------------------------*/
6366 /* genRRC - rotate right with carry */
6367 /*-----------------------------------------------------------------*/
6368 static void genRRC (iCode *ic)
6370 operand *left , *result ;
6371 int size, offset = 0, same;
6374 /* rotate right with carry */
6376 result=IC_RESULT(ic);
6377 aopOp (left,ic,FALSE);
6378 aopOp (result,ic,FALSE);
6380 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6382 same = pic14_sameRegs(AOP(result),AOP(left));
6384 size = AOP_SIZE(result);
6386 /* get the lsb and put it into the carry */
6387 emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6394 emitpcode(POC_RRF, popGet(AOP(left),offset));
6396 emitpcode(POC_RRFW, popGet(AOP(left),offset));
6397 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6403 freeAsmop(left,NULL,ic,TRUE);
6404 freeAsmop(result,NULL,ic,TRUE);
6407 /*-----------------------------------------------------------------*/
6408 /* genRLC - generate code for rotate left with carry */
6409 /*-----------------------------------------------------------------*/
6410 static void genRLC (iCode *ic)
6412 operand *left , *result ;
6413 int size, offset = 0;
6417 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6418 /* rotate right with carry */
6420 result=IC_RESULT(ic);
6421 aopOp (left,ic,FALSE);
6422 aopOp (result,ic,FALSE);
6424 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6426 same = pic14_sameRegs(AOP(result),AOP(left));
6428 /* move it to the result */
6429 size = AOP_SIZE(result);
6431 /* get the msb and put it into the carry */
6432 emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6439 emitpcode(POC_RLF, popGet(AOP(left),offset));
6441 emitpcode(POC_RLFW, popGet(AOP(left),offset));
6442 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6449 freeAsmop(left,NULL,ic,TRUE);
6450 freeAsmop(result,NULL,ic,TRUE);
6453 /*-----------------------------------------------------------------*/
6454 /* genGetHbit - generates code get highest order bit */
6455 /*-----------------------------------------------------------------*/
6456 static void genGetHbit (iCode *ic)
6458 operand *left, *result;
6460 result=IC_RESULT(ic);
6461 aopOp (left,ic,FALSE);
6462 aopOp (result,ic,FALSE);
6465 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6466 /* get the highest order byte into a */
6467 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6468 if(AOP_TYPE(result) == AOP_CRY){
6469 pic14_emitcode("rlc","a");
6470 pic14_outBitC(result);
6473 pic14_emitcode("rl","a");
6474 pic14_emitcode("anl","a,#0x01");
6475 pic14_outAcc(result);
6479 freeAsmop(left,NULL,ic,TRUE);
6480 freeAsmop(result,NULL,ic,TRUE);
6483 /*-----------------------------------------------------------------*/
6484 /* AccLsh - shift left accumulator by known count */
6485 /* MARK: pic14 always rotates through CARRY! */
6486 /*-----------------------------------------------------------------*/
6487 static void AccLsh (pCodeOp *pcop,int shCount)
6490 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6491 shCount &= 0x0007; // shCount : 0..7
6498 emitpcode(POC_RLF,pcop);
6502 emitpcode(POC_RLF,pcop);
6503 emitpcode(POC_RLF,pcop);
6506 emitpcode(POC_RLF,pcop);
6507 emitpcode(POC_RLF,pcop);
6508 emitpcode(POC_RLF,pcop);
6511 emitpcode(POC_SWAPF,pcop);
6514 emitpcode(POC_SWAPF,pcop);
6515 emitpcode(POC_RLF,pcop);
6518 emitpcode(POC_SWAPF,pcop);
6519 emitpcode(POC_RLF,pcop);
6520 emitpcode(POC_RLF,pcop);
6523 emitpcode(POC_RRFW,pcop);
6524 emitpcode(POC_RRF,pcop);
6527 /* clear invalid bits */
6528 emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6529 emitpcode(POC_ANDWF, pcop);
6532 /*-----------------------------------------------------------------*/
6533 /* AccRsh - shift right accumulator by known count */
6534 /* MARK: pic14 always rotates through CARRY! */
6535 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6536 /* 1: mask out invalid bits (zero-extend) */
6537 /* 2: sign-extend result (pretty slow) */
6538 /*-----------------------------------------------------------------*/
6539 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6542 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6543 shCount &= 0x0007; // shCount : 0..7
6549 /* load sign if needed */
6550 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6551 else if (mask_mode == 1) emitCLRC;
6552 emitpcode(POC_RRF,pcop);
6556 /* load sign if needed */
6557 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6558 emitpcode(POC_RRF,pcop);
6559 /* load sign if needed */
6560 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6561 emitpcode(POC_RRF,pcop);
6562 if (mask_mode == 2) return;
6565 /* load sign if needed */
6566 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6567 emitpcode(POC_RRF,pcop);
6568 /* load sign if needed */
6569 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6570 emitpcode(POC_RRF,pcop);
6571 /* load sign if needed */
6572 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6573 emitpcode(POC_RRF,pcop);
6574 if (mask_mode == 2) return;
6577 emitpcode(POC_SWAPF,pcop);
6580 emitpcode(POC_SWAPF,pcop);
6581 emitpcode(POC_RRF,pcop);
6584 emitpcode(POC_SWAPF,pcop);
6585 emitpcode(POC_RRF,pcop);
6586 emitpcode(POC_RRF,pcop);
6592 emitpcode(POC_RLFW,pcop);
6593 emitpcode(POC_CLRF,pcop);
6595 emitpcode(POC_COMF,pcop);
6598 emitpcode(POC_RLFW,pcop);
6599 emitpcode(POC_RLF,pcop);
6606 /* leave invalid bits undefined */
6610 /* clear invalid bits -- zero-extend */
6611 emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6612 emitpcode(POC_ANDWF, pcop);
6614 if (mask_mode == 2) {
6616 emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6617 emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6618 emitpcode(POC_IORWF, pcop);
6623 /*-----------------------------------------------------------------*/
6624 /* AccSRsh - signed right shift accumulator by known count */
6625 /*-----------------------------------------------------------------*/
6626 static void AccSRsh (int shCount)
6629 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6632 pic14_emitcode("mov","c,acc.7");
6633 pic14_emitcode("rrc","a");
6634 } else if(shCount == 2){
6635 pic14_emitcode("mov","c,acc.7");
6636 pic14_emitcode("rrc","a");
6637 pic14_emitcode("mov","c,acc.7");
6638 pic14_emitcode("rrc","a");
6640 tlbl = newiTempLabel(NULL);
6641 /* rotate right accumulator */
6642 AccRol(8 - shCount);
6643 /* and kill the higher order bits */
6644 pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6645 pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6646 pic14_emitcode("orl","a,#0x%02x",
6647 (unsigned char)~SRMask[shCount]);
6648 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6653 /*-----------------------------------------------------------------*/
6654 /* shiftR1Left2Result - shift right one byte from left to result */
6655 /*-----------------------------------------------------------------*/
6656 static void shiftR1Left2ResultSigned (operand *left, int offl,
6657 operand *result, int offr,
6663 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6665 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6669 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6671 emitpcode(POC_RRF, popGet(AOP(result),offr));
6673 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6674 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6680 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6682 emitpcode(POC_RRF, popGet(AOP(result),offr));
6684 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6685 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6687 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6688 emitpcode(POC_RRF, popGet(AOP(result),offr));
6694 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6696 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6697 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6700 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6701 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6702 emitpcode(POC_ANDLW, popGetLit(0x1f));
6704 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6705 emitpcode(POC_IORLW, popGetLit(0xe0));
6707 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6711 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6712 emitpcode(POC_ANDLW, popGetLit(0x0f));
6713 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6714 emitpcode(POC_IORLW, popGetLit(0xf0));
6715 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6719 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6721 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6722 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6724 emitpcode(POC_RRFW, popGet(AOP(result),offr));
6725 emitpcode(POC_ANDLW, popGetLit(0x07));
6726 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6727 emitpcode(POC_IORLW, popGetLit(0xf8));
6728 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6733 emitpcode(POC_MOVLW, popGetLit(0x00));
6734 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6735 emitpcode(POC_MOVLW, popGetLit(0xfe));
6736 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6737 emitpcode(POC_IORLW, popGetLit(0x01));
6738 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6740 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6741 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6742 emitpcode(POC_DECF, popGet(AOP(result),offr));
6743 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6744 emitpcode(POC_BCF, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6750 emitpcode(POC_MOVLW, popGetLit(0x00));
6751 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6752 emitpcode(POC_MOVLW, popGetLit(0xff));
6753 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6755 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6756 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6757 emitpcode(POC_DECF, popGet(AOP(result),offr));
6765 /*-----------------------------------------------------------------*/
6766 /* shiftR1Left2Result - shift right one byte from left to result */
6767 /*-----------------------------------------------------------------*/
6768 static void shiftR1Left2Result (operand *left, int offl,
6769 operand *result, int offr,
6770 int shCount, int sign)
6775 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6777 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6779 /* Copy the msb into the carry if signed. */
6781 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6791 emitpcode(POC_RRF, popGet(AOP(result),offr));
6793 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6794 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6800 emitpcode(POC_RRF, popGet(AOP(result),offr));
6802 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6803 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6806 emitpcode(POC_RRF, popGet(AOP(result),offr));
6811 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6813 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6814 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6817 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6818 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6819 emitpcode(POC_ANDLW, popGetLit(0x1f));
6820 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6824 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6825 emitpcode(POC_ANDLW, popGetLit(0x0f));
6826 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6830 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6831 emitpcode(POC_ANDLW, popGetLit(0x0f));
6832 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6834 emitpcode(POC_RRF, popGet(AOP(result),offr));
6839 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6840 emitpcode(POC_ANDLW, popGetLit(0x80));
6841 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6842 emitpcode(POC_RLF, popGet(AOP(result),offr));
6843 emitpcode(POC_RLF, popGet(AOP(result),offr));
6848 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6849 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6850 emitpcode(POC_RLF, popGet(AOP(result),offr));
6859 /*-----------------------------------------------------------------*/
6860 /* shiftL1Left2Result - shift left one byte from left to result */
6861 /*-----------------------------------------------------------------*/
6862 static void shiftL1Left2Result (operand *left, int offl,
6863 operand *result, int offr, int shCount)
6869 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6871 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6872 DEBUGpic14_emitcode ("; ***","same = %d",same);
6873 // l = aopGet(AOP(left),offl,FALSE,FALSE);
6875 /* shift left accumulator */
6876 //AccLsh(shCount); // don't comment out just yet...
6877 // aopPut(AOP(result),"a",offr);
6881 /* Shift left 1 bit position */
6882 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6884 emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6886 emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6887 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6891 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6892 emitpcode(POC_ANDLW,popGetLit(0x7e));
6893 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6894 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6897 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6898 emitpcode(POC_ANDLW,popGetLit(0x3e));
6899 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6900 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6901 emitpcode(POC_RLF, popGet(AOP(result),offr));
6904 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6905 emitpcode(POC_ANDLW, popGetLit(0xf0));
6906 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6909 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6910 emitpcode(POC_ANDLW, popGetLit(0xf0));
6911 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6912 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6915 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6916 emitpcode(POC_ANDLW, popGetLit(0x30));
6917 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6918 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6919 emitpcode(POC_RLF, popGet(AOP(result),offr));
6922 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6923 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6924 emitpcode(POC_RRF, popGet(AOP(result),offr));
6928 DEBUGpic14_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6934 /*-----------------------------------------------------------------*/
6935 /* movLeft2Result - move byte from left to result */
6936 /*-----------------------------------------------------------------*/
6937 static void movLeft2Result (operand *left, int offl,
6938 operand *result, int offr)
6942 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6943 if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6944 l = aopGet(AOP(left),offl,FALSE,FALSE);
6946 if (*l == '@' && (IS_AOP_PREG(result))) {
6947 pic14_emitcode("mov","a,%s",l);
6948 aopPut(AOP(result),"a",offr);
6950 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6951 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6956 /*-----------------------------------------------------------------*/
6957 /* shiftLeft_Left2ResultLit - shift left by known count */
6958 /*-----------------------------------------------------------------*/
6960 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6962 int size, same, offr, i;
6964 size = AOP_SIZE(left);
6965 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6967 same = pic14_sameRegs (AOP(left), AOP(result));
6970 shCount = shCount & 0x07;
6976 case 0: /* takes 0 or 2N cycles (for offr==0) */
6977 if (!same || offr) {
6978 for (i=size-1; i >= 0; i--)
6979 movLeft2Result (left, i, result, offr + i);
6983 case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6985 shiftLeft_Left2ResultLit (left, result, 8 * offr);
6986 shiftLeft_Left2ResultLit (result, result, shCount);
6987 return; /* prevent clearing result again */
6990 for (i=0; i < size; i++) {
6991 if (same && !offr) {
6992 emitpcode (POC_RLF, popGet (AOP(left), i));
6994 emitpcode (POC_RLFW, popGet (AOP(left), i));
6995 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7001 case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
7002 /* works in-place/with offr as well */
7003 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
7004 emitpcode (POC_ANDLW, popGetLit (0xF0));
7005 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
7007 for (i = size - 2; i >= 0; i--)
7009 emitpcode (POC_SWAPFW, popGet (AOP(left), i));
7010 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7011 emitpcode (POC_ANDLW, popGetLit (0x0F));
7012 emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
7013 emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
7017 case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
7018 /* works in-place/with offr as well */
7019 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
7020 for (i = size-2; i >= 0; i--) {
7021 emitpcode (POC_RRFW, popGet (AOP(left), i));
7022 emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
7024 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7025 emitpcode (POC_RRF, popGet (AOP(result), offr));
7029 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
7030 shiftLeft_Left2ResultLit (result, result, 1);
7031 return; /* prevent clearing result again */
7037 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7041 /*-----------------------------------------------------------------*/
7042 /* shiftRight_Left2ResultLit - shift right by known count */
7043 /*-----------------------------------------------------------------*/
7045 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
7047 int size, same, offr, i;
7049 size = AOP_SIZE(left);
7050 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7052 same = pic14_sameRegs (AOP(left), AOP(result));
7055 shCount = shCount & 0x07;
7063 case 0: /* takes 0 or 2N cycles (for offr==0) */
7064 if (!same || offr) {
7065 for (i=0; i < size; i++)
7066 movLeft2Result (left, i + offr, result, i);
7070 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7071 emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7073 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7074 shiftRight_Left2ResultLit (result, result, shCount, sign);
7075 return; /* prevent sign-extending result again */
7079 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7082 for (i = size-1; i >= 0; i--) {
7083 if (same && !offr) {
7084 emitpcode (POC_RRF, popGet (AOP(left), i));
7086 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7087 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7093 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7094 /* works in-place/with offr as well */
7095 emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7096 emitpcode (POC_ANDLW, popGetLit (0x0F));
7097 emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7099 for (i = 1; i < size; i++)
7101 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7102 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7103 emitpcode (POC_ANDLW, popGetLit (0xF0));
7104 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7105 emitpcode (POC_XORWF, popGet (AOP(result), i));
7110 emitpcode (POC_MOVLW, popGetLit (0xF0));
7111 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7112 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7116 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7117 /* works in-place/with offr as well */
7118 emitpcode (POC_RLFW, popGet (AOP(left), offr));
7119 for (i = 0; i < size-1; i++) {
7120 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7121 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7123 emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7125 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7128 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7133 shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7134 shiftRight_Left2ResultLit (result, result, 1, sign);
7135 return; /* prevent sign extending result again */
7140 addSign (result, size, sign);
7144 /*-----------------------------------------------------------------*/
7145 /* shiftL2Left2Result - shift left two bytes from left to result */
7146 /*-----------------------------------------------------------------*/
7147 static void shiftL2Left2Result (operand *left, int offl,
7148 operand *result, int offr, int shCount)
7152 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7154 if(pic14_sameRegs(AOP(result), AOP(left))) {
7162 emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7163 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7164 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7168 emitpcode(POC_RLF, popGet(AOP(result),offr));
7169 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7175 emitpcode(POC_MOVLW, popGetLit(0x0f));
7176 emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7177 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7178 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7179 emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7180 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7181 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7183 emitpcode(POC_RLF, popGet(AOP(result),offr));
7184 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7188 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7189 emitpcode(POC_RRF, popGet(AOP(result),offr));
7190 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7191 emitpcode(POC_RRF, popGet(AOP(result),offr));
7192 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7193 emitpcode(POC_ANDLW,popGetLit(0xc0));
7194 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7195 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7196 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7197 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7200 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7201 emitpcode(POC_RRFW, popGet(AOP(result),offr));
7202 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7203 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7204 emitpcode(POC_RRF, popGet(AOP(result),offr));
7214 /* note, use a mov/add for the shift since the mov has a
7215 chance of getting optimized out */
7216 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7217 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7218 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7219 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7220 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7224 emitpcode(POC_RLF, popGet(AOP(result),offr));
7225 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7231 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7232 emitpcode(POC_ANDLW, popGetLit(0xF0));
7233 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7234 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7235 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7236 emitpcode(POC_ANDLW, popGetLit(0xF0));
7237 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7238 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7242 emitpcode(POC_RLF, popGet(AOP(result),offr));
7243 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7247 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7248 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7249 emitpcode(POC_RRFW, popGet(AOP(result),offl));
7250 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7252 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7253 emitpcode(POC_RRF, popGet(AOP(result),offr));
7254 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7255 emitpcode(POC_ANDLW,popGetLit(0xc0));
7256 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7257 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7258 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7259 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7262 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7263 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7264 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7265 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7266 emitpcode(POC_RRF, popGet(AOP(result),offr));
7272 /*-----------------------------------------------------------------*/
7273 /* shiftR2Left2Result - shift right two bytes from left to result */
7274 /*-----------------------------------------------------------------*/
7275 static void shiftR2Left2Result (operand *left, int offl,
7276 operand *result, int offr,
7277 int shCount, int sign)
7282 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7283 same = pic14_sameRegs(AOP(result), AOP(left));
7285 if(same && ((offl + MSB16) == offr)){
7287 /* don't crash result[offr] */
7288 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7289 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7292 movLeft2Result(left,offl, result, offr);
7293 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7296 /* a:x >> shCount (x = lsb(result))*/
7299 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7301 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7310 emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7315 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7316 emitpcode(POC_RRF,popGet(AOP(result),offr));
7318 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7319 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7320 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7321 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7326 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7329 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7330 emitpcode(POC_RRF,popGet(AOP(result),offr));
7337 emitpcode(POC_MOVLW, popGetLit(0xf0));
7338 emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7339 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7341 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7342 emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7343 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7344 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7346 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7347 emitpcode(POC_ANDLW, popGetLit(0x0f));
7348 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7350 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7351 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7352 emitpcode(POC_ANDLW, popGetLit(0xf0));
7353 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7354 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7358 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7359 emitpcode(POC_RRF, popGet(AOP(result),offr));
7363 emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7364 emitpcode(POC_BTFSC,
7365 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7366 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7374 emitpcode(POC_RLF, popGet(AOP(result),offr));
7375 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7377 emitpcode(POC_RLF, popGet(AOP(result),offr));
7378 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7379 emitpcode(POC_RLFW, popGet(AOP(result),offr));
7380 emitpcode(POC_ANDLW,popGetLit(0x03));
7382 emitpcode(POC_BTFSC,
7383 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7384 emitpcode(POC_IORLW,popGetLit(0xfc));
7386 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7387 emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7388 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7389 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7391 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7392 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7393 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7394 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7395 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7396 emitpcode(POC_RLF, popGet(AOP(result),offr));
7397 emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7398 emitpcode(POC_ANDLW,popGetLit(0x03));
7400 emitpcode(POC_BTFSC,
7401 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7402 emitpcode(POC_IORLW,popGetLit(0xfc));
7404 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7405 //emitpcode(POC_RLF, popGet(AOP(result),offr));
7412 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7413 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7414 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7415 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7418 emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7420 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7424 /*-----------------------------------------------------------------*/
7425 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7426 /*-----------------------------------------------------------------*/
7427 static void shiftLLeftOrResult (operand *left, int offl,
7428 operand *result, int offr, int shCount)
7431 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7433 /* shift left accumulator */
7434 AccLsh(left,offl,shCount);
7435 /* or with result */
7436 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7437 assert ( !"broken (modifies left, fails for left==result))" );
7440 /*-----------------------------------------------------------------*/
7441 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7442 /*-----------------------------------------------------------------*/
7443 static void shiftRLeftOrResult (operand *left, int offl,
7444 operand *result, int offr, int shCount)
7447 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7449 /* shift right accumulator */
7450 AccRsh(left,offl,shCount);
7451 /* or with result */
7452 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7453 assert ( !"broken (modifies left, fails for left==result))" );
7456 /*-----------------------------------------------------------------*/
7457 /* genlshOne - left shift a one byte quantity by known count */
7458 /*-----------------------------------------------------------------*/
7459 static void genlshOne (operand *result, operand *left, int shCount)
7462 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7463 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7466 /*-----------------------------------------------------------------*/
7467 /* genlshTwo - left shift two bytes by known amount != 0 */
7468 /*-----------------------------------------------------------------*/
7469 static void genlshTwo (operand *result,operand *left, int shCount)
7474 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7475 size = pic14_getDataSize(result);
7477 /* if shCount >= 8 */
7483 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7485 movLeft2Result(left, LSB, result, MSB16);
7487 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7490 /* 1 <= shCount <= 7 */
7493 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7495 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7499 /*-----------------------------------------------------------------*/
7500 /* shiftLLong - shift left one long from left to result */
7501 /* offl = LSB or MSB16 */
7502 /*-----------------------------------------------------------------*/
7503 static void shiftLLong (operand *left, operand *result, int offr )
7506 int size = AOP_SIZE(result);
7509 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7510 if(size >= LSB+offr){
7511 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7513 pic14_emitcode("add","a,acc");
7514 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7515 size >= MSB16+offr && offr != LSB )
7516 pic14_emitcode("xch","a,%s",
7517 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7519 aopPut(AOP(result),"a",LSB+offr);
7522 if(size >= MSB16+offr){
7523 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7524 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7527 pic14_emitcode("rlc","a");
7528 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7529 size >= MSB24+offr && offr != LSB)
7530 pic14_emitcode("xch","a,%s",
7531 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7533 aopPut(AOP(result),"a",MSB16+offr);
7536 if(size >= MSB24+offr){
7537 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7538 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7541 pic14_emitcode("rlc","a");
7542 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7543 size >= MSB32+offr && offr != LSB )
7544 pic14_emitcode("xch","a,%s",
7545 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7547 aopPut(AOP(result),"a",MSB24+offr);
7550 if(size > MSB32+offr){
7551 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7552 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7555 pic14_emitcode("rlc","a");
7556 aopPut(AOP(result),"a",MSB32+offr);
7559 aopPut(AOP(result),zero,LSB);
7562 /*-----------------------------------------------------------------*/
7563 /* genlshFour - shift four byte by a known amount != 0 */
7564 /*-----------------------------------------------------------------*/
7565 static void genlshFour (operand *result, operand *left, int shCount)
7570 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7571 size = AOP_SIZE(result);
7573 /* if shifting more that 3 bytes */
7574 if (shCount >= 24 ) {
7577 /* lowest order of left goes to the highest
7578 order of the destination */
7579 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7581 movLeft2Result(left, LSB, result, MSB32);
7582 aopPut(AOP(result),zero,LSB);
7583 aopPut(AOP(result),zero,MSB16);
7584 aopPut(AOP(result),zero,MSB32);
7588 /* more than two bytes */
7589 else if ( shCount >= 16 ) {
7590 /* lower order two bytes goes to higher order two bytes */
7592 /* if some more remaining */
7594 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7596 movLeft2Result(left, MSB16, result, MSB32);
7597 movLeft2Result(left, LSB, result, MSB24);
7599 aopPut(AOP(result),zero,MSB16);
7600 aopPut(AOP(result),zero,LSB);
7604 /* if more than 1 byte */
7605 else if ( shCount >= 8 ) {
7606 /* lower order three bytes goes to higher order three bytes */
7610 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7612 movLeft2Result(left, LSB, result, MSB16);
7614 else{ /* size = 4 */
7616 movLeft2Result(left, MSB24, result, MSB32);
7617 movLeft2Result(left, MSB16, result, MSB24);
7618 movLeft2Result(left, LSB, result, MSB16);
7619 aopPut(AOP(result),zero,LSB);
7621 else if(shCount == 1)
7622 shiftLLong(left, result, MSB16);
7624 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7625 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7626 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7627 aopPut(AOP(result),zero,LSB);
7632 /* 1 <= shCount <= 7 */
7633 else if(shCount <= 2){
7634 shiftLLong(left, result, LSB);
7636 shiftLLong(result, result, LSB);
7638 /* 3 <= shCount <= 7, optimize */
7640 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7641 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7642 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7648 /*-----------------------------------------------------------------*/
7649 /* genLeftShiftLiteral - left shifting by known count */
7650 /*-----------------------------------------------------------------*/
7651 static void genLeftShiftLiteral (operand *left,
7656 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7660 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7661 freeAsmop(right,NULL,ic,TRUE);
7663 aopOp(left,ic,FALSE);
7664 aopOp(result,ic,FALSE);
7666 size = getSize(operandType(result));
7669 pic14_emitcode("; shift left ","result %d, left %d",size,
7673 /* I suppose that the left size >= result size */
7676 movLeft2Result(left, size, result, size);
7680 else if(shCount >= (size * 8))
7682 aopPut(AOP(result),zero,size);
7686 genlshOne (result,left,shCount);
7691 genlshTwo (result,left,shCount);
7695 genlshFour (result,left,shCount);
7699 freeAsmop(left,NULL,ic,TRUE);
7700 freeAsmop(result,NULL,ic,TRUE);
7704 /*-----------------------------------------------------------------*
7705 * genMultiAsm - repeat assembly instruction for size of register.
7706 * if endian == 1, then the high byte (i.e base address + size of
7707 * register) is used first else the low byte is used first;
7708 *-----------------------------------------------------------------*/
7709 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7715 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7728 emitpcode(poc, popGet(AOP(reg),offset));
7735 /*-----------------------------------------------------------------*/
7736 /* genLeftShift - generates code for left shifting */
7737 /*-----------------------------------------------------------------*/
7738 static void genLeftShift (iCode *ic)
7740 operand *left,*right, *result;
7742 unsigned long lit = 0L;
7744 symbol *tlbl , *tlbl1;
7748 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7750 right = IC_RIGHT(ic);
7752 result = IC_RESULT(ic);
7754 aopOp(right,ic,FALSE);
7755 aopOp(left,ic,FALSE);
7756 aopOp(result,ic,FALSE);
7759 /* if the shift count is known then do it
7760 as efficiently as possible */
7761 if (AOP_TYPE(right) == AOP_LIT) {
7762 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7766 /* shift count is unknown then we have to form
7767 a loop get the loop count in B : Note: we take
7768 only the lower order byte since shifting
7769 more that 32 bits make no sense anyway, ( the
7770 largest size of an object can be only 32 bits ) */
7772 /* this code fails for RIGHT == RESULT */
7773 assert (!pic14_sameRegs (AOP(right), AOP(result)));
7775 /* now move the left to the result if they are not the
7777 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
7778 AOP_SIZE(result) > 1) {
7780 size = AOP_SIZE(result);
7783 l = aopGet(AOP(left),offset,FALSE,TRUE);
7784 if (*l == '@' && (IS_AOP_PREG(result))) {
7786 pic14_emitcode("mov","a,%s",l);
7787 aopPut(AOP(result),"a",offset);
7789 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
7790 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7791 //aopPut(AOP(result),l,offset);
7797 if(AOP_TYPE(left) == AOP_LIT)
7798 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7800 size = AOP_SIZE(result);
7802 /* if it is only one byte then */
7804 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7805 emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7806 emitpcode(POC_ANDLW, popGetLit(0xf0));
7807 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7808 emitpcode(POC_MOVFW, popGet(AOP(left),0));
7809 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7810 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7811 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7812 emitpcode(POC_RLFW, popGet(AOP(result),0));
7813 emitpcode(POC_ANDLW, popGetLit(0xfe));
7814 emitpcode(POC_ADDFW, popGet(AOP(result),0));
7815 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7816 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7819 tlbl = newiTempLabel(NULL);
7820 if (!pic14_sameRegs(AOP(left),AOP(result))) {
7821 mov2w (AOP(left), 0);
7822 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7825 emitpcode(POC_COMFW, popGet(AOP(right),0));
7826 emitpcode(POC_RRF, popGet(AOP(result),0));
7827 emitpLabel(tlbl->key);
7828 emitpcode(POC_RLF, popGet(AOP(result),0));
7829 emitpcode(POC_ADDLW, popGetLit(1));
7831 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7836 if (pic14_sameRegs(AOP(left),AOP(result))) {
7838 tlbl = newiTempLabel(NULL);
7839 emitpcode(POC_COMFW, popGet(AOP(right),0));
7840 genMultiAsm(POC_RRF, result, size,1);
7841 emitpLabel(tlbl->key);
7842 genMultiAsm(POC_RLF, result, size,0);
7843 emitpcode(POC_ADDLW, popGetLit(1));
7845 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7849 //tlbl = newiTempLabel(NULL);
7851 //tlbl1 = newiTempLabel(NULL);
7853 //reAdjustPreg(AOP(result));
7855 //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7856 //pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7857 //l = aopGet(AOP(result),offset,FALSE,FALSE);
7859 //pic14_emitcode("add","a,acc");
7860 //aopPut(AOP(result),"a",offset++);
7862 // l = aopGet(AOP(result),offset,FALSE,FALSE);
7864 // pic14_emitcode("rlc","a");
7865 // aopPut(AOP(result),"a",offset++);
7867 //reAdjustPreg(AOP(result));
7869 //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7870 //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7873 tlbl = newiTempLabel(NULL);
7874 tlbl1= newiTempLabel(NULL);
7876 size = AOP_SIZE(result);
7879 pctemp = popGetTempReg(); /* grab a temporary working register. */
7881 emitpcode(POC_MOVFW, popGet(AOP(right),0));
7883 /* offset should be 0, 1 or 3 */
7884 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7886 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
7888 emitpcode(POC_MOVWF, pctemp);
7891 emitpLabel(tlbl->key);
7894 emitpcode(POC_RLF, popGet(AOP(result),0));
7896 emitpcode(POC_RLF, popGet(AOP(result),offset++));
7898 emitpcode(POC_DECFSZ, pctemp);
7899 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7900 emitpLabel(tlbl1->key);
7902 popReleaseTempReg(pctemp);
7906 freeAsmop (right,NULL,ic,TRUE);
7907 freeAsmop(left,NULL,ic,TRUE);
7908 freeAsmop(result,NULL,ic,TRUE);
7913 /*-----------------------------------------------------------------*/
7914 /* genrshOne - right shift a one byte quantity by known count */
7915 /*-----------------------------------------------------------------*/
7916 static void genrshOne (operand *result, operand *left,
7917 int shCount, int sign)
7920 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7921 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7924 /*-----------------------------------------------------------------*/
7925 /* genrshTwo - right shift two bytes by known amount != 0 */
7926 /*-----------------------------------------------------------------*/
7927 static void genrshTwo (operand *result,operand *left,
7928 int shCount, int sign)
7931 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7932 /* if shCount >= 8 */
7936 shiftR1Left2Result(left, MSB16, result, LSB,
7939 movLeft2Result(left, MSB16, result, LSB);
7941 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7944 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7945 emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7949 /* 1 <= shCount <= 7 */
7951 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
7954 /*-----------------------------------------------------------------*/
7955 /* shiftRLong - shift right one long from left to result */
7956 /* offl = LSB or MSB16 */
7957 /*-----------------------------------------------------------------*/
7958 static void shiftRLong (operand *left, int offl,
7959 operand *result, int sign)
7964 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7966 size = AOP_SIZE(left);
7967 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7970 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7974 assert (offl >= 0 && offl < size);
7976 same = pic14_sameRegs (AOP(left), AOP(result));
7978 /* perform the shift */
7981 if (same && !offl) {
7982 emitpcode (POC_RRF, popGet (AOP(result), size));
7984 emitpcode (POC_RRFW, popGet (AOP(left), size));
7985 emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7989 addSign (result, AOP_SIZE(left) - offl, sign);
7992 /*-----------------------------------------------------------------*/
7993 /* genrshFour - shift four byte by a known amount != 0 */
7994 /*-----------------------------------------------------------------*/
7995 static void genrshFour (operand *result, operand *left,
7996 int shCount, int sign)
7999 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8000 /* if shifting more that 3 bytes */
8001 if(shCount >= 24 ) {
8004 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8006 movLeft2Result(left, MSB32, result, LSB);
8008 addSign(result, MSB16, sign);
8010 else if(shCount >= 16){
8013 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8015 movLeft2Result(left, MSB24, result, LSB);
8016 movLeft2Result(left, MSB32, result, MSB16);
8018 addSign(result, MSB24, sign);
8020 else if(shCount >= 8){
8023 shiftRLong(left, MSB16, result, sign);
8024 else if(shCount == 0){
8025 movLeft2Result(left, MSB16, result, LSB);
8026 movLeft2Result(left, MSB24, result, MSB16);
8027 movLeft2Result(left, MSB32, result, MSB24);
8028 addSign(result, MSB32, sign);
8031 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8032 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8033 /* the last shift is signed */
8034 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8035 addSign(result, MSB32, sign);
8038 else{ /* 1 <= shCount <= 7 */
8040 shiftRLong(left, LSB, result, sign);
8042 shiftRLong(result, LSB, result, sign);
8045 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8046 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8047 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8052 /*-----------------------------------------------------------------*/
8053 /* genRightShiftLiteral - right shifting by known count */
8054 /*-----------------------------------------------------------------*/
8055 static void genRightShiftLiteral (operand *left,
8061 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8065 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8066 freeAsmop(right,NULL,ic,TRUE);
8068 aopOp(left,ic,FALSE);
8069 aopOp(result,ic,FALSE);
8072 pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8076 lsize = pic14_getDataSize(left);
8077 res_size = pic14_getDataSize(result);
8078 /* test the LEFT size !!! */
8080 /* I suppose that the left size >= result size */
8083 movLeft2Result(left, res_size, result, res_size);
8086 else if(shCount >= (lsize * 8)){
8089 emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8091 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8092 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8097 emitpcode(POC_MOVLW, popGetLit(0));
8098 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8099 emitpcode(POC_MOVLW, popGetLit(0xff));
8101 emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8106 emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8113 genrshOne (result,left,shCount,sign);
8117 genrshTwo (result,left,shCount,sign);
8121 genrshFour (result,left,shCount,sign);
8129 freeAsmop(left,NULL,ic,TRUE);
8130 freeAsmop(result,NULL,ic,TRUE);
8135 /*-----------------------------------------------------------------*/
8136 /* genSignedRightShift - right shift of signed number */
8137 /*-----------------------------------------------------------------*/
8138 static void genSignedRightShift (iCode *ic)
8140 operand *right, *left, *result;
8143 symbol *tlbl, *tlbl1 ;
8146 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8148 /* we do it the hard way put the shift count in b
8149 and loop thru preserving the sign */
8151 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8153 right = IC_RIGHT(ic);
8155 result = IC_RESULT(ic);
8157 aopOp(right,ic,FALSE);
8158 aopOp(left,ic,FALSE);
8159 aopOp(result,ic,FALSE);
8162 if ( AOP_TYPE(right) == AOP_LIT) {
8163 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8164 //genRightShiftLiteral (left,right,result,ic,1);
8167 /* shift count is unknown then we have to form
8168 a loop get the loop count in B : Note: we take
8169 only the lower order byte since shifting
8170 more that 32 bits make no sense anyway, ( the
8171 largest size of an object can be only 32 bits ) */
8173 //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8174 //pic14_emitcode("inc","b");
8175 //freeAsmop (right,NULL,ic,TRUE);
8176 //aopOp(left,ic,FALSE);
8177 //aopOp(result,ic,FALSE);
8179 /* now move the left to the result if they are not the
8181 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
8182 AOP_SIZE(result) > 1) {
8184 size = AOP_SIZE(result);
8188 l = aopGet(AOP(left),offset,FALSE,TRUE);
8189 if (*l == '@' && IS_AOP_PREG(result)) {
8190 pic14_emitcode("mov","a,%s",l);
8191 aopPut(AOP(result),"a",offset);
8193 aopPut(AOP(result),l,offset);
8195 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8196 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8202 /* mov the highest order bit to OVR */
8203 tlbl = newiTempLabel(NULL);
8204 tlbl1= newiTempLabel(NULL);
8206 size = AOP_SIZE(result);
8209 pctemp = popGetTempReg(); /* grab a temporary working register. */
8211 emitpcode(POC_MOVFW, popGet(AOP(right),0));
8213 /* offset should be 0, 1 or 3 */
8214 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8216 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8218 emitpcode(POC_MOVWF, pctemp);
8221 emitpLabel(tlbl->key);
8223 emitpcode(POC_RLFW, popGet(AOP(result),offset));
8224 emitpcode(POC_RRF, popGet(AOP(result),offset));
8227 emitpcode(POC_RRF, popGet(AOP(result),--offset));
8230 emitpcode(POC_DECFSZ, pctemp);
8231 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8232 emitpLabel(tlbl1->key);
8234 popReleaseTempReg(pctemp);
8236 size = AOP_SIZE(result);
8238 pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8239 pic14_emitcode("rlc","a");
8240 pic14_emitcode("mov","ov,c");
8241 /* if it is only one byte then */
8243 l = aopGet(AOP(left),0,FALSE,FALSE);
8245 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8246 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8247 pic14_emitcode("mov","c,ov");
8248 pic14_emitcode("rrc","a");
8249 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8250 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8251 aopPut(AOP(result),"a",0);
8255 reAdjustPreg(AOP(result));
8256 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8257 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8258 pic14_emitcode("mov","c,ov");
8260 l = aopGet(AOP(result),offset,FALSE,FALSE);
8262 pic14_emitcode("rrc","a");
8263 aopPut(AOP(result),"a",offset--);
8265 reAdjustPreg(AOP(result));
8266 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8267 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8272 freeAsmop(left,NULL,ic,TRUE);
8273 freeAsmop(result,NULL,ic,TRUE);
8274 freeAsmop(right,NULL,ic,TRUE);
8278 /*-----------------------------------------------------------------*/
8279 /* loadSignToC - load the operand's sign bit into CARRY */
8280 /*-----------------------------------------------------------------*/
8282 static void loadSignToC (operand *op)
8285 assert (op && AOP(op) && AOP_SIZE(op));
8288 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8292 /*-----------------------------------------------------------------*/
8293 /* genRightShift - generate code for right shifting */
8294 /*-----------------------------------------------------------------*/
8295 static void genGenericShift (iCode *ic, int shiftRight)
8297 operand *right, *left, *result;
8300 symbol *tlbl, *tlbl1, *inverselbl;
8303 /* if signed then we do it the hard way preserve the
8304 sign bit moving it inwards */
8305 retype = getSpec(operandType(IC_RESULT(ic)));
8306 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8308 /* signed & unsigned types are treated the same : i.e. the
8309 signed is NOT propagated inwards : quoting from the
8310 ANSI - standard : "for E1 >> E2, is equivalent to division
8311 by 2**E2 if unsigned or if it has a non-negative value,
8312 otherwise the result is implementation defined ", MY definition
8313 is that the sign does not get propagated */
8315 right = IC_RIGHT(ic);
8317 result = IC_RESULT(ic);
8319 aopOp(right,ic,FALSE);
8320 aopOp(left,ic,FALSE);
8321 aopOp(result,ic,FALSE);
8323 /* if the shift count is known then do it
8324 as efficiently as possible */
8325 if (AOP_TYPE(right) == AOP_LIT) {
8326 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8330 shiftRight = !shiftRight;
8334 shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8336 shiftLeft_Left2ResultLit (left, result, lit);
8337 //genRightShiftLiteral (left,right,result,ic, 0);
8341 /* shift count is unknown then we have to form
8342 a loop get the loop count in B : Note: we take
8343 only the lower order byte since shifting
8344 more that 32 bits make no sense anyway, ( the
8345 largest size of an object can be only 32 bits ) */
8347 /* we must not overwrite the shift counter */
8348 assert (!pic14_sameRegs(AOP(right),AOP(result)));
8350 /* now move the left to the result if they are not the
8352 if (!pic14_sameRegs(AOP(left),AOP(result)))
8354 size = min(AOP_SIZE(result), AOP_SIZE(left));
8356 mov2w(AOP(left), size);
8357 movwf(AOP(result), size);
8359 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8362 tlbl = newiTempLabel(NULL);
8363 tlbl1= newiTempLabel(NULL);
8365 size = AOP_SIZE(result);
8367 mov2w(AOP(right),0);
8368 if (!SPEC_USIGN(operandType(right)))
8370 inverselbl = newiTempLabel(NULL);
8371 /* signed shift count -- invert shift direction for c<0 */
8372 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8373 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8375 emitpcode(POC_SUBLW, popGetLit(0)); /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8376 /* check for `a = b >> c' with `-c == 0' */
8378 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8379 emitpLabel(tlbl->key);
8380 /* propagate the sign bit inwards for SIGNED result */
8381 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8382 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8383 emitpcode(POC_ADDLW, popGetLit(1)); /* clears CARRY (unless W==0 afterwards) */
8385 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8387 if (!SPEC_USIGN(operandType(right)))
8389 symbol *inv_loop = newiTempLabel(NULL);
8391 shiftRight = !shiftRight; /* invert shift direction */
8393 /* we came here from the code above -- we are done */
8394 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8396 /* emit code for shifting N<0 steps, count is already in W */
8397 emitpLabel(inverselbl->key);
8398 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8399 emitpLabel(inv_loop->key);
8400 /* propagate the sign bit inwards for SIGNED result */
8401 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8402 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8403 emitpcode(POC_ADDLW, popGetLit(1));
8405 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8408 emitpLabel(tlbl1->key);
8410 freeAsmop(left,NULL,ic,TRUE);
8411 freeAsmop (right,NULL,ic,TRUE);
8412 freeAsmop(result,NULL,ic,TRUE);
8415 static void genRightShift (iCode *ic)
8417 genGenericShift(ic, 1);
8420 static void genLeftShift (iCode *ic)
8422 genGenericShift(ic, 0);
8425 /*-----------------------------------------------------------------*/
8426 /* SetIrp - Set IRP bit */
8427 /*-----------------------------------------------------------------*/
8428 void SetIrp(operand *result) {
8430 if (AOP_TYPE(result) == AOP_LIT) {
8431 unsigned lit = (unsigned)operandLitValue(result);
8437 if (PCOP(AOP(result))->type == PO_LITERAL) {
8438 int addrs = PCOL(AOP(result))->lit;
8444 emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8445 if(AOP_SIZE(result) > 1) {
8446 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8454 setup_fsr (operand *ptr)
8457 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8459 /* also setup-up IRP */
8463 /*-----------------------------------------------------------------*/
8464 /* emitPtrByteGet - emits code to get a byte into WREG from an */
8465 /* arbitrary pointer (__code, __data, generic) */
8466 /*-----------------------------------------------------------------*/
8468 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8475 if (!alreadyAddressed) setup_fsr (src);
8476 emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8480 assert( AOP_SIZE(src) == 2 );
8482 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8484 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8485 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
8486 call_libraryfunc ("__gptrget1");
8490 assert( AOP_SIZE(src) == 3 );
8492 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8494 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8496 call_libraryfunc ("__gptrget1");
8500 assert( !"unhandled pointer type" );
8505 /*-----------------------------------------------------------------*/
8506 /* emitPtrByteSet - emits code to set a byte from src through a */
8507 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR). */
8508 /*-----------------------------------------------------------------*/
8510 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8517 if (!alreadyAddressed) setup_fsr (dst);
8518 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8522 assert( !"trying to assign to __code pointer" );
8526 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8528 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8530 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8532 call_libraryfunc ("__gptrput1");
8536 assert( !"unhandled pointer type" );
8541 /*-----------------------------------------------------------------*/
8542 /* genUnpackBits - generates code for unpacking bits */
8543 /*-----------------------------------------------------------------*/
8544 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8546 int rsize; /* result size */
8547 sym_link *etype; /* bitfield type information */
8548 int blen; /* bitfield length */
8549 int bstr; /* bitfield starting bit within byte */
8552 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8553 etype = getSpec(operandType(result));
8554 rsize = getSize (operandType (result));
8555 blen = SPEC_BLEN (etype);
8556 bstr = SPEC_BSTR (etype);
8558 /* single bit field case */
8560 if (ifx) { /* that is for an if statement */
8563 resolveIfx(&rIfx,ifx);
8564 if (ptype == -1) /* direct */
8565 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8567 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8568 emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8569 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8573 assert (!pic14_sameRegs (AOP(result), AOP(left)));
8574 for (i=0; i < AOP_SIZE(result); i++)
8575 emitpcode (POC_CLRF, popGet (AOP(result), i));
8580 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8581 /* adjust result below */
8588 emitPtrByteGet (left, ptype, FALSE);
8589 emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8591 /* adjust result below */
8595 assert( !"unhandled pointer type" );
8598 /* move sign-/zero extended bit to result */
8599 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8600 emitpcode (POC_INCF, popGet (AOP(result), 0));
8602 emitpcode (POC_DECF, popGet (AOP(result), 0));
8604 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8608 else if (blen <= 8 && ((blen + bstr) <= 8))
8613 for (i=0; i < AOP_SIZE(result); i++)
8614 emitpcode (POC_CLRF, popGet (AOP(result), i));
8619 mov2w(AOP(left), 0);
8626 emitPtrByteGet (left, ptype, FALSE);
8630 assert( !"unhandled pointer type" );
8634 emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8635 movwf(AOP(result), 0);
8636 AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8638 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8640 /* signed bitfield */
8641 assert (bstr + blen > 0);
8642 emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8643 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8644 emitpcode(POC_IORWF, popGet(AOP(result),0));
8646 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8650 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8654 /*-----------------------------------------------------------------*/
8655 /* genDataPointerGet - generates code when ptr offset is known */
8656 /*-----------------------------------------------------------------*/
8657 static void genDataPointerGet (operand *left,
8661 int size , offset = 0;
8664 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8667 /* optimization - most of the time, left and result are the same
8668 * address, but different types. for the pic code, we could omit
8671 aopOp(result,ic,TRUE);
8673 if (pic14_sameRegs (AOP(left), AOP(result)))
8676 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8678 //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8680 size = AOP_SIZE(result);
8681 if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8685 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8686 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8690 freeAsmop(left,NULL,ic,TRUE);
8691 freeAsmop(result,NULL,ic,TRUE);
8695 /*-----------------------------------------------------------------*/
8696 /* genNearPointerGet - pic14_emitcode for near pointer fetch */
8697 /*-----------------------------------------------------------------*/
8698 static void genNearPointerGet (operand *left,
8703 sym_link *ltype = operandType(left);
8704 sym_link *rtype = operandType(result);
8705 sym_link *retype= getSpec(rtype); /* bitfield type information */
8709 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8712 aopOp(left,ic,FALSE);
8714 /* if left is rematerialisable and
8715 result is not bit variable type and
8716 the left is pointer to data space i.e
8717 lower 128 bytes of space */
8718 if (AOP_TYPE(left) == AOP_PCODE && //AOP_TYPE(left) == AOP_IMMD &&
8719 !IS_BITVAR(retype) &&
8720 PIC_IS_DATA_PTR(ltype)) {
8721 genDataPointerGet (left,result,ic);
8725 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8726 aopOp (result,ic,FALSE);
8728 /* Check if can access directly instead of via a pointer */
8729 if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8730 && AOP_SIZE(result) == 1)
8735 if (IS_BITFIELD(getSpec(operandType(result))))
8737 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8741 /* If the pointer value is not in a the FSR then need to put it in */
8742 /* Must set/reset IRP bit for use with FSR. */
8747 /* if bitfield then unpack the bits */
8749 /* we have can just get the values */
8750 int size = AOP_SIZE(result);
8753 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8757 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8759 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8760 if (AOP_TYPE(result) == AOP_LIT) {
8761 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8763 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8765 if (size && !direct)
8766 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8771 /* now some housekeeping stuff */
8773 /* we had to allocate for this iCode */
8774 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8775 freeAsmop(NULL,aop,ic,TRUE);
8777 /* we did not allocate which means left
8778 already in a pointer register, then
8779 if size > 0 && this could be used again
8780 we have to point it back to where it
8782 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8783 if (AOP_SIZE(result) > 1 &&
8784 !OP_SYMBOL(left)->remat &&
8785 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8787 int size = AOP_SIZE(result) - 1;
8789 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8795 freeAsmop(left,NULL,ic,TRUE);
8796 freeAsmop(result,NULL,ic,TRUE);
8801 /*-----------------------------------------------------------------*/
8802 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch */
8803 /*-----------------------------------------------------------------*/
8804 static void genPagedPointerGet (operand *left,
8811 sym_link *rtype, *retype;
8814 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8816 rtype = operandType(result);
8817 retype= getSpec(rtype);
8819 aopOp(left,ic,FALSE);
8821 /* if the value is already in a pointer register
8822 then don't need anything more */
8823 if (!AOP_INPREG(AOP(left))) {
8824 /* otherwise get a free pointer register */
8826 preg = getFreePtr(ic,&aop,FALSE);
8827 pic14_emitcode("mov","%s,%s",
8829 aopGet(AOP(left),0,FALSE,TRUE));
8830 rname = preg->name ;
8832 rname = aopGet(AOP(left),0,FALSE,FALSE);
8834 freeAsmop(left,NULL,ic,TRUE);
8835 aopOp (result,ic,FALSE);
8837 /* if bitfield then unpack the bits */
8838 if (IS_BITFIELD(retype))
8839 genUnpackBits (result,left,rname,PPOINTER,0);
8841 /* we have can just get the values */
8842 int size = AOP_SIZE(result);
8847 pic14_emitcode("movx","a,@%s",rname);
8848 aopPut(AOP(result),"a",offset);
8853 pic14_emitcode("inc","%s",rname);
8857 /* now some housekeeping stuff */
8859 /* we had to allocate for this iCode */
8860 freeAsmop(NULL,aop,ic,TRUE);
8862 /* we did not allocate which means left
8863 already in a pointer register, then
8864 if size > 0 && this could be used again
8865 we have to point it back to where it
8867 if (AOP_SIZE(result) > 1 &&
8868 !OP_SYMBOL(left)->remat &&
8869 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8871 int size = AOP_SIZE(result) - 1;
8873 pic14_emitcode("dec","%s",rname);
8878 freeAsmop(result,NULL,ic,TRUE);
8883 /*-----------------------------------------------------------------*/
8884 /* genFarPointerGet - gget value from far space */
8885 /*-----------------------------------------------------------------*/
8886 static void genFarPointerGet (operand *left,
8887 operand *result, iCode *ic)
8890 sym_link *retype = getSpec(operandType(result));
8893 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8895 aopOp(left,ic,FALSE);
8897 /* if the operand is already in dptr
8898 then we do nothing else we move the value to dptr */
8899 if (AOP_TYPE(left) != AOP_STR) {
8900 /* if this is remateriazable */
8901 if (AOP_TYPE(left) == AOP_IMMD)
8902 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8903 else { /* we need to get it byte by byte */
8904 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8905 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8906 if (options.model == MODEL_FLAT24)
8908 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8912 /* so dptr know contains the address */
8913 freeAsmop(left,NULL,ic,TRUE);
8914 aopOp(result,ic,FALSE);
8916 /* if bit then unpack */
8917 if (IS_BITFIELD(retype))
8918 genUnpackBits(result,left,"dptr",FPOINTER,0);
8920 size = AOP_SIZE(result);
8924 pic14_emitcode("movx","a,@dptr");
8925 aopPut(AOP(result),"a",offset++);
8927 pic14_emitcode("inc","dptr");
8931 freeAsmop(result,NULL,ic,TRUE);
8936 /*-----------------------------------------------------------------*/
8937 /* genCodePointerGet - get value from code space */
8938 /*-----------------------------------------------------------------*/
8939 static void genCodePointerGet (operand *left,
8940 operand *result, iCode *ic)
8943 sym_link *retype = getSpec(operandType(result));
8945 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8947 aopOp(left,ic,FALSE);
8949 /* if the operand is already in dptr
8950 then we do nothing else we move the value to dptr */
8951 if (AOP_TYPE(left) != AOP_STR) {
8952 /* if this is remateriazable */
8953 if (AOP_TYPE(left) == AOP_IMMD)
8954 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8955 else { /* we need to get it byte by byte */
8956 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8957 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8958 if (options.model == MODEL_FLAT24)
8960 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8964 /* so dptr know contains the address */
8965 freeAsmop(left,NULL,ic,TRUE);
8966 aopOp(result,ic,FALSE);
8968 /* if bit then unpack */
8969 if (IS_BITFIELD(retype))
8970 genUnpackBits(result,left,"dptr",CPOINTER,0);
8972 size = AOP_SIZE(result);
8976 pic14_emitcode("clr","a");
8977 pic14_emitcode("movc","a,@a+dptr");
8978 aopPut(AOP(result),"a",offset++);
8980 pic14_emitcode("inc","dptr");
8984 freeAsmop(result,NULL,ic,TRUE);
8987 /*-----------------------------------------------------------------*/
8988 /* genGenPointerGet - gget value from generic pointer space */
8989 /*-----------------------------------------------------------------*/
8990 static void genGenPointerGet (operand *left,
8991 operand *result, iCode *ic)
8994 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8995 aopOp(left,ic,FALSE);
8996 aopOp(result,ic,FALSE);
8999 DEBUGpic14_AopType(__LINE__,left,NULL,result);
9001 if (IS_BITFIELD(getSpec(operandType(result))))
9003 genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
9008 /* emit call to __gptrget */
9009 char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
9010 int size = AOP_SIZE(result);
9013 assert (size > 0 && size <= 4);
9015 /* pass arguments */
9016 assert (AOP_SIZE(left) == 3);
9017 mov2w(AOP(left), 0);
9018 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9019 mov2w(AOP(left), 1);
9020 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9021 mov2w(AOP(left), 2);
9022 call_libraryfunc (func[size]);
9025 movwf (AOP(result), --size);
9027 emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
9028 movwf (AOP(result), size);
9032 freeAsmop(left,NULL,ic,TRUE);
9033 freeAsmop(result,NULL,ic,TRUE);
9037 /*-----------------------------------------------------------------*/
9038 /* genConstPointerGet - get value from const generic pointer space */
9039 /*-----------------------------------------------------------------*/
9040 static void genConstPointerGet (operand *left,
9041 operand *result, iCode *ic)
9043 //sym_link *retype = getSpec(operandType(result));
9045 symbol *albl, *blbl;//, *clbl;
9052 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9053 aopOp(left,ic,FALSE);
9054 aopOp(result,ic,FALSE);
9056 size = AOP_SIZE(result);
9058 DEBUGpic14_AopType(__LINE__,left,NULL,result);
9060 DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
9062 lit = op_isLitLike (left);
9063 poc = lit ? POC_MOVLW : POC_MOVFW;
9065 if (IS_BITFIELD(getSpec(operandType(result))))
9067 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
9072 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
9073 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
9074 assert (size > 0 && size <= 4);
9077 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9079 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9080 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
9081 call_libraryfunc (func[size]);
9083 movwf(AOP(result),size-1);
9084 for (i = 1; i < size; i++)
9086 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
9087 movwf(AOP(result),size - 1 - i);
9092 freeAsmop(left,NULL,ic,TRUE);
9093 freeAsmop(result,NULL,ic,TRUE);
9096 /*-----------------------------------------------------------------*/
9097 /* genPointerGet - generate code for pointer get */
9098 /*-----------------------------------------------------------------*/
9099 static void genPointerGet (iCode *ic)
9101 operand *left, *result ;
9102 sym_link *type, *etype;
9106 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9109 result = IC_RESULT(ic) ;
9111 /* depending on the type of pointer we need to
9112 move it to the correct pointer register */
9113 type = operandType(left);
9114 etype = getSpec(type);
9116 if (IS_PTR_CONST(type))
9117 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9119 /* if left is of type of pointer then it is simple */
9120 if (IS_PTR(type) && !IS_FUNC(type->next))
9121 p_type = DCL_TYPE(type);
9123 /* we have to go by the storage class */
9124 p_type = PTR_TYPE(SPEC_OCLS(etype));
9126 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9128 if (SPEC_OCLS(etype)->codesp ) {
9129 DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9130 //p_type = CPOINTER ;
9133 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9134 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9135 /*p_type = FPOINTER ;*/
9137 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9138 DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9139 /* p_type = PPOINTER; */
9141 if (SPEC_OCLS(etype) == idata )
9142 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9143 /* p_type = IPOINTER; */
9145 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9146 /* p_type = POINTER ; */
9149 /* now that we have the pointer type we assign
9150 the pointer values */
9156 genNearPointerGet (left,result,ic);
9160 genPagedPointerGet(left,result,ic);
9164 genFarPointerGet (left,result,ic);
9168 genConstPointerGet (left,result,ic);
9172 genGenPointerGet (left,result,ic);
9175 assert ( !"unhandled pointer type" );
9181 /*-----------------------------------------------------------------*/
9182 /* genPackBits - generates code for packed bit storage */
9183 /*-----------------------------------------------------------------*/
9184 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9186 int blen; /* bitfield length */
9187 int bstr; /* bitfield starting bit within byte */
9188 int litval; /* source literal value (if AOP_LIT) */
9189 unsigned char mask; /* bitmask within current byte */
9192 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9194 blen = SPEC_BLEN (etype);
9195 bstr = SPEC_BSTR (etype);
9197 /* If the bitfield length is less than a byte and does not cross byte boundaries */
9198 if ((blen <= 8) && ((bstr + blen) <= 8))
9200 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9201 (unsigned char) (0xFF >> (8 - bstr)));
9203 if (AOP_TYPE (right) == AOP_LIT)
9205 /* Case with a bitfield length <8 and literal source */
9206 int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9213 if (AOP(result)->type == AOP_PCODE)
9214 pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9216 pcop = popGet(AOP(result),0);
9217 emitpcode(lit?POC_BSF:POC_BCF,pcop);
9223 emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9227 assert( !"trying to assign to bitfield via pointer to __code space" );
9231 emitPtrByteGet(result, p_type, FALSE);
9233 emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9235 emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9237 emitPtrByteSet(result, p_type, TRUE);
9241 assert( !"unhandled pointer type" );
9243 } // switch (p_type)
9246 litval = lit << bstr;
9247 litval &= (~mask) & 0x00ff;
9252 mov2w (AOP(result), 0);
9253 if ((litval|mask) != 0x00ff)
9254 emitpcode(POC_ANDLW, popGetLit (mask));
9256 emitpcode(POC_IORLW, popGetLit (litval));
9257 movwf (AOP(result), 0);
9263 emitPtrByteGet(result, p_type, FALSE);
9264 if ((litval|mask) != 0x00ff)
9265 emitpcode(POC_ANDLW, popGetLit (mask));
9267 emitpcode(POC_IORLW, popGetLit (litval));
9268 emitPtrByteSet(result, p_type, TRUE);
9272 assert( !"trying to assign to bitfield via pointer to __code space" );
9276 assert( !"unhandled pointer type" );
9283 /* right is no literal */
9288 /* Note more efficient code, of pre clearing bit then only setting it if required,
9289 * can only be done if it is known that the result is not a SFR */
9290 emitpcode(POC_RRFW,popGet(AOP(right),0));
9292 emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9294 emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9300 emitPtrByteGet (result, p_type, FALSE);
9301 emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9302 emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9303 emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9304 emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9305 emitPtrByteSet (result, p_type, TRUE);
9309 assert( !"trying to assign to bitfield via pointer to __code space" );
9313 assert( !"unhandled pointer type" );
9318 /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9319 pCodeOp *temp = popGetTempReg ();
9321 mov2w (AOP(right), 0);
9323 emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9325 emitpcode(POC_MOVWF, temp);
9327 AccLsh (temp, bstr);
9333 mov2w (AOP(result), 0);
9334 emitpcode(POC_ANDLW, popGetLit (mask));
9335 emitpcode(POC_IORFW, temp);
9336 movwf (AOP(result), 0);
9342 emitPtrByteGet (result, p_type, FALSE);
9343 emitpcode(POC_ANDLW, popGetLit (mask));
9344 emitpcode(POC_IORFW, temp);
9345 emitPtrByteSet (result, p_type, TRUE);
9349 assert( !"trying to assign to bitfield via pointer to __code space" );
9353 assert( !"unhandled pointer type" );
9357 popReleaseTempReg (temp);
9359 } // if (AOP(right)->type != AOP_LIT)
9361 } // if (blen <= 8 && ((blen + bstr) <= 8))
9363 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9367 bitpatternFromVal (value *val)
9374 assert (sizeof (float) == sizeof (uint32_t));
9376 //fprintf (stderr, "%s:%u(%s): val=%lf, type: %d, etype: %d\n", __FILE__, __LINE__, __FUNCTION__, floatFromVal(val), SPEC_NOUN(val->type), SPEC_NOUN(val->etype));
9378 switch (SPEC_NOUN(val->type))
9382 return (unsigned long)floatFromVal (val);
9386 float_long.d = floatFromVal (val);
9387 return float_long.l;
9390 assert( !"unhandled value type" );
9394 float_long.d = floatFromVal (val);
9395 return float_long.l;
9398 /*-----------------------------------------------------------------*/
9399 /* genDataPointerSet - remat pointer to data space */
9400 /*-----------------------------------------------------------------*/
9401 static void genDataPointerSet(operand *right,
9405 int size, offset = 0 ;
9409 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9410 aopOp(right,ic,FALSE);
9411 aopOp(result,ic,FALSE);
9413 assert (IS_SYMOP(result));
9414 assert (IS_PTR(OP_SYM_TYPE(result)));
9416 size = AOP_SIZE(right);
9417 ressize = getSize(OP_SYM_ETYPE(result));
9418 if (size > ressize) size = ressize;
9419 //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9421 //assert( !"what's going on here?" );
9424 if ( AOP_TYPE(result) == AOP_PCODE) {
9425 fprintf(stderr,"genDataPointerSet %s, %d\n",
9426 AOP(result)->aopu.pcop->name,
9427 PCOI(AOP(result)->aopu.pcop)->offset);
9431 // tsd, was l+1 - the underline `_' prefix was being stripped
9433 emitpComment ("%s:%u: size=%d/%d, offset=%i", __FILE__,__LINE__, size, ressize, offset);
9435 if (AOP_TYPE(right) == AOP_LIT) {
9436 /* XXX: might be float... */
9437 unsigned int lit = bitpatternFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9438 lit = lit >> (8*offset);
9439 //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9441 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9442 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9444 emitpcode(POC_CLRF, popGet(AOP(result),offset));
9447 //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9448 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9449 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9455 freeAsmop(right,NULL,ic,TRUE);
9456 freeAsmop(result,NULL,ic,TRUE);
9459 /*-----------------------------------------------------------------*/
9460 /* genNearPointerSet - pic14_emitcode for near pointer put */
9461 /*-----------------------------------------------------------------*/
9462 static void genNearPointerSet (operand *right,
9467 sym_link *ptype = operandType(result);
9468 sym_link *retype = getSpec(operandType(right));
9469 sym_link *letype = getSpec(ptype);
9474 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9475 aopOp(result,ic,FALSE);
9478 /* if the result is rematerializable &
9479 in data space & not a bit variable */
9480 //if (AOP_TYPE(result) == AOP_IMMD &&
9481 if (AOP_TYPE(result) == AOP_PCODE &&
9482 PIC_IS_DATA_PTR(ptype) &&
9483 !IS_BITVAR (retype) &&
9484 !IS_BITVAR (letype)) {
9485 genDataPointerSet (right,result,ic);
9486 freeAsmop(result,NULL,ic,TRUE);
9491 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9492 aopOp(right,ic,FALSE);
9493 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9495 /* Check if can access directly instead of via a pointer */
9496 if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9500 if (IS_BITFIELD (letype))
9502 genPackBits (letype, result, right, direct?-1:POINTER);
9506 /* If the pointer value is not in a the FSR then need to put it in */
9507 /* Must set/reset IRP bit for use with FSR. */
9508 /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9513 /* we have can just get the values */
9514 int size = AOP_SIZE(right);
9517 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9519 char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9521 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9523 if (AOP_TYPE(right) == AOP_LIT) {
9524 emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9526 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9529 emitpcode(POC_MOVWF,popGet(AOP(result),0));
9531 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9533 if (size && !direct)
9534 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9539 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9540 /* now some housekeeping stuff */
9542 /* we had to allocate for this iCode */
9543 freeAsmop(NULL,aop,ic,TRUE);
9545 /* we did not allocate which means left
9546 already in a pointer register, then
9547 if size > 0 && this could be used again
9548 we have to point it back to where it
9550 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9551 if (AOP_SIZE(right) > 1 &&
9552 !OP_SYMBOL(result)->remat &&
9553 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9555 int size = AOP_SIZE(right) - 1;
9557 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9561 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9564 freeAsmop(right,NULL,ic,TRUE);
9565 freeAsmop(result,NULL,ic,TRUE);
9569 /*-----------------------------------------------------------------*/
9570 /* genPagedPointerSet - pic14_emitcode for Paged pointer put */
9571 /*-----------------------------------------------------------------*/
9572 static void genPagedPointerSet (operand *right,
9582 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9584 retype= getSpec(operandType(right));
9586 aopOp(result,ic,FALSE);
9588 /* if the value is already in a pointer register
9589 then don't need anything more */
9590 if (!AOP_INPREG(AOP(result))) {
9591 /* otherwise get a free pointer register */
9593 preg = getFreePtr(ic,&aop,FALSE);
9594 pic14_emitcode("mov","%s,%s",
9596 aopGet(AOP(result),0,FALSE,TRUE));
9597 rname = preg->name ;
9599 rname = aopGet(AOP(result),0,FALSE,FALSE);
9601 freeAsmop(result,NULL,ic,TRUE);
9602 aopOp (right,ic,FALSE);
9604 /* if bitfield then unpack the bits */
9605 if (IS_BITFIELD(retype))
9606 genPackBits (retype,result,right,rname,PPOINTER);
9608 /* we have can just get the values */
9609 int size = AOP_SIZE(right);
9613 l = aopGet(AOP(right),offset,FALSE,TRUE);
9616 pic14_emitcode("movx","@%s,a",rname);
9619 pic14_emitcode("inc","%s",rname);
9625 /* now some housekeeping stuff */
9627 /* we had to allocate for this iCode */
9628 freeAsmop(NULL,aop,ic,TRUE);
9630 /* we did not allocate which means left
9631 already in a pointer register, then
9632 if size > 0 && this could be used again
9633 we have to point it back to where it
9635 if (AOP_SIZE(right) > 1 &&
9636 !OP_SYMBOL(result)->remat &&
9637 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9639 int size = AOP_SIZE(right) - 1;
9641 pic14_emitcode("dec","%s",rname);
9646 freeAsmop(right,NULL,ic,TRUE);
9651 /*-----------------------------------------------------------------*/
9652 /* genFarPointerSet - set value from far space */
9653 /*-----------------------------------------------------------------*/
9654 static void genFarPointerSet (operand *right,
9655 operand *result, iCode *ic)
9658 sym_link *retype = getSpec(operandType(right));
9661 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9662 aopOp(result,ic,FALSE);
9664 /* if the operand is already in dptr
9665 then we do nothing else we move the value to dptr */
9666 if (AOP_TYPE(result) != AOP_STR) {
9667 /* if this is remateriazable */
9668 if (AOP_TYPE(result) == AOP_IMMD)
9669 pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9670 else { /* we need to get it byte by byte */
9671 pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9672 pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9673 if (options.model == MODEL_FLAT24)
9675 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9679 /* so dptr know contains the address */
9680 freeAsmop(result,NULL,ic,TRUE);
9681 aopOp(right,ic,FALSE);
9683 /* if bit then unpack */
9684 if (IS_BITFIELD(retype))
9685 genPackBits(retype,result,right,"dptr",FPOINTER);
9687 size = AOP_SIZE(right);
9691 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9693 pic14_emitcode("movx","@dptr,a");
9695 pic14_emitcode("inc","dptr");
9699 freeAsmop(right,NULL,ic,TRUE);
9703 /*-----------------------------------------------------------------*/
9704 /* genGenPointerSet - set value from generic pointer space */
9705 /*-----------------------------------------------------------------*/
9706 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9708 sym_link *retype = getSpec(operandType(result));
9711 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9712 aopOp(right,ic,FALSE);
9713 aopOp(result,ic,FALSE);
9716 DEBUGpic14_AopType(__LINE__,right,NULL,result);
9718 if (IS_BITFIELD(retype))
9720 genPackBits (retype, result, right, GPOINTER);
9725 /* emit call to __gptrput */
9726 char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9727 int size = AOP_SIZE(right);
9730 assert (size == getSize(OP_SYM_ETYPE(result)));
9731 assert (size > 0 && size <= 4);
9733 /* pass arguments */
9734 /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9740 mov2w_op (right, off);
9741 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9746 assert (AOP_SIZE(result) == 3);
9747 mov2w(AOP(result), 0);
9748 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9749 mov2w(AOP(result), 1);
9750 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9751 mov2w(AOP(result), 2);
9752 call_libraryfunc (func[size]);
9755 freeAsmop(right,NULL,ic,TRUE);
9756 freeAsmop(result,NULL,ic,TRUE);
9759 /*-----------------------------------------------------------------*/
9760 /* genPointerSet - stores the value into a pointer location */
9761 /*-----------------------------------------------------------------*/
9762 static void genPointerSet (iCode *ic)
9764 operand *right, *result ;
9765 sym_link *type, *etype;
9769 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9771 right = IC_RIGHT(ic);
9772 result = IC_RESULT(ic) ;
9774 /* depending on the type of pointer we need to
9775 move it to the correct pointer register */
9776 type = operandType(result);
9777 etype = getSpec(type);
9778 /* if left is of type of pointer then it is simple */
9779 if (IS_PTR(type) && !IS_FUNC(type->next)) {
9780 p_type = DCL_TYPE(type);
9783 /* we have to go by the storage class */
9784 p_type = PTR_TYPE(SPEC_OCLS(etype));
9786 /* if (SPEC_OCLS(etype)->codesp ) { */
9787 /* p_type = CPOINTER ; */
9790 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9791 /* p_type = FPOINTER ; */
9793 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9794 /* p_type = PPOINTER ; */
9796 /* if (SPEC_OCLS(etype) == idata ) */
9797 /* p_type = IPOINTER ; */
9799 /* p_type = POINTER ; */
9802 /* now that we have the pointer type we assign
9803 the pointer values */
9809 genNearPointerSet (right,result,ic);
9813 genPagedPointerSet (right,result,ic);
9817 genFarPointerSet (right,result,ic);
9821 genGenPointerSet (right,result,ic);
9825 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9826 "genPointerSet: illegal pointer type");
9830 /*-----------------------------------------------------------------*/
9831 /* genIfx - generate code for Ifx statement */
9832 /*-----------------------------------------------------------------*/
9833 static void genIfx (iCode *ic, iCode *popIc)
9835 operand *cond = IC_COND(ic);
9839 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9841 aopOp(cond,ic,FALSE);
9843 /* get the value into acc */
9844 if (AOP_TYPE(cond) != AOP_CRY)
9845 pic14_toBoolean(cond);
9849 /* if there was something to be popped then do it */
9855 /* This assumes that CARRY is set iff cond is true */
9858 assert (!IC_FALSE(ic));
9859 emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
9861 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9863 assert (IC_FALSE(ic));
9864 emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
9866 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9870 static int hasWarned = 0;
9873 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
9880 /* now Z is set iff !cond */
9883 assert (!IC_FALSE(ic));
9885 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9888 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9894 /* the result is now in the accumulator */
9895 freeAsmop(cond,NULL,ic,TRUE);
9898 /*-----------------------------------------------------------------*/
9899 /* genAddrOf - generates code for address of */
9900 /*-----------------------------------------------------------------*/
9901 static void genAddrOf (iCode *ic)
9903 operand *right, *result, *left;
9907 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9910 //aopOp(IC_RESULT(ic),ic,FALSE);
9912 aopOp((left=IC_LEFT(ic)),ic,FALSE);
9913 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9914 aopOp((result=IC_RESULT(ic)),ic,TRUE);
9916 DEBUGpic14_AopType(__LINE__,left,right,result);
9917 assert (IS_SYMOP (left));
9919 /* sanity check: generic pointers to code space are not yet supported,
9920 * pionters to codespace must not be assigned addresses of __data values. */
9922 fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9923 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)));
9924 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)));
9925 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)));
9926 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)));
9929 if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9930 fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9931 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9932 OP_SYMBOL(left)->name);
9933 } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9934 fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9935 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9936 OP_SYMBOL(left)->name);
9939 size = AOP_SIZE(IC_RESULT(ic));
9940 if (IS_GENPTR(OP_SYM_TYPE(result))) {
9942 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9947 /* fixing bug #863624, reported from (errolv) */
9948 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9949 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9952 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9953 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9958 if (IS_GENPTR(OP_SYM_TYPE(result)))
9960 /* provide correct tag */
9961 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9962 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9963 movwf (AOP(result), 2);
9966 freeAsmop(left,NULL,ic,FALSE);
9967 freeAsmop(result,NULL,ic,TRUE);
9972 /*-----------------------------------------------------------------*/
9973 /* genFarFarAssign - assignment when both are in far space */
9974 /*-----------------------------------------------------------------*/
9975 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9977 int size = AOP_SIZE(right);
9980 /* first push the right side on to the stack */
9982 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9984 pic14_emitcode ("push","acc");
9987 freeAsmop(right,NULL,ic,FALSE);
9988 /* now assign DPTR to result */
9989 aopOp(result,ic,FALSE);
9990 size = AOP_SIZE(result);
9992 pic14_emitcode ("pop","acc");
9993 aopPut(AOP(result),"a",--offset);
9995 freeAsmop(result,NULL,ic,FALSE);
10000 /*-----------------------------------------------------------------*/
10001 /* genAssign - generate code for assignment */
10002 /*-----------------------------------------------------------------*/
10003 static void genAssign (iCode *ic)
10005 operand *result, *right;
10006 int size, offset,know_W;
10007 unsigned long lit = 0L;
10009 result = IC_RESULT(ic);
10010 right = IC_RIGHT(ic) ;
10013 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10015 /* if they are the same */
10016 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10019 aopOp(right,ic,FALSE);
10020 aopOp(result,ic,TRUE);
10022 DEBUGpic14_AopType(__LINE__,NULL,right,result);
10024 /* if they are the same registers */
10025 if (pic14_sameRegs(AOP(right),AOP(result)))
10028 /* special case: assign from __code */
10029 if (!IS_ITEMP(right) /* --> iTemps never reside in __code */
10030 && IS_SYMOP (right) /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
10031 && !IS_FUNC(OP_SYM_TYPE(right)) /* --> we would want its address instead of the first instruction */
10032 && !IS_CODEPTR(OP_SYM_TYPE(right)) /* --> get symbols address instread */
10033 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
10035 emitpComment ("genAssign from CODESPACE");
10036 genConstPointerGet (right, result, ic);
10040 /* just for symmetry reasons... */
10041 if (!IS_ITEMP(result)
10042 && IS_SYMOP (result)
10043 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
10045 assert ( !"cannot write to CODESPACE" );
10048 /* if the result is a bit */
10049 if (AOP_TYPE(result) == AOP_CRY) {
10051 /* if the right size is a literal then
10052 we know what the value is */
10053 if (AOP_TYPE(right) == AOP_LIT) {
10055 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10056 popGet(AOP(result),0));
10058 if (((int) operandLitValue(right)))
10059 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10060 AOP(result)->aopu.aop_dir,
10061 AOP(result)->aopu.aop_dir);
10063 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10064 AOP(result)->aopu.aop_dir,
10065 AOP(result)->aopu.aop_dir);
10069 /* the right is also a bit variable */
10070 if (AOP_TYPE(right) == AOP_CRY) {
10071 emitpcode(POC_BCF, popGet(AOP(result),0));
10072 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10073 emitpcode(POC_BSF, popGet(AOP(result),0));
10075 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10076 AOP(result)->aopu.aop_dir,
10077 AOP(result)->aopu.aop_dir);
10078 pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
10079 AOP(right)->aopu.aop_dir,
10080 AOP(right)->aopu.aop_dir);
10081 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10082 AOP(result)->aopu.aop_dir,
10083 AOP(result)->aopu.aop_dir);
10087 /* we need to or */
10088 emitpcode(POC_BCF, popGet(AOP(result),0));
10089 pic14_toBoolean(right);
10091 emitpcode(POC_BSF, popGet(AOP(result),0));
10092 //aopPut(AOP(result),"a",0);
10096 /* bit variables done */
10098 size = AOP_SIZE(result);
10100 if(AOP_TYPE(right) == AOP_LIT)
10101 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10103 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
10104 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10105 if(aopIdx(AOP(result),0) == 4) {
10106 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10107 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10108 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10111 DEBUGpic14_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
10116 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10117 if(AOP_TYPE(right) == AOP_LIT) {
10119 if(know_W != (int)(lit&0xff))
10120 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10122 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10124 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10128 } else if (AOP_TYPE(right) == AOP_CRY) {
10129 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10131 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10132 emitpcode(POC_INCF, popGet(AOP(result),0));
10135 mov2w_op (right, offset);
10136 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10144 freeAsmop (right,NULL,ic,FALSE);
10145 freeAsmop (result,NULL,ic,TRUE);
10148 /*-----------------------------------------------------------------*/
10149 /* genJumpTab - genrates code for jump table */
10150 /*-----------------------------------------------------------------*/
10151 static void genJumpTab (iCode *ic)
10157 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10159 aopOp(IC_JTCOND(ic),ic,FALSE);
10160 /* get the condition into accumulator */
10161 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10163 /* multiply by three */
10164 pic14_emitcode("add","a,acc");
10165 pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10167 jtab = newiTempLabel(NULL);
10168 pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10169 pic14_emitcode("jmp","@a+dptr");
10170 pic14_emitcode("","%05d_DS_:",jtab->key+100);
10172 emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10173 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10174 emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10175 emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10177 emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10178 emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10179 emitpLabel(jtab->key);
10181 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10183 /* now generate the jump labels */
10184 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10185 jtab = setNextItem(IC_JTLABELS(ic))) {
10186 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10187 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10193 /*-----------------------------------------------------------------*/
10194 /* genMixedOperation - gen code for operators between mixed types */
10195 /*-----------------------------------------------------------------*/
10197 TSD - Written for the PIC port - but this unfortunately is buggy.
10198 This routine is good in that it is able to efficiently promote
10199 types to different (larger) sizes. Unfortunately, the temporary
10200 variables that are optimized out by this routine are sometimes
10201 used in other places. So until I know how to really parse the
10202 iCode tree, I'm going to not be using this routine :(.
10204 static int genMixedOperation (iCode *ic)
10208 operand *result = IC_RESULT(ic);
10209 sym_link *ctype = operandType(IC_LEFT(ic));
10210 operand *right = IC_RIGHT(ic);
10216 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10218 pic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10224 nextright = IC_RIGHT(nextic);
10225 nextleft = IC_LEFT(nextic);
10226 nextresult = IC_RESULT(nextic);
10228 aopOp(right,ic,FALSE);
10229 aopOp(result,ic,FALSE);
10230 aopOp(nextright, nextic, FALSE);
10231 aopOp(nextleft, nextic, FALSE);
10232 aopOp(nextresult, nextic, FALSE);
10234 if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10236 operand *t = right;
10240 pic14_emitcode(";remove right +","");
10242 } else if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10244 operand *t = right;
10248 pic14_emitcode(";remove left +","");
10252 big = AOP_SIZE(nextleft);
10253 small = AOP_SIZE(nextright);
10255 switch(nextic->op) {
10258 pic14_emitcode(";optimize a +","");
10259 /* if unsigned or not an integral type */
10260 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10261 pic14_emitcode(";add a bit to something","");
10264 pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10266 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10267 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10268 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10270 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10278 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10279 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10280 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10283 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10285 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10286 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10287 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10288 pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10289 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10292 pic14_emitcode("rlf","known_zero,w");
10299 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10300 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10301 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10303 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10313 freeAsmop(right,NULL,ic,TRUE);
10314 freeAsmop(result,NULL,ic,TRUE);
10315 freeAsmop(nextright,NULL,ic,TRUE);
10316 freeAsmop(nextleft,NULL,ic,TRUE);
10318 nextic->generated = 1;
10325 /*-----------------------------------------------------------------*/
10326 /* genCast - gen code for casting */
10327 /*-----------------------------------------------------------------*/
10328 static void genCast (iCode *ic)
10330 operand *result = IC_RESULT(ic);
10331 sym_link *restype = operandType(result);
10332 sym_link *rtype = operandType(IC_RIGHT(ic));
10333 operand *right = IC_RIGHT(ic);
10337 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10338 /* if they are equivalent then do nothing */
10339 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10342 aopOp(right,ic,FALSE) ;
10343 aopOp(result,ic,FALSE);
10345 DEBUGpic14_AopType(__LINE__,NULL,right,result);
10347 /* if the result is a bit */
10348 if (AOP_TYPE(result) == AOP_CRY) {
10349 assert(!"assigning to bit variables is not supported");
10352 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10354 size = AOP_SIZE(result);
10356 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10358 emitpcode(POC_CLRF, popGet(AOP(result),0));
10359 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10360 emitpcode(POC_INCF, popGet(AOP(result),0));
10363 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
10368 if (IS_PTR(restype))
10370 operand *result = IC_RESULT(ic);
10371 //operand *left = IC_LEFT(ic);
10372 operand *right = IC_RIGHT(ic);
10375 /* copy common part */
10376 int max, size = AOP_SIZE(result);
10377 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10378 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10380 /* warn if we discard generic opinter tag */
10381 if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10383 //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10389 mov2w_op (right, size);
10390 movwf (AOP(result), size);
10393 /* upcast into generic pointer type? */
10394 if (IS_GENPTR(restype)
10395 && (size < AOP_SIZE(result))
10396 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10398 //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10401 switch (DCL_TYPE(rtype))
10403 case POINTER: /* __data */
10404 case FPOINTER: /* __data */
10405 assert (AOP_SIZE(right) == 2);
10406 tag = GPTRTAG_DATA;
10409 case CPOINTER: /* __code */
10410 assert (AOP_SIZE(right) == 2);
10411 tag = GPTRTAG_CODE;
10414 case GPOINTER: /* unknown destination, __data or __code */
10415 /* assume __data space (address of immediate) */
10416 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10417 if (AOP(right)->code)
10418 tag = GPTRTAG_CODE;
10420 tag = GPTRTAG_DATA;
10424 assert (!"unhandled pointer type");
10427 /* convert other values into pointers to __data space */
10428 tag = GPTRTAG_DATA;
10431 assert (AOP_SIZE(result) == 3);
10433 emitpcode(POC_CLRF, popGet(AOP(result), 2));
10435 emitpcode(POC_MOVLW, popGetLit(tag));
10436 movwf(AOP(result), 2);
10439 addSign(result, max, 0);
10444 /* if they are the same size : or less */
10445 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10447 /* if they are in the same place */
10448 if (pic14_sameRegs(AOP(right),AOP(result)))
10451 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10452 if (IS_PTR_CONST(rtype))
10453 DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10454 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10455 DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10457 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10458 emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10459 emitpcode(POC_MOVWF, popGet(AOP(result),0));
10460 emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10461 emitpcode(POC_MOVWF, popGet(AOP(result),1));
10462 if(AOP_SIZE(result) <2)
10463 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10467 /* if they in different places then copy */
10468 size = AOP_SIZE(result);
10471 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10472 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10474 //aopPut(AOP(result),
10475 // aopGet(AOP(right),offset,FALSE,FALSE),
10484 /* so we now know that the size of destination is greater
10485 than the size of the source.
10486 Now, if the next iCode is an operator then we might be
10487 able to optimize the operation without performing a cast.
10489 if(0 && genMixedOperation(ic)) {
10490 /* XXX: cannot optimize: must copy regs! */
10494 /* we move to result for the size of source */
10495 size = AOP_SIZE(right);
10498 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10499 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10503 addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10506 freeAsmop(right,NULL,ic,TRUE);
10507 freeAsmop(result,NULL,ic,TRUE);
10511 /*-----------------------------------------------------------------*/
10512 /* genDjnz - generate decrement & jump if not zero instrucion */
10513 /*-----------------------------------------------------------------*/
10514 static int genDjnz (iCode *ic, iCode *ifx)
10516 symbol *lbl, *lbl1;
10518 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10523 /* if the if condition has a false label
10524 then we cannot save */
10528 /* if the minus is not of the form
10530 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10531 !IS_OP_LITERAL(IC_RIGHT(ic)))
10534 if (operandLitValue(IC_RIGHT(ic)) != 1)
10537 /* if the size of this greater than one then no
10539 if (getSize(operandType(IC_RESULT(ic))) > 1)
10542 /* otherwise we can save BIG */
10543 lbl = newiTempLabel(NULL);
10544 lbl1= newiTempLabel(NULL);
10546 aopOp(IC_RESULT(ic),ic,FALSE);
10548 if (IS_AOP_PREG(IC_RESULT(ic))) {
10549 pic14_emitcode("dec","%s",
10550 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10551 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10552 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10556 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10557 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10559 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10560 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10563 /* pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10564 /* pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10565 /* pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10566 /* pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10569 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10570 ifx->generated = 1;
10574 /*-----------------------------------------------------------------*/
10575 /* genReceive - generate code for a receive iCode */
10576 /*-----------------------------------------------------------------*/
10577 static void genReceive (iCode *ic)
10580 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10582 if (isOperandInFarSpace(IC_RESULT(ic)) &&
10583 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10584 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10586 int size = getSize(operandType(IC_RESULT(ic)));
10587 int offset = fReturnSizePic - size;
10589 pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10590 fReturn[fReturnSizePic - offset - 1] : "acc"));
10593 aopOp(IC_RESULT(ic),ic,FALSE);
10594 size = AOP_SIZE(IC_RESULT(ic));
10597 pic14_emitcode ("pop","acc");
10598 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10603 aopOp(IC_RESULT(ic),ic,FALSE);
10605 assignResultValue(IC_RESULT(ic));
10608 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10611 /*-----------------------------------------------------------------*/
10612 /* genDummyRead - generate code for dummy read of volatiles */
10613 /*-----------------------------------------------------------------*/
10615 genDummyRead (iCode * ic)
10618 pic14_emitcode ("; genDummyRead","");
10619 pic14_emitcode ("; not implemented","");
10624 /*-----------------------------------------------------------------*/
10625 /* genpic14Code - generate code for pic14 based controllers */
10626 /*-----------------------------------------------------------------*/
10628 * At this point, ralloc.c has gone through the iCode and attempted
10629 * to optimize in a way suitable for a PIC. Now we've got to generate
10630 * PIC instructions that correspond to the iCode.
10632 * Once the instructions are generated, we'll pass through both the
10633 * peep hole optimizer and the pCode optimizer.
10634 *-----------------------------------------------------------------*/
10636 void genpic14Code (iCode *lic)
10643 lineHead = lineCurr = NULL;
10645 pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10648 /* if debug information required */
10649 if (options.debug && currFunc) {
10651 debugFile->writeFunction (currFunc, lic);
10656 for (ic = lic ; ic ; ic = ic->next ) {
10658 //DEBUGpic14_emitcode(";ic","");
10659 //fprintf (stderr, "in ic loop\n");
10660 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10661 //ic->lineno, printCLine(ic->filename, ic->lineno));
10663 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10665 //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10666 cline = printCLine (ic->filename, ic->lineno);
10667 if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10668 addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10669 //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10672 if (options.iCodeInAsm) {
10673 emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10675 /* if the result is marked as
10676 spilt and rematerializable or code for
10677 this has already been generated then
10679 if (resultRemat(ic) || ic->generated )
10682 /* depending on the operation */
10701 /* IPOP happens only when trying to restore a
10702 spilt live range, if there is an ifx statement
10703 following this pop then the if statement might
10704 be using some of the registers being popped which
10705 would destory the contents of the register so
10706 we need to check for this condition and handle it */
10708 ic->next->op == IFX &&
10709 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10710 genIfx (ic->next,ic);
10728 genEndFunction (ic);
10748 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10765 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
10769 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10776 /* note these two are xlated by algebraic equivalence
10777 during parsing SDCC.y */
10778 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10779 "got '>=' or '<=' shouldn't have come here");
10783 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10795 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10799 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10803 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10827 genRightShift (ic);
10830 case GET_VALUE_AT_ADDRESS:
10835 if (POINTER_SET(ic))
10862 addSet(&_G.sendSet,ic);
10865 case DUMMY_READ_VOLATILE:
10870 fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10877 /* now we are ready to call the
10878 peep hole optimizer */
10879 if (!options.nopeep) {
10880 peepHole (&lineHead);
10882 /* now do the actual printing */
10883 printLine (lineHead,codeOutFile);
10886 DFPRINTF((stderr,"printing pBlock\n\n"));
10887 printpBlock(stdout,pb);
10893 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10894 * (meaning: representing its own address) or not (referencing its contents).
10895 * This can only be decided based on the operand's type. */
10897 aop_isLitLike (asmop *aop)
10900 if (aop->type == AOP_LIT) return 1;
10901 if (aop->type == AOP_IMMD) return 1;
10902 if ((aop->type == AOP_PCODE) &&
10903 ((aop->aopu.pcop->type == PO_LITERAL)))
10905 /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10906 * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10913 op_isLitLike (operand *op)
10916 if (aop_isLitLike (AOP(op))) return 1;
10917 if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10918 if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;