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@web.de (2005)
10 This program is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the
12 Free Software Foundation; either version 2, or (at your option) any
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 In other words, you are welcome to use, share and improve this program.
25 You are forbidden to forbid anyone else to use, share and improve
26 what you give them. Help stamp out software-hoarding!
29 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
30 Made everything static
31 -------------------------------------------------------------------------*/
37 #include "SDCCglobl.h"
41 #include "SDCCpeeph.h"
46 /* When changing these, you must also update the assembler template
47 * in device/lib/libsdcc/macros.inc */
48 #define GPTRTAG_DATA 0x00
49 #define GPTRTAG_CODE 0x80
51 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
52 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
53 void genMult8X8_8 (operand *, operand *,operand *);
54 extern void printpBlock(FILE *of, pBlock *pb);
56 static int labelOffset=0;
57 extern int debug_verbose;
58 //static int optimized_for_speed = 0;
60 /* max_key keeps track of the largest label number used in
61 a function. This is then used to adjust the label offset
62 for the next function.
65 static int GpsuedoStkPtr=0;
67 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
68 extern char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
69 unsigned int pic14aopLiteral (value *val, int offset);
70 const char *AopType(short type);
72 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0x00ff)
74 /* this is the down and dirty file with all kinds of
75 kludgy & hacky stuff. This is what it is all about
76 CODE GENERATION for a specific MCU . some of the
77 routines may be reusable, will have to see */
79 static char *zero = "#0x00";
80 static char *one = "#0x01";
81 static char *spname = "sp";
83 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
84 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
85 static char **fReturn = fReturnpic14;
87 //static char *accUse[] = {"a","b"};
89 //static short rbank = -1;
101 /* Resolved ifx structure. This structure stores information
102 about an iCode ifx that makes it easier to generate code.
104 typedef struct resolvedIfx {
105 symbol *lbl; /* pointer to a label */
106 int condition; /* true or false ifx */
107 int generated; /* set true when the code associated with the ifx
111 extern int pic14_ptrRegReq ;
112 extern int pic14_nRegs;
113 extern FILE *codeOutFile;
114 static void saverbank (int, iCode *,bool);
116 static lineNode *lineHead = NULL;
117 static lineNode *lineCurr = NULL;
120 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
121 0xE0, 0xC0, 0x80, 0x00};
122 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
123 0x07, 0x03, 0x01, 0x00};
128 /*-----------------------------------------------------------------*/
129 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
130 /* exponent of 2 is returned, otherwise -1 is */
132 /* note that this is similar to the function `powof2' in SDCCsymt */
136 /*-----------------------------------------------------------------*/
137 static int my_powof2 (unsigned long num)
140 if( (num & (num-1)) == 0) {
153 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
156 DEBUGpic14_emitcode ("; ","line = %d result %s=%s, size=%d, left %s=%s, size=%d, right %s=%s, size=%d",
158 ((result) ? AopType(AOP_TYPE(result)) : "-"),
159 ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
160 ((result) ? AOP_SIZE(result) : 0),
161 ((left) ? AopType(AOP_TYPE(left)) : "-"),
162 ((left) ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
163 ((left) ? AOP_SIZE(left) : 0),
164 ((right) ? AopType(AOP_TYPE(right)) : "-"),
165 ((right) ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
166 ((right) ? AOP_SIZE(right) : 0));
170 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
173 DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
175 ((result) ? AopType(AOP_TYPE(result)) : "-"),
176 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
177 ((left) ? AopType(AOP_TYPE(left)) : "-"),
178 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
179 ((right) ? AopType(AOP_TYPE(right)) : "-"),
180 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
184 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
187 char lb[INITIAL_INLINEASM];
188 unsigned char *lbp = lb;
190 if(!debug_verbose && !options.debug)
197 sprintf(lb,"%s\t",inst);
199 sprintf(lb,"%s",inst);
200 vsprintf(lb+(strlen(lb)),fmt,ap);
204 while (isspace(*lbp)) lbp++;
207 lineCurr = (lineCurr ?
208 connectLine(lineCurr,newLineNode(lb)) :
209 (lineHead = newLineNode(lb)));
210 lineCurr->isInline = _G.inLine;
211 lineCurr->isDebug = _G.debugLine;
213 addpCode2pBlock(pb,newpCodeCharP(lb));
218 static void Safe_vsnprintf (char *buf, size_t size, const char *fmt, va_list ap)
220 #if defined (HAVE_VSNPRINTF)
221 vsnprintf (buf, size, fmt, ap);
222 #elif defined (HAVE_VSPRINTF)
223 vsprintf (buf, size, fmt, ap);
224 if (strlen (buf) >= size)
226 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
228 #elif defined (HAVE_SNPRINTF)
229 snprintf (buf, size, "vs(n)printf required");
230 #elif defined (HAVE_SRINTF)
231 sprintf (buf, "vs(n)printf required");
232 if (strlen (buf) >= size)
234 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
237 assert ( !"neither vsnprintf nor vsprintf is present -- unable to proceed" );
241 void emitpComment (const char *fmt, ...)
248 Safe_vsnprintf (buffer, 4096, fmt, va);
249 //fprintf (stderr, "%s\n" ,buffer);
250 addpCode2pBlock (pb, newpCodeCharP (buffer));
253 Safe_vsnprintf (buffer, 4096, fmt, va);
254 fprintf (stderr, "No current pBlock -- discarding comment [%s]\n", buffer);
260 void emitpLabel(int key)
262 addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
265 /* gen.h defines a macro emitpcode that should be used to call emitpcode
266 * as this allows for easy debugging (ever asked the question: where was
267 * this instruction geenrated? Here is the answer... */
268 void emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
271 addpCode2pBlock(pb,newpCode(poc,pcop));
273 DEBUGpic14_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
276 void emitpcodeNULLop(PIC_OPCODE poc)
279 addpCode2pBlock(pb,newpCode(poc,NULL));
284 /*-----------------------------------------------------------------*/
285 /* pic14_emitcode - writes the code into a file : for now it is simple */
286 /*-----------------------------------------------------------------*/
287 void pic14_emitcode (char *inst,char *fmt, ...)
290 char lb[INITIAL_INLINEASM];
291 unsigned char *lbp = lb;
297 sprintf(lb,"%s\t",inst);
299 sprintf(lb,"%s",inst);
300 vsprintf(lb+(strlen(lb)),fmt,ap);
304 while (isspace(*lbp)) lbp++;
307 lineCurr = (lineCurr ?
308 connectLine(lineCurr,newLineNode(lb)) :
309 (lineHead = newLineNode(lb)));
310 lineCurr->isInline = _G.inLine;
311 lineCurr->isDebug = _G.debugLine;
314 addpCode2pBlock(pb,newpCodeCharP(lb));
319 /*-----------------------------------------------------------------*/
320 /* pic14_emitDebuggerSymbol - associate the current code location */
321 /* with a debugger symbol */
322 /*-----------------------------------------------------------------*/
324 pic14_emitDebuggerSymbol (char * debugSym)
327 pic14_emitcode ("", ";%s ==.", debugSym);
332 /*-----------------------------------------------------------------*/
333 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
334 /*-----------------------------------------------------------------*/
335 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
337 bool r0iu = FALSE , r1iu = FALSE;
338 bool r0ou = FALSE , r1ou = FALSE;
340 /* the logic: if r0 & r1 used in the instruction
341 then we are in trouble otherwise */
343 /* first check if r0 & r1 are used by this
344 instruction, in which case we are in trouble */
345 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
346 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
351 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
352 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
354 /* if no usage of r0 then return it */
355 if (!r0iu && !r0ou) {
356 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
357 (*aopp)->type = AOP_R0;
359 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
362 /* if no usage of r1 then return it */
363 if (!r1iu && !r1ou) {
364 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
365 (*aopp)->type = AOP_R1;
367 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
370 /* now we know they both have usage */
371 /* if r0 not used in this instruction */
373 /* push it if not already pushed */
375 //pic14_emitcode ("push","%s",
376 // pic14_regWithIdx(R0_IDX)->dname);
380 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
381 (*aopp)->type = AOP_R0;
383 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
386 /* if r1 not used then */
389 /* push it if not already pushed */
391 //pic14_emitcode ("push","%s",
392 // pic14_regWithIdx(R1_IDX)->dname);
396 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
397 (*aopp)->type = AOP_R1;
398 return pic14_regWithIdx(R1_IDX);
402 /* I said end of world but not quite end of world yet */
403 /* if this is a result then we can push it on the stack*/
405 (*aopp)->type = AOP_STK;
409 /* other wise this is true end of the world */
410 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
411 "getFreePtr should never reach here");
416 /*-----------------------------------------------------------------*/
417 /* newAsmop - creates a new asmOp */
418 /*-----------------------------------------------------------------*/
419 asmop *newAsmop (short type)
423 aop = Safe_calloc(1,sizeof(asmop));
428 static void genSetDPTR(int n)
432 pic14_emitcode(";", "Select standard DPTR");
433 pic14_emitcode("mov", "dps, #0x00");
437 pic14_emitcode(";", "Select alternate DPTR");
438 pic14_emitcode("mov", "dps, #0x01");
442 /*-----------------------------------------------------------------*/
443 /* resolveIfx - converts an iCode ifx into a form more useful for */
444 /* generating code */
445 /*-----------------------------------------------------------------*/
446 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
451 // DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
453 resIfx->condition = 1; /* assume that the ifx is true */
454 resIfx->generated = 0; /* indicate that the ifx has not been used */
457 resIfx->lbl = NULL; /* this is wrong: newiTempLabel(NULL); / * oops, there is no ifx. so create a label */
459 DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
460 __FUNCTION__,__LINE__,resIfx->lbl->key);
464 resIfx->lbl = IC_TRUE(ifx);
466 resIfx->lbl = IC_FALSE(ifx);
467 resIfx->condition = 0;
471 DEBUGpic14_emitcode("; ***","ifx true is non-null");
473 DEBUGpic14_emitcode("; ***","ifx false is non-null");
477 // DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
480 /*-----------------------------------------------------------------*/
481 /* pointerCode - returns the code for a pointer type */
482 /*-----------------------------------------------------------------*/
484 static int pointerCode (sym_link *etype)
487 return PTR_TYPE(SPEC_OCLS(etype));
492 /*-----------------------------------------------------------------*/
493 /* aopForSym - for a true symbol */
494 /*-----------------------------------------------------------------*/
495 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
498 memmap *space= SPEC_OCLS(sym->etype);
500 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
501 /* if already has one */
506 /* assign depending on the storage class */
507 /* if it is on the stack or indirectly addressable */
508 /* space we need to assign either r0 or r1 to it */
509 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
510 sym->aop = aop = newAsmop(0);
511 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
512 aop->size = getSize(sym->type);
514 /* now assign the address of the variable to
515 the pointer register */
516 if (aop->type != AOP_STK) {
520 pic14_emitcode("push","acc");
522 pic14_emitcode("mov","a,_bp");
523 pic14_emitcode("add","a,#0x%02x",
525 ((char)(sym->stack - _G.nRegsSaved )) :
526 ((char)sym->stack)) & 0xff);
527 pic14_emitcode("mov","%s,a",
528 aop->aopu.aop_ptr->name);
531 pic14_emitcode("pop","acc");
533 pic14_emitcode("mov","%s,#%s",
534 aop->aopu.aop_ptr->name,
536 aop->paged = space->paged;
538 aop->aopu.aop_stk = sym->stack;
542 if (sym->onStack && options.stack10bit)
544 /* It's on the 10 bit stack, which is located in
548 //DEBUGpic14_emitcode(";","%d",__LINE__);
551 pic14_emitcode("push","acc");
553 pic14_emitcode("mov","a,_bp");
554 pic14_emitcode("add","a,#0x%02x",
556 ((char)(sym->stack - _G.nRegsSaved )) :
557 ((char)sym->stack)) & 0xff);
560 pic14_emitcode ("mov","dpx1,#0x40");
561 pic14_emitcode ("mov","dph1,#0x00");
562 pic14_emitcode ("mov","dpl1, a");
566 pic14_emitcode("pop","acc");
568 sym->aop = aop = newAsmop(AOP_DPTR2);
569 aop->size = getSize(sym->type);
574 //DEBUGpic14_emitcode(";","%d",__LINE__);
575 /* if in bit space */
576 if (IN_BITSPACE(space)) {
577 sym->aop = aop = newAsmop (AOP_CRY);
578 aop->aopu.aop_dir = sym->rname ;
579 aop->size = getSize(sym->type);
580 //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
583 /* if it is in direct space */
584 if (IN_DIRSPACE(space)) {
585 sym->aop = aop = newAsmop (AOP_DIR);
586 aop->aopu.aop_dir = sym->rname ;
587 aop->size = getSize(sym->type);
588 DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
592 /* special case for a function */
593 if (IS_FUNC(sym->type)) {
595 sym->aop = aop = newAsmop(AOP_PCODE);
596 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
597 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
598 PCOI(aop->aopu.pcop)->_function = 1;
599 PCOI(aop->aopu.pcop)->index = 0;
600 aop->size = FPTRSIZE;
602 sym->aop = aop = newAsmop(AOP_IMMD);
603 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
604 strcpy(aop->aopu.aop_immd,sym->rname);
605 aop->size = FPTRSIZE;
607 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
611 if (IS_ARRAY(sym->type)) {
612 sym->aop = aop = newAsmop(AOP_PCODE);
613 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
614 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
615 PCOI(aop->aopu.pcop)->_function = 0;
616 PCOI(aop->aopu.pcop)->index = 0;
617 aop->size = getSize(sym->etype) * DCL_ELEM(sym->type);
619 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
623 /* only remaining is far space */
624 /* in which case DPTR gets the address */
625 sym->aop = aop = newAsmop(AOP_PCODE);
627 aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
628 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
629 PCOI(aop->aopu.pcop)->index = 0;
631 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
632 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
634 allocDirReg (IC_LEFT(ic));
636 aop->size = FPTRSIZE;
638 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
639 sym->aop = aop = newAsmop(AOP_DPTR);
640 pic14_emitcode ("mov","dptr,#%s", sym->rname);
641 aop->size = getSize(sym->type);
643 DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
646 /* if it is in code space */
647 if (IN_CODESPACE(space))
653 /*-----------------------------------------------------------------*/
654 /* aopForRemat - rematerialzes an object */
655 /*-----------------------------------------------------------------*/
656 static asmop *aopForRemat (operand *op) // x symbol *sym)
658 symbol *sym = OP_SYMBOL(op);
660 asmop *aop = newAsmop(AOP_PCODE);
664 ic = sym->rematiCode;
666 DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
667 if(IS_OP_POINTER(op)) {
668 DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
672 val += (int) operandLitValue(IC_RIGHT(ic));
673 } else if (ic->op == '-') {
674 val -= (int) operandLitValue(IC_RIGHT(ic));
678 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
681 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
682 aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
683 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
684 PCOI(aop->aopu.pcop)->index = val;
686 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
687 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
688 val, IS_PTR_CONST(operandType(op)));
690 // DEBUGpic14_emitcode(";","aop type %s",AopType(AOP_TYPE(IC_LEFT(ic))));
692 allocDirReg (IC_LEFT(ic));
697 int aopIdx (asmop *aop, int offset)
702 if(aop->type != AOP_REG)
705 return aop->aopu.aop_reg[offset]->rIdx;
708 /*-----------------------------------------------------------------*/
709 /* regsInCommon - two operands have some registers in common */
710 /*-----------------------------------------------------------------*/
711 static bool regsInCommon (operand *op1, operand *op2)
716 /* if they have registers in common */
717 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
720 sym1 = OP_SYMBOL(op1);
721 sym2 = OP_SYMBOL(op2);
723 if (sym1->nRegs == 0 || sym2->nRegs == 0)
726 for (i = 0 ; i < sym1->nRegs ; i++) {
731 for (j = 0 ; j < sym2->nRegs ;j++ ) {
735 if (sym2->regs[j] == sym1->regs[i])
743 /*-----------------------------------------------------------------*/
744 /* operandsEqu - equivalent */
745 /*-----------------------------------------------------------------*/
746 static bool operandsEqu ( operand *op1, operand *op2)
750 /* if they not symbols */
751 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
754 sym1 = OP_SYMBOL(op1);
755 sym2 = OP_SYMBOL(op2);
757 /* if both are itemps & one is spilt
758 and the other is not then false */
759 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
760 sym1->isspilt != sym2->isspilt )
763 /* if they are the same */
767 if (sym1->rname[0] && sym2->rname[0]
768 && strcmp (sym1->rname, sym2->rname) == 0)
772 /* if left is a tmp & right is not */
776 (sym1->usl.spillLoc == sym2))
783 (sym2->usl.spillLoc == sym1))
789 /*-----------------------------------------------------------------*/
790 /* pic14_sameRegs - two asmops have the same registers */
791 /*-----------------------------------------------------------------*/
792 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
799 if (aop1->type != AOP_REG ||
800 aop2->type != AOP_REG )
803 if (aop1->size != aop2->size )
806 for (i = 0 ; i < aop1->size ; i++ )
807 if (aop1->aopu.aop_reg[i] !=
808 aop2->aopu.aop_reg[i] )
814 /*-----------------------------------------------------------------*/
815 /* aopOp - allocates an asmop for an operand : */
816 /*-----------------------------------------------------------------*/
817 void aopOp (operand *op, iCode *ic, bool result)
826 /* if this a literal */
827 if (IS_OP_LITERAL(op)) {
828 op->aop = aop = newAsmop(AOP_LIT);
829 aop->aopu.aop_lit = op->operand.valOperand;
830 aop->size = getSize(operandType(op));
835 sym_link *type = operandType(op);
836 if(IS_PTR_CONST(type))
837 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
840 /* if already has a asmop then continue */
844 /* if the underlying symbol has a aop */
845 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
846 DEBUGpic14_emitcode(";","%d",__LINE__);
847 op->aop = OP_SYMBOL(op)->aop;
851 /* if this is a true symbol */
852 if (IS_TRUE_SYMOP(op)) {
853 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
854 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
858 /* this is a temporary : this has
864 e) can be a return use only */
869 /* if the type is a conditional */
870 if (sym->regType == REG_CND) {
871 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
876 /* if it is spilt then two situations
878 b) has a spill location */
879 if (sym->isspilt || sym->nRegs == 0) {
881 DEBUGpic14_emitcode(";","%d",__LINE__);
882 /* rematerialize it NOW */
885 sym->aop = op->aop = aop = aopForRemat (op);
886 aop->size = getSize(sym->type);
887 //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
892 /* WREG is not usable as an ordinary operand with PIC architecture,
893 * one might introduce a scratch register that can be used to make
894 * WREG accesible as an operand... disable WREG for now */
897 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
898 aop->size = getSize(sym->type);
899 for ( i = 0 ; i < 2 ; i++ )
900 aop->aopu.aop_str[i] = accUse[i];
901 DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
907 if(sym->isptr) { // && sym->uptr
908 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
909 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
911 //PCOI(aop->aopu.pcop)->_const = 0;
912 //PCOI(aop->aopu.pcop)->index = 0;
914 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
915 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
917 //allocDirReg (IC_LEFT(ic));
919 aop->size = getSize(sym->type);
920 DEBUGpic14_emitcode(";","%d",__LINE__);
927 aop = op->aop = sym->aop = newAsmop(AOP_STR);
928 aop->size = getSize(sym->type);
929 for ( i = 0 ; i < fReturnSizePic ; i++ )
930 aop->aopu.aop_str[i] = fReturn[i];
932 DEBUGpic14_emitcode(";","%d",__LINE__);
937 /* else spill location */
938 if (sym->usl.spillLoc)
940 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
942 /* force a new aop if sizes differ */
943 sym->usl.spillLoc->aop = NULL;
945 DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
946 __FUNCTION__,__LINE__,
947 sym->usl.spillLoc->rname,
948 sym->rname, sym->usl.spillLoc->offset);
950 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
951 //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
952 aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname,
954 sym->usl.spillLoc->offset);
955 aop->size = getSize(sym->type);
962 sym_link *type = operandType(op);
963 if(IS_PTR_CONST(type))
964 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
967 /* must be in a register */
968 DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
969 sym->aop = op->aop = aop = newAsmop(AOP_REG);
970 aop->size = sym->nRegs;
971 for ( i = 0 ; i < sym->nRegs ;i++)
972 aop->aopu.aop_reg[i] = sym->regs[i];
975 /*-----------------------------------------------------------------*/
976 /* freeAsmop - free up the asmop given to an operand */
977 /*----------------------------------------------------------------*/
978 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
995 /* depending on the asmop type only three cases need work AOP_RO
996 , AOP_R1 && AOP_STK */
1002 pic14_emitcode ("pop","ar0");
1006 bitVectUnSetBit(ic->rUsed,R0_IDX);
1012 pic14_emitcode ("pop","ar1");
1016 bitVectUnSetBit(ic->rUsed,R1_IDX);
1022 int stk = aop->aopu.aop_stk + aop->size;
1023 bitVectUnSetBit(ic->rUsed,R0_IDX);
1024 bitVectUnSetBit(ic->rUsed,R1_IDX);
1026 getFreePtr(ic,&aop,FALSE);
1028 if (options.stack10bit)
1030 /* I'm not sure what to do here yet... */
1033 "*** Warning: probably generating bad code for "
1034 "10 bit stack mode.\n");
1038 pic14_emitcode ("mov","a,_bp");
1039 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1040 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1042 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1046 pic14_emitcode("pop","acc");
1047 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1049 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1052 freeAsmop(op,NULL,ic,TRUE);
1054 pic14_emitcode("pop","ar0");
1059 pic14_emitcode("pop","ar1");
1067 /* all other cases just dealloc */
1071 OP_SYMBOL(op)->aop = NULL;
1072 /* if the symbol has a spill */
1074 SPIL_LOC(op)->aop = NULL;
1079 /*-----------------------------------------------------------------*/
1080 /* aopGet - for fetching value of the aop */
1081 /*-----------------------------------------------------------------*/
1082 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1087 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1088 /* offset is greater than
1090 if (offset > (aop->size - 1) &&
1091 aop->type != AOP_LIT)
1094 /* depending on type */
1095 switch (aop->type) {
1099 DEBUGpic14_emitcode(";","%d",__LINE__);
1100 /* if we need to increment it */
1101 while (offset > aop->coff) {
1102 pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);
1106 while (offset < aop->coff) {
1107 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1111 aop->coff = offset ;
1113 pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1114 return (dname ? "acc" : "a");
1116 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1117 rs = Safe_calloc(1,strlen(s)+1);
1123 DEBUGpic14_emitcode(";","%d",__LINE__);
1124 if (aop->type == AOP_DPTR2)
1129 while (offset > aop->coff) {
1130 pic14_emitcode ("inc","dptr");
1134 while (offset < aop->coff) {
1135 pic14_emitcode("lcall","__decdptr");
1141 pic14_emitcode("clr","a");
1142 pic14_emitcode("movc","a,@a+dptr");
1145 pic14_emitcode("movx","a,@dptr");
1148 if (aop->type == AOP_DPTR2)
1153 return (dname ? "acc" : "a");
1158 sprintf (s,"%s",aop->aopu.aop_immd);
1161 sprintf(s,"(%s >> %d)",
1166 aop->aopu.aop_immd);
1167 DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1168 rs = Safe_calloc(1,strlen(s)+1);
1174 sprintf(s,"(%s + %d)",
1177 DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1179 sprintf(s,"%s",aop->aopu.aop_dir);
1180 rs = Safe_calloc(1,strlen(s)+1);
1186 // return aop->aopu.aop_reg[offset]->dname;
1188 return aop->aopu.aop_reg[offset]->name;
1191 //pic14_emitcode(";","%d",__LINE__);
1192 return aop->aopu.aop_dir;
1195 DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1196 return "AOP_accumulator_bug";
1199 sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1200 rs = Safe_calloc(1,strlen(s)+1);
1205 aop->coff = offset ;
1206 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1209 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1211 return aop->aopu.aop_str[offset];
1215 pCodeOp *pcop = aop->aopu.pcop;
1216 DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1219 DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
1220 sprintf(s,"(%s+%d)", pcop->name,offset);
1222 DEBUGpic14_emitcode(";","%s",pcop->name);
1223 sprintf(s,"%s", pcop->name);
1226 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1229 rs = Safe_calloc(1,strlen(s)+1);
1235 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1236 "aopget got unsupported aop->type");
1241 /*-----------------------------------------------------------------*/
1242 /* popGetTempReg - create a new temporary pCodeOp */
1243 /*-----------------------------------------------------------------*/
1244 pCodeOp *popGetTempReg(void)
1249 pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1250 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1251 PCOR(pcop)->r->wasUsed=1;
1252 PCOR(pcop)->r->isFree=0;
1258 /*-----------------------------------------------------------------*/
1259 /* popReleaseTempReg - create a new temporary pCodeOp */
1260 /*-----------------------------------------------------------------*/
1261 void popReleaseTempReg(pCodeOp *pcop)
1264 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1265 PCOR(pcop)->r->isFree = 1;
1268 /*-----------------------------------------------------------------*/
1269 /* popGetLabel - create a new pCodeOp of type PO_LABEL */
1270 /*-----------------------------------------------------------------*/
1271 pCodeOp *popGetLabel(unsigned int key)
1274 DEBUGpic14_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1276 if(key>(unsigned int)max_key)
1279 return newpCodeOpLabel(NULL,key+100+labelOffset);
1282 /*-------------------------------------------------------------------*/
1283 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1284 /*-------------------------------------------------------------------*/
1285 pCodeOp *popGetHighLabel(unsigned int key)
1288 pcop = popGetLabel(key);
1289 PCOLAB(pcop)->offset = 1;
1293 /*-----------------------------------------------------------------*/
1294 /* popGetLit - asm operator to pcode operator conversion */
1295 /*-----------------------------------------------------------------*/
1296 pCodeOp *popGetLit(unsigned int lit)
1299 return newpCodeOpLit((unsigned char)lit);
1302 /*-----------------------------------------------------------------*/
1303 /* popGetImmd - asm operator to pcode immediate conversion */
1304 /*-----------------------------------------------------------------*/
1305 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1308 return newpCodeOpImmd(name, offset,index, 0, is_func);
1311 extern set *externs;
1313 /*-----------------------------------------------------------------*/
1314 /* popGetWithString - asm operator to pcode operator conversion */
1315 /*-----------------------------------------------------------------*/
1316 pCodeOp *popGetWithString(char *str, int isExtern)
1322 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1326 pcop = newpCodeOp(str,PO_STR);
1327 PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1332 pCodeOp *popGetExternal (char *str)
1334 pCodeOp *pcop = popGetWithString (str, 1);
1340 for (sym = setFirstItem (externs); !found && sym; sym = setNextItem (externs))
1342 if (!strcmp (str, sym->rname))
1348 sym = newSymbol(str, 0);
1349 strncpy(sym->rname, str, SDCC_NAME_MAX);
1350 addSet (&externs, sym);
1356 /*-----------------------------------------------------------------*/
1357 /* popRegFromString - */
1358 /*-----------------------------------------------------------------*/
1359 pCodeOp *popRegFromString(char *str, int size, int offset)
1362 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1363 pcop->type = PO_DIR;
1365 DEBUGpic14_emitcode(";","%d",__LINE__);
1370 pcop->name = Safe_calloc(1,strlen(str)+1);
1371 strcpy(pcop->name,str);
1373 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1375 PCOR(pcop)->r = dirregWithName(pcop->name);
1376 if(PCOR(pcop)->r == NULL) {
1377 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1378 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1379 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1381 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1383 PCOR(pcop)->instance = offset;
1388 /*-----------------------------------------------------------------*/
1389 /*-----------------------------------------------------------------*/
1390 pCodeOp *popRegFromIdx(int rIdx)
1394 DEBUGpic14_emitcode ("; ***","%s,%d , rIdx=0x%x",
1395 __FUNCTION__,__LINE__,rIdx);
1397 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1399 PCOR(pcop)->rIdx = rIdx;
1400 PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1401 PCOR(pcop)->r->isFree = 0;
1402 PCOR(pcop)->r->wasUsed = 1;
1404 pcop->type = PCOR(pcop)->r->pc_type;
1410 /*-----------------------------------------------------------------*/
1411 /* popGet - asm operator to pcode operator conversion */
1412 /*-----------------------------------------------------------------*/
1413 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1415 //char *s = buffer ;
1420 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1421 /* offset is greater than
1426 /* XXX: still needed for BIT operands (AOP_CRY) */
1427 if (offset > (aop->size - 1) &&
1428 aop->type != AOP_LIT)
1429 return NULL; //zero;
1431 /* depending on type */
1432 switch (aop->type) {
1439 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1443 DEBUGpic14_emitcode(";","%d",__LINE__);
1444 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1447 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1449 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1450 pcop->type = PO_DIR;
1452 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1453 strcpy(pcop->name,aop->aopu.aop_dir);
1454 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1455 if(PCOR(pcop)->r == NULL) {
1456 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1457 PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1458 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1460 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1462 PCOR(pcop)->instance = offset;
1470 assert (offset < aop->size);
1471 rIdx = aop->aopu.aop_reg[offset]->rIdx;
1473 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1474 PCOR(pcop)->rIdx = rIdx;
1475 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1476 PCOR(pcop)->r->wasUsed=1;
1477 PCOR(pcop)->r->isFree=0;
1479 PCOR(pcop)->instance = offset;
1480 pcop->type = PCOR(pcop)->r->pc_type;
1481 //rs = aop->aopu.aop_reg[offset]->name;
1482 DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1487 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1488 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1489 //if(PCOR(pcop)->r == NULL)
1490 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1494 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1497 DEBUGpic14_emitcode(";","%d %s",__LINE__,aop->aopu.aop_str[offset]);
1498 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1500 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1501 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1502 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1503 pcop->type = PCOR(pcop)->r->pc_type;
1504 pcop->name = PCOR(pcop)->r->name;
1511 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1513 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1514 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1515 switch (aop->aopu.pcop->type)
1518 pcop = pCodeOpCopy (aop->aopu.pcop);
1519 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1520 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1521 PCOI(pcop)->index += offset;
1522 //PCOI(pcop)->offset = 0;
1525 pcop = pCodeOpCopy (aop->aopu.pcop);
1526 PCOR(pcop)->instance = offset;
1529 assert ( !"unhandled pCode type" );
1535 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1536 "popGet got unsupported aop->type");
1540 /*-----------------------------------------------------------------*/
1541 /* popGetAddr - access the low/high word of a symbol (immediate) */
1542 /* (for non-PO_IMMEDIATEs this is the same as popGet) */
1543 /*-----------------------------------------------------------------*/
1544 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1546 if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1548 pCodeOp *pcop = aop->aopu.pcop;
1549 assert (offset <= GPTRSIZE);
1551 /* special case: index >= 2 should return GPOINTER-style values */
1554 pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1558 pcop = pCodeOpCopy (pcop);
1559 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1560 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1561 PCOI(pcop)->offset += offset;
1562 PCOI(pcop)->index += index;
1563 //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);
1566 return popGet (aop, offset + index);
1570 /*-----------------------------------------------------------------*/
1571 /* aopPut - puts a string for a aop */
1572 /*-----------------------------------------------------------------*/
1573 void aopPut (asmop *aop, char *s, int offset)
1578 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1580 if (aop->size && offset > ( aop->size - 1)) {
1581 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1582 "aopPut got offset > aop->size");
1586 /* will assign value to value */
1587 /* depending on where it is ofcourse */
1588 switch (aop->type) {
1591 sprintf(d,"(%s + %d)",
1592 aop->aopu.aop_dir,offset);
1593 fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1596 sprintf(d,"%s",aop->aopu.aop_dir);
1599 DEBUGpic14_emitcode(";","%d",__LINE__);
1601 pic14_emitcode("movf","%s,w",s);
1602 pic14_emitcode("movwf","%s",d);
1605 pic14_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
1606 if(offset >= aop->size) {
1607 emitpcode(POC_CLRF,popGet(aop,offset));
1610 emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
1613 emitpcode(POC_MOVWF,popGet(aop,offset));
1619 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1620 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1623 strcmp(s,"r0") == 0 ||
1624 strcmp(s,"r1") == 0 ||
1625 strcmp(s,"r2") == 0 ||
1626 strcmp(s,"r3") == 0 ||
1627 strcmp(s,"r4") == 0 ||
1628 strcmp(s,"r5") == 0 ||
1629 strcmp(s,"r6") == 0 ||
1630 strcmp(s,"r7") == 0 )
1631 pic14_emitcode("mov","%s,%s ; %d",
1632 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1636 if(strcmp(s,"W")==0 )
1637 pic14_emitcode("movf","%s,w ; %d",s,__LINE__);
1639 pic14_emitcode("movwf","%s",
1640 aop->aopu.aop_reg[offset]->name);
1642 if(strcmp(s,zero)==0) {
1643 emitpcode(POC_CLRF,popGet(aop,offset));
1645 } else if(strcmp(s,"W")==0) {
1646 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1647 pcop->type = PO_GPR_REGISTER;
1649 PCOR(pcop)->rIdx = -1;
1650 PCOR(pcop)->r = NULL;
1652 DEBUGpic14_emitcode(";","%d",__LINE__);
1653 pcop->name = Safe_strdup(s);
1654 emitpcode(POC_MOVFW,pcop);
1655 emitpcode(POC_MOVWF,popGet(aop,offset));
1656 } else if(strcmp(s,one)==0) {
1657 emitpcode(POC_CLRF,popGet(aop,offset));
1658 emitpcode(POC_INCF,popGet(aop,offset));
1660 emitpcode(POC_MOVWF,popGet(aop,offset));
1668 if (aop->type == AOP_DPTR2)
1674 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1675 "aopPut writting to code space");
1679 while (offset > aop->coff) {
1681 pic14_emitcode ("inc","dptr");
1684 while (offset < aop->coff) {
1686 pic14_emitcode("lcall","__decdptr");
1691 /* if not in accumulater */
1694 pic14_emitcode ("movx","@dptr,a");
1696 if (aop->type == AOP_DPTR2)
1704 while (offset > aop->coff) {
1706 pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1708 while (offset < aop->coff) {
1710 pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1716 pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1721 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1723 if (strcmp(s,"r0") == 0 ||
1724 strcmp(s,"r1") == 0 ||
1725 strcmp(s,"r2") == 0 ||
1726 strcmp(s,"r3") == 0 ||
1727 strcmp(s,"r4") == 0 ||
1728 strcmp(s,"r5") == 0 ||
1729 strcmp(s,"r6") == 0 ||
1730 strcmp(s,"r7") == 0 ) {
1732 sprintf(buffer,"a%s",s);
1733 pic14_emitcode("mov","@%s,%s",
1734 aop->aopu.aop_ptr->name,buffer);
1736 pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1741 if (strcmp(s,"a") == 0)
1742 pic14_emitcode("push","acc");
1744 pic14_emitcode("push","%s",s);
1749 /* if bit variable */
1750 if (!aop->aopu.aop_dir) {
1751 pic14_emitcode("clr","a");
1752 pic14_emitcode("rlc","a");
1755 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1758 pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1761 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1763 lbl = newiTempLabel(NULL);
1765 if (strcmp(s,"a")) {
1768 pic14_emitcode("clr","c");
1769 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1770 pic14_emitcode("cpl","c");
1771 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1772 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1779 if (strcmp(aop->aopu.aop_str[offset],s))
1780 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1785 if (!offset && (strcmp(s,"acc") == 0))
1788 if (strcmp(aop->aopu.aop_str[offset],s))
1789 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1793 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1794 "aopPut got unsupported aop->type");
1800 /*-----------------------------------------------------------------*/
1801 /* mov2w_op - generate either a MOVLW or MOVFW based operand type */
1802 /*-----------------------------------------------------------------*/
1803 static void mov2w_op (operand *op, int offset)
1808 /* for PO_IMMEDIATEs: use address or value? */
1809 if (op_isLitLike (op))
1811 /* access address of op */
1812 if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
1813 if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
1815 if (offset == GPTRSIZE-1)
1816 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1818 emitpcode (POC_MOVLW, popGetLit (0));
1821 emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
1823 /* access value stored in op */
1824 mov2w (AOP(op), offset);
1829 /*-----------------------------------------------------------------*/
1830 /* mov2w - generate either a MOVLW or MOVFW based operand type */
1831 /*-----------------------------------------------------------------*/
1832 void mov2w (asmop *aop, int offset)
1838 DEBUGpic14_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
1840 if ( aop_isLitLike (aop) )
1841 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1843 emitpcode(POC_MOVFW,popGet(aop,offset));
1847 static void movwf (asmop *op, int offset)
1849 emitpcode (POC_MOVWF, popGet(op, offset));
1852 static pCodeOp *get_argument_pcop (int idx)
1854 assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1855 return popRegFromIdx (Gstack_base_addr - (idx - 1));
1858 static pCodeOp *get_return_val_pcop (int offset)
1860 assert (offset > 0 && "the most significant byte is returned via WREG");
1861 return popRegFromIdx (Gstack_base_addr - (offset - 1));
1864 static void pass_argument (operand *op, int offset, int idx)
1867 mov2w_op (op, offset);
1869 emitpcode(POC_MOVWF, get_argument_pcop (idx));
1872 static void get_returnvalue (operand *op, int offset, int idx)
1875 emitpcode(POC_MOVFW, get_return_val_pcop (idx));
1876 movwf(AOP(op), offset);
1879 static void call_libraryfunc (char *name)
1881 /* library code might reside in different page... */
1882 emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1883 /* call the library function */
1884 emitpcode (POC_CALL, popGetExternal (name));
1885 /* might return from different page... */
1886 emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1889 /*-----------------------------------------------------------------*/
1890 /* reAdjustPreg - points a register back to where it should */
1891 /*-----------------------------------------------------------------*/
1892 static void reAdjustPreg (asmop *aop)
1896 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1898 if ((size = aop->size) <= 1)
1901 switch (aop->type) {
1905 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1909 if (aop->type == AOP_DPTR2)
1915 pic14_emitcode("lcall","__decdptr");
1918 if (aop->type == AOP_DPTR2)
1931 /*-----------------------------------------------------------------*/
1932 /* opIsGptr: returns non-zero if the passed operand is */
1933 /* a generic pointer type. */
1934 /*-----------------------------------------------------------------*/
1935 static int opIsGptr(operand *op)
1937 sym_link *type = operandType(op);
1939 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1940 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1948 /*-----------------------------------------------------------------*/
1949 /* pic14_getDataSize - get the operand data size */
1950 /*-----------------------------------------------------------------*/
1951 int pic14_getDataSize(operand *op)
1955 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1958 size = getSize(OP_SYM_ETYPE(op));
1960 //return AOP_SIZE(op);
1962 // tsd- in the pic port, the genptr size is 1, so this code here
1963 // fails. ( in the 8051 port, the size was 4).
1965 size = AOP_SIZE(op);
1966 if (IS_GENPTR(OP_SYM_TYPE(op)))
1968 sym_link *type = operandType(op);
1969 if (IS_GENPTR(type))
1971 /* generic pointer; arithmetic operations
1972 * should ignore the high byte (pointer type).
1975 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1982 /*-----------------------------------------------------------------*/
1983 /* pic14_outAcc - output Acc */
1984 /*-----------------------------------------------------------------*/
1985 void pic14_outAcc(operand *result)
1988 DEBUGpic14_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
1989 DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1992 size = pic14_getDataSize(result);
1994 emitpcode(POC_MOVWF,popGet(AOP(result),0));
1997 /* unsigned or positive */
1999 emitpcode(POC_CLRF,popGet(AOP(result),offset++));
2004 /*-----------------------------------------------------------------*/
2005 /* pic14_outBitC - output a bit C */
2006 /*-----------------------------------------------------------------*/
2007 void pic14_outBitC(operand *result)
2010 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2011 /* if the result is bit */
2012 if (AOP_TYPE(result) == AOP_CRY)
2013 aopPut(AOP(result),"c",0);
2015 pic14_emitcode("clr","a ; %d", __LINE__);
2016 pic14_emitcode("rlc","a");
2017 pic14_outAcc(result);
2021 /*-----------------------------------------------------------------*/
2022 /* pic14_toBoolean - emit code for orl a,operator(sizeop) */
2023 /*-----------------------------------------------------------------*/
2024 void pic14_toBoolean(operand *oper)
2026 int size = AOP_SIZE(oper);
2029 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2034 /* MOVFW does not load the flags... */
2035 if (AOP_TYPE(oper) == AOP_ACC) {
2036 emitpcode(POC_IORLW, popGetLit(0));
2039 emitpcode(POC_MOVLW, popGetLit(0));
2043 if ( AOP_TYPE(oper) != AOP_ACC) {
2044 emitpcode(POC_MOVFW,popGet(AOP(oper),0));
2049 while (offset < size) {
2050 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
2052 /* Z is set iff (oper == 0) */
2056 /*-----------------------------------------------------------------*/
2057 /* genNot - generate code for ! operation */
2058 /*-----------------------------------------------------------------*/
2059 static void genNot (iCode *ic)
2066 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2067 /* assign asmOps to operand & result */
2068 aopOp (IC_LEFT(ic),ic,FALSE);
2069 aopOp (IC_RESULT(ic),ic,TRUE);
2071 DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2072 /* if in bit space then a special case */
2073 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2074 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2075 emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
2076 emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
2078 emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
2079 emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
2080 emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
2085 size = AOP_SIZE(IC_LEFT(ic));
2086 mov2w (AOP(IC_LEFT(ic)),0);
2089 if (op_isLitLike (IC_LEFT(ic)))
2090 emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
2092 emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
2094 emitpcode(POC_MOVLW, popGetLit (0));
2096 emitpcode(POC_MOVLW, popGetLit (1));
2097 movwf(AOP(IC_RESULT(ic)), 0);
2099 for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
2101 emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
2106 /* release the aops */
2107 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2108 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2112 /*-----------------------------------------------------------------*/
2113 /* genCpl - generate code for complement */
2114 /*-----------------------------------------------------------------*/
2115 static void genCpl (iCode *ic)
2117 operand *left, *result;
2122 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2123 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2124 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2126 /* if both are in bit space then
2128 if (AOP_TYPE(result) == AOP_CRY &&
2129 AOP_TYPE(left) == AOP_CRY ) {
2131 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir);
2132 pic14_emitcode("cpl","c");
2133 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir);
2137 size = AOP_SIZE(result);
2138 if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
2141 if(AOP_TYPE(left) == AOP_ACC)
2142 emitpcode(POC_XORLW, popGetLit(0xff));
2144 emitpcode(POC_COMFW,popGet(AOP(left),offset));
2146 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
2149 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2153 /* release the aops */
2154 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2155 freeAsmop(result,NULL,ic,TRUE);
2158 /*-----------------------------------------------------------------*/
2159 /* genUminusFloat - unary minus for floating points */
2160 /*-----------------------------------------------------------------*/
2161 static void genUminusFloat(operand *op,operand *result)
2163 int size ,offset =0 ;
2168 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2169 /* for this we just need to flip the
2170 first it then copy the rest in place */
2171 size = AOP_SIZE(op) - 1;
2172 l = aopGet(AOP(op),3,FALSE,FALSE);
2176 pic14_emitcode("cpl","acc.7");
2177 aopPut(AOP(result),"a",3);
2181 aopGet(AOP(op),offset,FALSE,FALSE),
2187 /*-----------------------------------------------------------------*/
2188 /* genUminus - unary minus code generation */
2189 /*-----------------------------------------------------------------*/
2190 static void genUminus (iCode *ic)
2193 sym_link *optype, *rtype;
2197 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2199 aopOp(IC_LEFT(ic),ic,FALSE);
2200 aopOp(IC_RESULT(ic),ic,TRUE);
2202 /* if both in bit space then special
2204 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2205 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2207 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0));
2208 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2209 emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0));
2214 optype = operandType(IC_LEFT(ic));
2215 rtype = operandType(IC_RESULT(ic));
2217 /* if float then do float stuff */
2218 if (IS_FLOAT(optype)) {
2219 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2223 /* otherwise subtract from zero by taking the 2's complement */
2224 size = AOP_SIZE(IC_LEFT(ic));
2226 for(i=0; i<size; i++) {
2227 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2228 emitpcode(POC_COMF, popGet(AOP(IC_LEFT(ic)),i));
2230 emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2231 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2235 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0));
2236 for(i=1; i<size; i++) {
2238 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),i));
2242 /* release the aops */
2243 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2244 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2247 /*-----------------------------------------------------------------*/
2248 /* saveRegisters - will look for a call and save the registers */
2249 /*-----------------------------------------------------------------*/
2250 static void saveRegisters(iCode *lic)
2259 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2261 for (ic = lic ; ic ; ic = ic->next)
2262 if (ic->op == CALL || ic->op == PCALL)
2266 fprintf(stderr,"found parameter push with no function call\n");
2270 /* if the registers have been saved already then
2272 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2275 /* find the registers in use at this time
2276 and push them away to safety */
2277 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2281 if (options.useXstack) {
2282 if (bitVectBitValue(rsave,R0_IDX))
2283 pic14_emitcode("mov","b,r0");
2284 pic14_emitcode("mov","r0,%s",spname);
2285 for (i = 0 ; i < pic14_nRegs ; i++) {
2286 if (bitVectBitValue(rsave,i)) {
2288 pic14_emitcode("mov","a,b");
2290 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2291 pic14_emitcode("movx","@r0,a");
2292 pic14_emitcode("inc","r0");
2295 pic14_emitcode("mov","%s,r0",spname);
2296 if (bitVectBitValue(rsave,R0_IDX))
2297 pic14_emitcode("mov","r0,b");
2299 //for (i = 0 ; i < pic14_nRegs ; i++) {
2300 // if (bitVectBitValue(rsave,i))
2301 // pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2304 dtype = operandType(IC_LEFT(ic));
2305 if (currFunc && dtype &&
2306 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2307 IFFUNC_ISISR(currFunc->type) &&
2310 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2313 /*-----------------------------------------------------------------*/
2314 /* unsaveRegisters - pop the pushed registers */
2315 /*-----------------------------------------------------------------*/
2316 static void unsaveRegisters (iCode *ic)
2323 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2324 /* find the registers in use at this time
2325 and push them away to safety */
2326 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2329 if (options.useXstack) {
2330 pic14_emitcode("mov","r0,%s",spname);
2331 for (i = pic14_nRegs ; i >= 0 ; i--) {
2332 if (bitVectBitValue(rsave,i)) {
2333 pic14_emitcode("dec","r0");
2334 pic14_emitcode("movx","a,@r0");
2336 pic14_emitcode("mov","b,a");
2338 pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2342 pic14_emitcode("mov","%s,r0",spname);
2343 if (bitVectBitValue(rsave,R0_IDX))
2344 pic14_emitcode("mov","r0,b");
2346 //for (i = pic14_nRegs ; i >= 0 ; i--) {
2347 // if (bitVectBitValue(rsave,i))
2348 // pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2354 /*-----------------------------------------------------------------*/
2356 /*-----------------------------------------------------------------*/
2357 static void pushSide(operand * oper, int size)
2361 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2363 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2364 if (AOP_TYPE(oper) != AOP_REG &&
2365 AOP_TYPE(oper) != AOP_DIR &&
2367 pic14_emitcode("mov","a,%s",l);
2368 pic14_emitcode("push","acc");
2370 pic14_emitcode("push","%s",l);
2375 /*-----------------------------------------------------------------*/
2376 /* assignResultValue - */
2377 /*-----------------------------------------------------------------*/
2378 static void assignResultValue(operand * oper)
2380 int size = AOP_SIZE(oper);
2385 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2387 DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2389 /* assign MSB first (passed via WREG) */
2391 get_returnvalue (oper, size, offset + GpsuedoStkPtr);
2397 /*-----------------------------------------------------------------*/
2398 /* genIpush - genrate code for pushing this gets a little complex */
2399 /*-----------------------------------------------------------------*/
2400 static void genIpush (iCode *ic)
2404 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2406 int size, offset = 0 ;
2410 /* if this is not a parm push : ie. it is spill push
2411 and spill push is always done on the local stack */
2412 if (!ic->parmPush) {
2414 /* and the item is spilt then do nothing */
2415 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2418 aopOp(IC_LEFT(ic),ic,FALSE);
2419 size = AOP_SIZE(IC_LEFT(ic));
2420 /* push it on the stack */
2422 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2427 pic14_emitcode("push","%s",l);
2432 /* this is a paramter push: in this case we call
2433 the routine to find the call and save those
2434 registers that need to be saved */
2437 /* then do the push */
2438 aopOp(IC_LEFT(ic),ic,FALSE);
2441 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2442 size = AOP_SIZE(IC_LEFT(ic));
2445 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2446 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
2447 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2449 pic14_emitcode("mov","a,%s",l);
2450 pic14_emitcode("push","acc");
2452 pic14_emitcode("push","%s",l);
2455 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2459 /*-----------------------------------------------------------------*/
2460 /* genIpop - recover the registers: can happen only for spilling */
2461 /*-----------------------------------------------------------------*/
2462 static void genIpop (iCode *ic)
2466 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2467 assert (!"genIpop -- unimplemented");
2472 /* if the temp was not pushed then */
2473 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2476 aopOp(IC_LEFT(ic),ic,FALSE);
2477 size = AOP_SIZE(IC_LEFT(ic));
2480 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2483 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2487 /*-----------------------------------------------------------------*/
2488 /* unsaverbank - restores the resgister bank from stack */
2489 /*-----------------------------------------------------------------*/
2490 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2494 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2500 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2502 if (options.useXstack) {
2504 r = getFreePtr(ic,&aop,FALSE);
2507 pic14_emitcode("mov","%s,_spx",r->name);
2508 pic14_emitcode("movx","a,@%s",r->name);
2509 pic14_emitcode("mov","psw,a");
2510 pic14_emitcode("dec","%s",r->name);
2513 pic14_emitcode ("pop","psw");
2516 for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2517 if (options.useXstack) {
2518 pic14_emitcode("movx","a,@%s",r->name);
2519 //pic14_emitcode("mov","(%s+%d),a",
2520 // regspic14[i].base,8*bank+regspic14[i].offset);
2521 pic14_emitcode("dec","%s",r->name);
2524 pic14_emitcode("pop",""); //"(%s+%d)",
2525 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2528 if (options.useXstack) {
2530 pic14_emitcode("mov","_spx,%s",r->name);
2531 freeAsmop(NULL,aop,ic,TRUE);
2537 /*-----------------------------------------------------------------*/
2538 /* saverbank - saves an entire register bank on the stack */
2539 /*-----------------------------------------------------------------*/
2540 static void saverbank (int bank, iCode *ic, bool pushPsw)
2544 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2550 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2551 if (options.useXstack) {
2554 r = getFreePtr(ic,&aop,FALSE);
2555 pic14_emitcode("mov","%s,_spx",r->name);
2559 for (i = 0 ; i < pic14_nRegs ;i++) {
2560 if (options.useXstack) {
2561 pic14_emitcode("inc","%s",r->name);
2562 //pic14_emitcode("mov","a,(%s+%d)",
2563 // regspic14[i].base,8*bank+regspic14[i].offset);
2564 pic14_emitcode("movx","@%s,a",r->name);
2566 pic14_emitcode("push","");// "(%s+%d)",
2567 //regspic14[i].base,8*bank+regspic14[i].offset);
2571 if (options.useXstack) {
2572 pic14_emitcode("mov","a,psw");
2573 pic14_emitcode("movx","@%s,a",r->name);
2574 pic14_emitcode("inc","%s",r->name);
2575 pic14_emitcode("mov","_spx,%s",r->name);
2576 freeAsmop (NULL,aop,ic,TRUE);
2579 pic14_emitcode("push","psw");
2581 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2587 /*-----------------------------------------------------------------*/
2588 /* genCall - generates a call statement */
2589 /*-----------------------------------------------------------------*/
2590 static void genCall (iCode *ic)
2594 unsigned char *name;
2599 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2601 /* if caller saves & we have not saved then */
2605 /* if we are calling a function that is not using
2606 the same register bank then we need to save the
2607 destination registers on the stack */
2608 dtype = operandType(IC_LEFT(ic));
2609 if (currFunc && dtype &&
2610 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2611 IFFUNC_ISISR(currFunc->type) &&
2614 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2616 /* if send set is not empty the assign */
2619 /* For the Pic port, there is no data stack.
2620 * So parameters passed to functions are stored
2621 * in registers. (The pCode optimizer will get
2622 * rid of most of these :).
2624 int psuedoStkPtr=-1;
2625 int firstTimeThruLoop = 1;
2627 _G.sendSet = reverseSet(_G.sendSet);
2629 /* First figure how many parameters are getting passed */
2630 for (sic = setFirstItem(_G.sendSet) ; sic ;
2631 sic = setNextItem(_G.sendSet)) {
2633 aopOp(IC_LEFT(sic),sic,FALSE);
2634 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2635 freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2638 for (sic = setFirstItem(_G.sendSet) ; sic ;
2639 sic = setNextItem(_G.sendSet)) {
2640 int size, offset = 0;
2642 aopOp(IC_LEFT(sic),sic,FALSE);
2643 size = AOP_SIZE(IC_LEFT(sic));
2646 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2647 AopType(AOP_TYPE(IC_LEFT(sic))));
2649 if(!firstTimeThruLoop) {
2650 /* If this is not the first time we've been through the loop
2651 * then we need to save the parameter in a temporary
2652 * register. The last byte of the last parameter is
2654 emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2657 firstTimeThruLoop=0;
2659 mov2w_op (IC_LEFT(sic), offset);
2662 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2667 sym = OP_SYMBOL(IC_LEFT(ic));
2668 name = sym->rname[0] ? sym->rname : sym->name;
2669 isExtern = IS_EXTERN(sym->etype);
2671 emitpcode(POC_PAGESEL,popGetWithString(name,1)); /* Extern functions maybe on another page - must call pagesel */
2673 emitpcode(POC_CALL,popGetWithString(name,isExtern));
2675 emitpcode(POC_PAGESEL,popGetWithString("$",0)); /* May have returned from another page - must call pagesel to restore PCLATH before next goto or call instruction */
2678 /* if we need assign a result value */
2679 if ((IS_ITEMP(IC_RESULT(ic)) &&
2680 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2681 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2682 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2685 aopOp(IC_RESULT(ic),ic,FALSE);
2688 assignResultValue(IC_RESULT(ic));
2690 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2691 AopType(AOP_TYPE(IC_RESULT(ic))));
2693 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2696 /* if register bank was saved then pop them */
2698 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2700 /* if we hade saved some registers then unsave them */
2701 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2702 unsaveRegisters (ic);
2707 /*-----------------------------------------------------------------*/
2708 /* genPcall - generates a call by pointer statement */
2709 /*-----------------------------------------------------------------*/
2710 static void genPcall (iCode *ic)
2713 symbol *albl = newiTempLabel(NULL);
2714 symbol *blbl = newiTempLabel(NULL);
2721 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2722 /* if caller saves & we have not saved then */
2726 /* if we are calling a function that is not using
2727 the same register bank then we need to save the
2728 destination registers on the stack */
2729 dtype = operandType(IC_LEFT(ic));
2730 if (currFunc && dtype &&
2731 IFFUNC_ISISR(currFunc->type) &&
2732 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2733 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2736 aopOp(left,ic,FALSE);
2737 DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2739 poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2741 pushSide(IC_LEFT(ic), FPTRSIZE);
2743 /* if send set is not empty, assign parameters */
2746 DEBUGpic14_emitcode ("; ***","%s %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2747 /* no way to pass args - W always gets used to make the call */
2749 /* first idea - factor out a common helper function and call it.
2750 But don't know how to get it generated only once in its own block
2752 if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2755 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2756 DEBUGpic14_emitcode ("; ***","%s %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2757 buffer = Safe_calloc(1,strlen(rname)+16);
2758 sprintf(buffer, "%s_goto_helper", rname);
2759 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2763 emitpcode(POC_CALL,popGetLabel(albl->key));
2764 pcop = popGetLabel(blbl->key);
2765 emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
2766 emitpcode(POC_GOTO,pcop);
2767 emitpLabel(albl->key);
2769 emitpcode(poc,popGetAddr(AOP(left),1,0));
2770 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2771 emitpcode(poc,popGetAddr(AOP(left),0,0));
2772 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2774 emitpLabel(blbl->key);
2776 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2778 /* if we need to assign a result value */
2779 if ((IS_ITEMP(IC_RESULT(ic)) &&
2780 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2781 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2782 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2785 aopOp(IC_RESULT(ic),ic,FALSE);
2790 assignResultValue(IC_RESULT(ic));
2792 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2795 /* if register bank was saved then unsave them */
2796 if (currFunc && dtype &&
2797 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2798 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2800 /* if we hade saved some registers then
2803 unsaveRegisters (ic);
2807 /*-----------------------------------------------------------------*/
2808 /* resultRemat - result is rematerializable */
2809 /*-----------------------------------------------------------------*/
2810 static int resultRemat (iCode *ic)
2812 // DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2815 if (SKIP_IC(ic) || ic->op == IFX)
2818 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2819 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2820 if (sym->remat && !POINTER_SET(ic))
2827 #if defined(__BORLANDC__) || defined(_MSC_VER)
2828 #define STRCASECMP stricmp
2830 #define STRCASECMP strcasecmp
2834 /*-----------------------------------------------------------------*/
2835 /* inExcludeList - return 1 if the string is in exclude Reg list */
2836 /*-----------------------------------------------------------------*/
2837 static bool inExcludeList(char *s)
2839 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2842 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2843 if (options.excludeRegs[i] &&
2844 STRCASECMP(options.excludeRegs[i],"none") == 0)
2847 for ( i = 0 ; options.excludeRegs[i]; i++) {
2848 if (options.excludeRegs[i] &&
2849 STRCASECMP(s,options.excludeRegs[i]) == 0)
2856 /*-----------------------------------------------------------------*/
2857 /* genFunction - generated code for function entry */
2858 /*-----------------------------------------------------------------*/
2859 static void genFunction (iCode *ic)
2866 DEBUGpic14_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2868 labelOffset += (max_key+4);
2872 /* create the function header */
2873 pic14_emitcode(";","-----------------------------------------");
2874 pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2875 pic14_emitcode(";","-----------------------------------------");
2877 pic14_emitcode("","%s:",sym->rname);
2878 addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2880 ftype = operandType(IC_LEFT(ic));
2882 /* if critical function then turn interrupts off */
2883 if (IFFUNC_ISCRITICAL(ftype))
2884 pic14_emitcode("clr","ea");
2886 /* here we need to generate the equates for the
2887 register bank if required */
2889 if (FUNC_REGBANK(ftype) != rbank) {
2892 rbank = FUNC_REGBANK(ftype);
2893 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2894 if (strcmp(regspic14[i].base,"0") == 0)
2895 pic14_emitcode("","%s = 0x%02x",
2897 8*rbank+regspic14[i].offset);
2899 pic14_emitcode ("","%s = %s + 0x%02x",
2902 8*rbank+regspic14[i].offset);
2907 /* if this is an interrupt service routine */
2908 if (IFFUNC_ISISR(sym->type)) {
2909 /* already done in pic14createInterruptVect() - delete me
2910 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2911 emitpcodeNULLop(POC_NOP);
2912 emitpcodeNULLop(POC_NOP);
2913 emitpcodeNULLop(POC_NOP);
2915 emitpcode(POC_MOVWF, popCopyReg(&pc_wsave));
2916 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2917 emitpcode(POC_CLRF, popCopyReg(&pc_status));
2918 emitpcode(POC_MOVWF, popCopyReg(&pc_ssave));
2919 emitpcode(POC_MOVFW, popCopyReg(&pc_pclath));
2920 emitpcode(POC_MOVWF, popCopyReg(&pc_psave));
2921 emitpcode(POC_CLRF, popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2923 pBlockConvert2ISR(pb);
2925 if (!inExcludeList("acc"))
2926 pic14_emitcode ("push","acc");
2927 if (!inExcludeList("b"))
2928 pic14_emitcode ("push","b");
2929 if (!inExcludeList("dpl"))
2930 pic14_emitcode ("push","dpl");
2931 if (!inExcludeList("dph"))
2932 pic14_emitcode ("push","dph");
2933 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2935 pic14_emitcode ("push", "dpx");
2936 /* Make sure we're using standard DPTR */
2937 pic14_emitcode ("push", "dps");
2938 pic14_emitcode ("mov", "dps, #0x00");
2939 if (options.stack10bit)
2941 /* This ISR could conceivably use DPTR2. Better save it. */
2942 pic14_emitcode ("push", "dpl1");
2943 pic14_emitcode ("push", "dph1");
2944 pic14_emitcode ("push", "dpx1");
2947 /* if this isr has no bank i.e. is going to
2948 run with bank 0 , then we need to save more
2950 if (!FUNC_REGBANK(sym->type)) {
2952 /* if this function does not call any other
2953 function then we can be economical and
2954 save only those registers that are used */
2955 if (! IFFUNC_HASFCALL(sym->type)) {
2958 /* if any registers used */
2959 if (sym->regsUsed) {
2960 /* save the registers used */
2961 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2962 if (bitVectBitValue(sym->regsUsed,i) ||
2963 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2964 pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);
2969 /* this function has a function call cannot
2970 determines register usage so we will have the
2972 saverbank(0,ic,FALSE);
2977 /* if callee-save to be used for this function
2978 then save the registers being used in this function */
2979 if (IFFUNC_CALLEESAVES(sym->type)) {
2982 /* if any registers used */
2983 if (sym->regsUsed) {
2984 /* save the registers used */
2985 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2986 if (bitVectBitValue(sym->regsUsed,i) ||
2987 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2988 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2996 /* set the register bank to the desired value */
2997 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2998 pic14_emitcode("push","psw");
2999 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);
3002 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3004 if (options.useXstack) {
3005 pic14_emitcode("mov","r0,%s",spname);
3006 pic14_emitcode("mov","a,_bp");
3007 pic14_emitcode("movx","@r0,a");
3008 pic14_emitcode("inc","%s",spname);
3012 /* set up the stack */
3013 pic14_emitcode ("push","_bp"); /* save the callers stack */
3015 pic14_emitcode ("mov","_bp,%s",spname);
3018 /* adjust the stack for the function */
3023 werror(W_STACK_OVERFLOW,sym->name);
3025 if (i > 3 && sym->recvSize < 4) {
3027 pic14_emitcode ("mov","a,sp");
3028 pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3029 pic14_emitcode ("mov","sp,a");
3034 pic14_emitcode("inc","sp");
3039 pic14_emitcode ("mov","a,_spx");
3040 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3041 pic14_emitcode ("mov","_spx,a");
3046 /*-----------------------------------------------------------------*/
3047 /* genEndFunction - generates epilogue for functions */
3048 /*-----------------------------------------------------------------*/
3049 static void genEndFunction (iCode *ic)
3051 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3055 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3057 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3059 pic14_emitcode ("mov","%s,_bp",spname);
3062 /* if use external stack but some variables were
3063 added to the local stack then decrement the
3065 if (options.useXstack && sym->stack) {
3066 pic14_emitcode("mov","a,sp");
3067 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3068 pic14_emitcode("mov","sp,a");
3072 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3073 if (options.useXstack) {
3074 pic14_emitcode("mov","r0,%s",spname);
3075 pic14_emitcode("movx","a,@r0");
3076 pic14_emitcode("mov","_bp,a");
3077 pic14_emitcode("dec","%s",spname);
3081 pic14_emitcode ("pop","_bp");
3085 /* restore the register bank */
3086 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3087 pic14_emitcode ("pop","psw");
3089 if (IFFUNC_ISISR(sym->type)) {
3091 /* now we need to restore the registers */
3092 /* if this isr has no bank i.e. is going to
3093 run with bank 0 , then we need to save more
3095 if (!FUNC_REGBANK(sym->type)) {
3097 /* if this function does not call any other
3098 function then we can be economical and
3099 save only those registers that are used */
3100 if (! IFFUNC_HASFCALL(sym->type)) {
3103 /* if any registers used */
3104 if (sym->regsUsed) {
3105 /* save the registers used */
3106 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3107 if (bitVectBitValue(sym->regsUsed,i) ||
3108 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3109 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3114 /* this function has a function call cannot
3115 determines register usage so we will have the
3117 unsaverbank(0,ic,FALSE);
3121 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3123 if (options.stack10bit)
3125 pic14_emitcode ("pop", "dpx1");
3126 pic14_emitcode ("pop", "dph1");
3127 pic14_emitcode ("pop", "dpl1");
3129 pic14_emitcode ("pop", "dps");
3130 pic14_emitcode ("pop", "dpx");
3132 if (!inExcludeList("dph"))
3133 pic14_emitcode ("pop","dph");
3134 if (!inExcludeList("dpl"))
3135 pic14_emitcode ("pop","dpl");
3136 if (!inExcludeList("b"))
3137 pic14_emitcode ("pop","b");
3138 if (!inExcludeList("acc"))
3139 pic14_emitcode ("pop","acc");
3141 if (IFFUNC_ISCRITICAL(sym->type))
3142 pic14_emitcode("setb","ea");
3145 /* if debug then send end of function */
3146 /* if (options.debug && currFunc) { */
3148 debugFile->writeEndFunction (currFunc, ic, 1);
3151 pic14_emitcode ("reti","");
3152 emitpcode(POC_MOVFW, popCopyReg(&pc_psave));
3153 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
3154 emitpcode(POC_CLRF, popCopyReg(&pc_status));
3155 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3156 emitpcode(POC_MOVWF, popCopyReg(&pc_status));
3157 emitpcode(POC_SWAPF, popCopyReg(&pc_wsave));
3158 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3159 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3160 emitpcodeNULLop(POC_RETFIE);
3163 if (IFFUNC_ISCRITICAL(sym->type))
3164 pic14_emitcode("setb","ea");
3166 if (IFFUNC_CALLEESAVES(sym->type)) {
3169 /* if any registers used */
3170 if (sym->regsUsed) {
3171 /* save the registers used */
3172 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3173 if (bitVectBitValue(sym->regsUsed,i) ||
3174 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3175 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3181 /* if debug then send end of function */
3183 debugFile->writeEndFunction (currFunc, ic, 1);
3186 pic14_emitcode ("return","");
3187 emitpcodeNULLop(POC_RETURN);
3189 /* Mark the end of a function */
3190 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3195 /*-----------------------------------------------------------------*/
3196 /* genRet - generate code for return statement */
3197 /*-----------------------------------------------------------------*/
3198 static void genRet (iCode *ic)
3200 int size,offset = 0;
3204 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3205 /* if we have no return value then
3206 just generate the "ret" */
3210 /* we have something to return then
3211 move the return value into place */
3212 aopOp(IC_LEFT(ic),ic,FALSE);
3213 size = AOP_SIZE(IC_LEFT(ic));
3215 for (offset = 0; offset < size; offset++)
3217 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
3220 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3223 /* generate a jump to the return label
3224 if the next is not the return statement */
3225 if (!(ic->next && ic->next->op == LABEL &&
3226 IC_LABEL(ic->next) == returnLabel)) {
3228 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3233 /*-----------------------------------------------------------------*/
3234 /* genLabel - generates a label */
3235 /*-----------------------------------------------------------------*/
3236 static void genLabel (iCode *ic)
3240 /* special case never generate */
3241 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3242 if (IC_LABEL(ic) == entryLabel)
3245 emitpLabel(IC_LABEL(ic)->key);
3246 pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3249 /*-----------------------------------------------------------------*/
3250 /* genGoto - generates a goto */
3251 /*-----------------------------------------------------------------*/
3253 static void genGoto (iCode *ic)
3257 emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3258 pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3262 /*-----------------------------------------------------------------*/
3263 /* genMultbits :- multiplication of bits */
3264 /*-----------------------------------------------------------------*/
3265 static void genMultbits (operand *left,
3270 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3272 if(!pic14_sameRegs(AOP(result),AOP(right)))
3273 emitpcode(POC_BSF, popGet(AOP(result),0));
3275 emitpcode(POC_BTFSC,popGet(AOP(right),0));
3276 emitpcode(POC_BTFSS,popGet(AOP(left),0));
3277 emitpcode(POC_BCF, popGet(AOP(result),0));
3282 /*-----------------------------------------------------------------*/
3283 /* genMultOneByte : 8 bit multiplication & division */
3284 /*-----------------------------------------------------------------*/
3285 static void genMultOneByte (operand *left,
3289 char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
3297 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3298 DEBUGpic14_AopType(__LINE__,left,right,result);
3299 DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3301 /* (if two literals, the value is computed before) */
3302 /* if one literal, literal on the right */
3303 if (AOP_TYPE(left) == AOP_LIT){
3309 assert (AOP_SIZE(left) == AOP_SIZE(right));
3311 size = min(AOP_SIZE(result),AOP_SIZE(left));
3312 offset = Gstack_base_addr - (2*size - 1);
3314 /* pass right operand as argument */
3315 for (i=0; i < size; i++)
3317 mov2w (AOP(right), i);
3318 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3321 /* pass left operand as argument */
3322 for (i=0; i < size; i++)
3324 mov2w (AOP(left), i);
3325 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3327 assert (offset == Gstack_base_addr);
3329 /* call library routine */
3330 assert (size > 0 && size <= 4);
3331 call_libraryfunc (func[size]);
3334 movwf (AOP(result), size-1);
3335 for (i=0; i < size - 1; i++)
3337 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
3338 movwf (AOP(result), size - 2 - i);
3341 /* now (zero-/sign) extend the result to its size */
3342 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
3345 /*-----------------------------------------------------------------*/
3346 /* genMult - generates code for multiplication */
3347 /*-----------------------------------------------------------------*/
3348 static void genMult (iCode *ic)
3350 operand *left = IC_LEFT(ic);
3351 operand *right = IC_RIGHT(ic);
3352 operand *result= IC_RESULT(ic);
3356 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3357 /* assign the amsops */
3358 aopOp (left,ic,FALSE);
3359 aopOp (right,ic,FALSE);
3360 aopOp (result,ic,TRUE);
3362 DEBUGpic14_AopType(__LINE__,left,right,result);
3364 /* special cases first */
3366 if (AOP_TYPE(left) == AOP_CRY &&
3367 AOP_TYPE(right)== AOP_CRY) {
3368 genMultbits(left,right,result);
3372 /* if both are of size == 1 */
3373 if (AOP_SIZE(left) == 1 &&
3374 AOP_SIZE(right) == 1 ) {
3375 genMultOneByte(left,right,result);
3379 /* should have been converted to function call */
3383 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3384 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3385 freeAsmop(result,NULL,ic,TRUE);
3388 /*-----------------------------------------------------------------*/
3389 /* genDivbits :- division of bits */
3390 /*-----------------------------------------------------------------*/
3391 static void genDivbits (operand *left,
3400 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3401 /* the result must be bit */
3402 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3403 l = aopGet(AOP(left),0,FALSE,FALSE);
3407 pic14_emitcode("div","ab");
3408 pic14_emitcode("rrc","a");
3409 aopPut(AOP(result),"c",0);
3412 /*-----------------------------------------------------------------*/
3413 /* genDivOneByte : 8 bit division */
3414 /*-----------------------------------------------------------------*/
3415 static void genDivOneByte (operand *left,
3422 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3424 assert (AOP_SIZE(result) == 1);
3425 assert (AOP_SIZE(right) == 1);
3426 assert (AOP_SIZE(left) == 1);
3428 size = min(AOP_SIZE(result),AOP_SIZE(left));
3430 if (AOP_TYPE(right) == AOP_LIT)
3432 /* XXX: might add specialized code */
3435 if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3437 /* unsigned division */
3439 mov2w(AOP(right),0);
3440 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3442 call_libraryfunc("__divuchar");
3443 movwf(AOP(result),0);
3448 temp = popGetTempReg();
3449 lbl = newiTempLabel(NULL);
3451 /* XXX: improve this naive approach:
3452 [result] = [a] / [b]
3453 ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
3457 movwf temp // temp <-- left
3458 movf right,W // W <-- right
3462 subwf temp,F // temp <-- temp - W
3463 skipNC // subwf clears CARRY (i.e. sets BORROW) if temp < W
3465 decf result // we just subtract once too often
3468 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3469 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
3472 emitpcode(POC_MOVWF, temp);
3473 mov2w(AOP(right),0);
3474 emitpcode(POC_CLRF, popGet(AOP(result),0));
3476 emitpLabel(lbl->key);
3477 emitpcode(POC_INCF, popGet(AOP(result),0));
3478 emitpcode(POC_SUBWF, temp);
3480 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3481 emitpcode(POC_DECF, popGet(AOP(result),0));
3486 /* signed division */
3487 mov2w(AOP(right),0);
3488 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3490 call_libraryfunc("__divschar");
3491 movwf(AOP(result),0);
3494 /* now performed the signed/unsigned division -- extend result */
3495 addSign(result, 1, !SPEC_USIGN(operandType(result)));
3498 /*-----------------------------------------------------------------*/
3499 /* genDiv - generates code for division */
3500 /*-----------------------------------------------------------------*/
3501 static void genDiv (iCode *ic)
3503 operand *left = IC_LEFT(ic);
3504 operand *right = IC_RIGHT(ic);
3505 operand *result= IC_RESULT(ic);
3508 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3509 /* assign the amsops */
3510 aopOp (left,ic,FALSE);
3511 aopOp (right,ic,FALSE);
3512 aopOp (result,ic,TRUE);
3514 /* special cases first */
3516 if (AOP_TYPE(left) == AOP_CRY &&
3517 AOP_TYPE(right)== AOP_CRY) {
3518 genDivbits(left,right,result);
3522 /* if both are of size == 1 */
3523 if (AOP_SIZE(left) == 1 &&
3524 AOP_SIZE(right) == 1 ) {
3525 genDivOneByte(left,right,result);
3529 /* should have been converted to function call */
3532 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3533 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3534 freeAsmop(result,NULL,ic,TRUE);
3537 /*-----------------------------------------------------------------*/
3538 /* genModbits :- modulus of bits */
3539 /*-----------------------------------------------------------------*/
3540 static void genModbits (operand *left,
3548 /* the result must be bit */
3549 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3550 l = aopGet(AOP(left),0,FALSE,FALSE);
3554 pic14_emitcode("div","ab");
3555 pic14_emitcode("mov","a,b");
3556 pic14_emitcode("rrc","a");
3557 aopPut(AOP(result),"c",0);
3560 /*-----------------------------------------------------------------*/
3561 /* genModOneByte : 8 bit modulus */
3562 /*-----------------------------------------------------------------*/
3563 static void genModOneByte (operand *left,
3570 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3572 assert (AOP_SIZE(result) == 1);
3573 assert (AOP_SIZE(right) == 1);
3574 assert (AOP_SIZE(left) == 1);
3576 size = min(AOP_SIZE(result),AOP_SIZE(left));
3578 if (AOP_TYPE(right) == AOP_LIT)
3580 /* XXX: might add specialized code */
3583 if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3585 /* unsigned division */
3587 mov2w(AOP(right),0);
3588 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3590 call_libraryfunc("__moduchar");
3591 movwf(AOP(result),0);
3596 lbl = newiTempLabel(NULL);
3598 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3600 /* XXX: improve this naive approach:
3601 [result] = [a] % [b]
3602 ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3606 movwf result // result <-- left
3607 movf right,W // W <-- right
3609 subwf result,F // result <-- result - W
3610 skipNC // subwf clears CARRY (i.e. sets BORROW) if result < W
3612 addwf result, F // we just subtract once too often
3615 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3616 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3618 if (!pic14_sameRegs(AOP(left), AOP(result)))
3621 emitpcode(POC_MOVWF, popGet(AOP(result),0));
3623 mov2w(AOP(right),0);
3625 emitpLabel(lbl->key);
3626 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3628 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3629 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3634 /* signed division */
3635 mov2w(AOP(right),0);
3636 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3638 call_libraryfunc("__modschar");
3639 movwf(AOP(result),0);
3642 /* now we performed the signed/unsigned modulus -- extend result */
3643 addSign(result, 1, !SPEC_USIGN(operandType(result)));
3646 /*-----------------------------------------------------------------*/
3647 /* genMod - generates code for division */
3648 /*-----------------------------------------------------------------*/
3649 static void genMod (iCode *ic)
3651 operand *left = IC_LEFT(ic);
3652 operand *right = IC_RIGHT(ic);
3653 operand *result= IC_RESULT(ic);
3656 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3657 /* assign the amsops */
3658 aopOp (left,ic,FALSE);
3659 aopOp (right,ic,FALSE);
3660 aopOp (result,ic,TRUE);
3662 /* special cases first */
3664 if (AOP_TYPE(left) == AOP_CRY &&
3665 AOP_TYPE(right)== AOP_CRY) {
3666 genModbits(left,right,result);
3670 /* if both are of size == 1 */
3671 if (AOP_SIZE(left) == 1 &&
3672 AOP_SIZE(right) == 1 ) {
3673 genModOneByte(left,right,result);
3677 /* should have been converted to function call */
3681 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3682 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3683 freeAsmop(result,NULL,ic,TRUE);
3686 /*-----------------------------------------------------------------*/
3687 /* genIfxJump :- will create a jump depending on the ifx */
3688 /*-----------------------------------------------------------------*/
3690 note: May need to add parameter to indicate when a variable is in bit space.
3692 static void genIfxJump (iCode *ic, char *jval)
3696 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3697 /* if true label then we jump if condition
3699 if ( IC_TRUE(ic) ) {
3701 if(strcmp(jval,"a") == 0)
3703 else if (strcmp(jval,"c") == 0)
3706 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3707 emitpcode(POC_BTFSC, newpCodeOpBit(jval,-1,1));
3710 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3711 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3715 /* false label is present */
3716 if(strcmp(jval,"a") == 0)
3718 else if (strcmp(jval,"c") == 0)
3721 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3722 emitpcode(POC_BTFSS, newpCodeOpBit(jval,-1,1));
3725 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3726 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3731 /* mark the icode as generated */
3736 /*-----------------------------------------------------------------*/
3738 /*-----------------------------------------------------------------*/
3739 static void genSkip(iCode *ifx,int status_bit)
3745 if ( IC_TRUE(ifx) ) {
3746 switch(status_bit) {
3761 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3762 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3766 switch(status_bit) {
3780 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3781 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3788 /*-----------------------------------------------------------------*/
3790 /*-----------------------------------------------------------------*/
3791 static void genSkipc(resolvedIfx *rifx)
3802 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3803 emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3804 rifx->generated = 1;
3808 /*-----------------------------------------------------------------*/
3810 /*-----------------------------------------------------------------*/
3811 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3817 if( (rifx->condition ^ invert_condition) & 1)
3822 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3823 rifx->generated = 1;
3828 /*-----------------------------------------------------------------*/
3830 /*-----------------------------------------------------------------*/
3831 static void genSkipz(iCode *ifx, int condition)
3834 assert (ifx != NULL);
3842 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3844 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3847 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3849 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3855 /*-----------------------------------------------------------------*/
3857 /*-----------------------------------------------------------------*/
3858 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3865 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3867 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3870 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3871 rifx->generated = 1;
3876 /*-----------------------------------------------------------------*/
3877 /* genChkZeroes :- greater or less than comparison */
3878 /* For each byte in a literal that is zero, inclusive or the */
3879 /* the corresponding byte in the operand with W */
3880 /* returns true if any of the bytes are zero */
3881 /*-----------------------------------------------------------------*/
3882 static int genChkZeroes(operand *op, int lit, int size)
3889 i = (lit >> (size*8)) & 0xff;
3893 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3895 emitpcode(POC_IORFW, popGet(AOP(op),size));
3905 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3906 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
3907 #define DEBUGpc emitpComment
3909 /*-----------------------------------------------------------------*/
3910 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
3911 /* aop (if it's NOT a literal) or from lit (if */
3912 /* aop is a literal) */
3913 /*-----------------------------------------------------------------*/
3914 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3915 if (aop->type == AOP_LIT) {
3916 emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3918 emitpcode (POC_MOVFW, popGet (aop, offset));
3922 /* genCmp performs a left < right comparison, stores
3923 * the outcome in result (if != NULL) and generates
3924 * control flow code for the ifx (if != NULL).
3926 * This version leaves in sequences like
3927 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3928 * which should be optmized by the peephole
3929 * optimizer - RN 2005-01-01 */
3930 static void genCmp (operand *left,operand *right,
3931 operand *result, iCode *ifx, int sign)
3941 int invert_result = 0;
3945 assert (AOP_SIZE(left) == AOP_SIZE(right));
3946 assert (left && right);
3948 size = AOP_SIZE(right) - 1;
3949 mask = (0x100UL << (size*8)) - 1;
3950 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3955 resolveIfx (&rIfx, ifx);
3957 /**********************************************************************
3958 * handle bits - bit compares are promoted to int compares seemingly! *
3959 **********************************************************************/
3961 // THIS IS COMPLETELY UNTESTED!
3962 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3963 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3964 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3965 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3968 // 1 < {0,1} is false --> clear C by skipping the next instruction
3969 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3970 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3971 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3972 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3973 emitCLRC; // only skipped for left=0 && right=1
3975 goto correct_result_in_carry;
3979 /*************************************************
3980 * make sure that left is register (or the like) *
3981 *************************************************/
3982 if (!isAOP_REGlike(left)) {
3983 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
3984 assert (isAOP_LIT(left));
3985 assert (isAOP_REGlike(right));
3986 // swap left and right
3987 // left < right <==> right > left <==> (right >= left + 1)
3988 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3990 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
3991 // MAXVALUE < right? always false
3992 if (performedLt) emitCLRC; else emitSETC;
3993 goto correct_result_in_carry;
3996 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
3997 // that's why we handled it above.
4004 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4005 } else if (isAOP_LIT(right)) {
4006 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4009 assert (isAOP_REGlike(left)); // left must be register or the like
4010 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4012 /*************************************************
4013 * special cases go here *
4014 *************************************************/
4016 if (isAOP_LIT(right)) {
4018 // unsigned comparison to a literal
4019 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4021 // unsigned left < 0? always false
4022 if (performedLt) emitCLRC; else emitSETC;
4023 goto correct_result_in_carry;
4026 // signed comparison to a literal
4027 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4028 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4029 // signed left < 0x80000000? always false
4030 if (performedLt) emitCLRC; else emitSETC;
4031 goto correct_result_in_carry;
4032 } else if (lit == 0) {
4033 // compare left < 0; set CARRY if SIGNBIT(left) is set
4034 if (performedLt) emitSETC; else emitCLRC;
4035 emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
4036 if (performedLt) emitCLRC; else emitSETC;
4037 goto correct_result_in_carry;
4040 } // right is literal
4042 /*************************************************
4043 * perform a general case comparison *
4044 * make sure we get CARRY==1 <==> left >= right *
4045 *************************************************/
4046 // compare most significant bytes
4047 //DEBUGpc ("comparing bytes at offset %d", size);
4049 // unsigned comparison
4050 pic14_mov2w_regOrLit (AOP(right), lit, size);
4051 emitpcode (POC_SUBFW, popGet (AOP(left), size));
4053 // signed comparison
4054 // (add 2^n to both operands then perform an unsigned comparison)
4055 if (isAOP_LIT(right)) {
4056 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4057 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4059 if (litbyte == 0x80) {
4060 // left >= 0x80 -- always true, but more bytes to come
4061 mov2w (AOP(left), size);
4062 emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
4065 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4066 mov2w (AOP(left), size);
4067 emitpcode (POC_ADDLW, popGetLit (0x80));
4068 emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4071 pCodeOp *pctemp = popGetTempReg();
4072 mov2w (AOP(left), size);
4073 emitpcode (POC_ADDLW, popGetLit (0x80));
4074 emitpcode (POC_MOVWF, pctemp);
4075 mov2w (AOP(right), size);
4076 emitpcode (POC_ADDLW, popGetLit (0x80));
4077 emitpcode (POC_SUBFW, pctemp);
4078 popReleaseTempReg(pctemp);
4082 // compare remaining bytes (treat as unsigned case from above)
4083 templbl = newiTempLabel ( NULL );
4086 //DEBUGpc ("comparing bytes at offset %d", offs);
4088 emitpcode (POC_GOTO, popGetLabel (templbl->key));
4089 pic14_mov2w_regOrLit (AOP(right), lit, offs);
4090 emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4092 emitpLabel (templbl->key);
4093 goto result_in_carry;
4097 /****************************************************
4098 * now CARRY contains the result of the comparison: *
4099 * SUBWF sets CARRY iff *
4100 * F-W >= 0 <==> F >= W <==> !(F < W) *
4101 * (F=left, W=right) *
4102 ****************************************************/
4106 // value will be used in the following genSkipc()
4107 rIfx.condition ^= 1;
4110 correct_result_in_carry:
4112 // assign result to variable (if neccessary)
4113 if (result && AOP_TYPE(result) != AOP_CRY) {
4114 //DEBUGpc ("assign result");
4115 size = AOP_SIZE(result);
4117 emitpcode (POC_CLRF, popGet (AOP(result), size));
4119 if (invert_result) {
4121 emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4123 emitpcode (POC_RLF, popGet (AOP(result), 0));
4127 // perform conditional jump
4129 //DEBUGpc ("generate control flow");
4137 /* OLD VERSION -- BUGGY, DO NOT USE */
4139 /*-----------------------------------------------------------------*/
4140 /* genCmp :- greater or less than comparison */
4141 /*-----------------------------------------------------------------*/
4142 static void genCmp (operand *left,operand *right,
4143 operand *result, iCode *ifx, int sign)
4145 int size; //, offset = 0 ;
4146 unsigned long lit = 0L,i = 0;
4147 resolvedIfx rFalseIfx;
4148 // resolvedIfx rTrueIfx;
4152 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4155 DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4156 DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4160 resolveIfx(&rFalseIfx,ifx);
4161 truelbl = newiTempLabel(NULL);
4162 size = max(AOP_SIZE(left),AOP_SIZE(right));
4164 DEBUGpic14_AopType(__LINE__,left,right,result);
4168 /* if literal is on the right then swap with left */
4169 if ((AOP_TYPE(right) == AOP_LIT)) {
4170 operand *tmp = right ;
4171 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4172 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4175 lit = (lit - 1) & mask;
4178 rFalseIfx.condition ^= 1;
4181 } else if ((AOP_TYPE(left) == AOP_LIT)) {
4182 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4186 //if(IC_TRUE(ifx) == NULL)
4187 /* if left & right are bit variables */
4188 if (AOP_TYPE(left) == AOP_CRY &&
4189 AOP_TYPE(right) == AOP_CRY ) {
4190 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4191 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4193 /* subtract right from left if at the
4194 end the carry flag is set then we know that
4195 left is greater than right */
4197 symbol *lbl = newiTempLabel(NULL);
4200 if(AOP_TYPE(right) == AOP_LIT) {
4202 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4204 DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4211 genSkipCond(&rFalseIfx,left,size-1,7);
4213 /* no need to compare to 0...*/
4214 /* NOTE: this is a de-generate compare that most certainly
4215 * creates some dead code. */
4216 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4218 if(ifx) ifx->generated = 1;
4225 //i = (lit >> (size*8)) & 0xff;
4226 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4228 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4230 i = ((0-lit) & 0xff);
4233 /* lit is 0x7f, all signed chars are less than
4234 * this except for 0x7f itself */
4235 emitpcode(POC_XORLW, popGetLit(0x7f));
4236 genSkipz2(&rFalseIfx,0);
4238 emitpcode(POC_ADDLW, popGetLit(0x80));
4239 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4240 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4245 genSkipz2(&rFalseIfx,1);
4247 emitpcode(POC_ADDLW, popGetLit(i));
4248 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4252 if(ifx) ifx->generated = 1;
4256 /* chars are out of the way. now do ints and longs */
4259 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4266 genSkipCond(&rFalseIfx,left,size,7);
4267 if(ifx) ifx->generated = 1;
4272 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4274 //rFalseIfx.condition ^= 1;
4275 //genSkipCond(&rFalseIfx,left,size,7);
4276 //rFalseIfx.condition ^= 1;
4278 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4279 if(rFalseIfx.condition)
4280 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4282 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4284 emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4285 emitpcode(POC_ADDFW, popGet(AOP(left),0));
4286 emitpcode(POC_MOVFW, popGet(AOP(left),1));
4289 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4291 if(rFalseIfx.condition) {
4293 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4299 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4300 emitpLabel(truelbl->key);
4301 if(ifx) ifx->generated = 1;
4308 if( (lit & 0xff) == 0) {
4309 /* lower byte is zero */
4310 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4311 i = ((lit >> 8) & 0xff) ^0x80;
4312 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4313 emitpcode(POC_ADDLW, popGetLit( 0x80));
4314 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4315 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4318 if(ifx) ifx->generated = 1;
4323 /* Special cases for signed longs */
4324 if( (lit & 0xffffff) == 0) {
4325 /* lower byte is zero */
4326 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4327 i = ((lit >> 8*3) & 0xff) ^0x80;
4328 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4329 emitpcode(POC_ADDLW, popGetLit( 0x80));
4330 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4331 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4334 if(ifx) ifx->generated = 1;
4342 if(lit & (0x80 << (size*8))) {
4343 /* lit is negative */
4344 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4346 //genSkipCond(&rFalseIfx,left,size,7);
4348 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4350 if(rFalseIfx.condition)
4351 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4353 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4357 /* lit is positive */
4358 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4359 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4360 if(rFalseIfx.condition)
4361 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4363 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4367 /* There are no more special cases, so perform a general compare */
4369 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4370 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4374 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4376 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4378 //rFalseIfx.condition ^= 1;
4379 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4381 emitpLabel(truelbl->key);
4383 if(ifx) ifx->generated = 1;
4390 /* sign is out of the way. So now do an unsigned compare */
4391 DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4394 /* General case - compare to an unsigned literal on the right.*/
4396 i = (lit >> (size*8)) & 0xff;
4397 emitpcode(POC_MOVLW, popGetLit(i));
4398 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4400 i = (lit >> (size*8)) & 0xff;
4403 emitpcode(POC_MOVLW, popGetLit(i));
4405 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4407 /* this byte of the lit is zero,
4408 *if it's not the last then OR in the variable */
4410 emitpcode(POC_IORFW, popGet(AOP(left),size));
4415 emitpLabel(lbl->key);
4416 //if(emitFinalCheck)
4417 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4419 emitpLabel(truelbl->key);
4421 if(ifx) ifx->generated = 1;
4428 if(AOP_TYPE(left) == AOP_LIT) {
4429 //symbol *lbl = newiTempLabel(NULL);
4431 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4434 DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4437 if((lit == 0) && (sign == 0)){
4440 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4442 emitpcode(POC_IORFW, popGet(AOP(right),--size));
4444 genSkipz2(&rFalseIfx,0);
4445 if(ifx) ifx->generated = 1;
4452 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4453 /* degenerate compare can never be true */
4454 if(rFalseIfx.condition == 0)
4455 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4457 if(ifx) ifx->generated = 1;
4462 /* signed comparisons to a literal byte */
4464 int lp1 = (lit+1) & 0xff;
4466 DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4469 rFalseIfx.condition ^= 1;
4470 genSkipCond(&rFalseIfx,right,0,7);
4473 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4474 emitpcode(POC_XORLW, popGetLit(0x7f));
4475 genSkipz2(&rFalseIfx,1);
4478 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4479 emitpcode(POC_ADDLW, popGetLit(0x80));
4480 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4481 rFalseIfx.condition ^= 1;
4482 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4485 if(ifx) ifx->generated = 1;
4487 /* unsigned comparisons to a literal byte */
4489 switch(lit & 0xff ) {
4491 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4492 genSkipz2(&rFalseIfx,0);
4493 if(ifx) ifx->generated = 1;
4496 genSkipCond(&rFalseIfx,right,0,7);
4497 if(ifx) ifx->generated = 1;
4501 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4502 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4503 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4504 rFalseIfx.condition ^= 1;
4505 if (AOP_TYPE(result) == AOP_CRY) {
4506 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4507 if(ifx) ifx->generated = 1;
4509 DEBUGpic14_emitcode ("; ***","%s %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4510 emitpcode(POC_CLRF, popGet(AOP(result),0));
4511 emitpcode(POC_RLF, popGet(AOP(result),0));
4512 emitpcode(POC_MOVLW, popGetLit(0x01));
4513 emitpcode(POC_XORWF, popGet(AOP(result),0));
4524 /* Size is greater than 1 */
4532 /* this means lit = 0xffffffff, or -1 */
4535 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4536 rFalseIfx.condition ^= 1;
4537 genSkipCond(&rFalseIfx,right,size,7);
4538 if(ifx) ifx->generated = 1;
4545 if(rFalseIfx.condition) {
4546 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4547 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4550 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4552 emitpcode(POC_IORFW, popGet(AOP(right),size));
4556 if(rFalseIfx.condition) {
4557 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4558 emitpLabel(truelbl->key);
4560 rFalseIfx.condition ^= 1;
4561 genSkipCond(&rFalseIfx,right,s,7);
4564 if(ifx) ifx->generated = 1;
4568 if((size == 1) && (0 == (lp1&0xff))) {
4569 /* lower byte of signed word is zero */
4570 DEBUGpic14_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
4571 i = ((lp1 >> 8) & 0xff) ^0x80;
4572 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4573 emitpcode(POC_ADDLW, popGetLit( 0x80));
4574 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4575 rFalseIfx.condition ^= 1;
4576 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4579 if(ifx) ifx->generated = 1;
4583 if(lit & (0x80 << (size*8))) {
4584 /* Lit is less than zero */
4585 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
4586 //rFalseIfx.condition ^= 1;
4587 //genSkipCond(&rFalseIfx,left,size,7);
4588 //rFalseIfx.condition ^= 1;
4589 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4590 //emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4592 if(rFalseIfx.condition)
4593 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4595 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4599 /* Lit is greater than or equal to zero */
4600 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
4601 //rFalseIfx.condition ^= 1;
4602 //genSkipCond(&rFalseIfx,right,size,7);
4603 //rFalseIfx.condition ^= 1;
4605 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4606 //emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4608 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4609 if(rFalseIfx.condition)
4610 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4612 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4617 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4618 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4622 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4624 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4626 rFalseIfx.condition ^= 1;
4627 //rFalseIfx.condition = 1;
4628 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4630 emitpLabel(truelbl->key);
4632 if(ifx) ifx->generated = 1;
4637 /* compare word or long to an unsigned literal on the right.*/
4642 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4645 break; /* handled above */
4648 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4650 emitpcode(POC_IORFW, popGet(AOP(right),size));
4651 genSkipz2(&rFalseIfx,0);
4655 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4657 emitpcode(POC_IORFW, popGet(AOP(right),size));
4660 if(rFalseIfx.condition)
4661 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4663 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4666 emitpcode(POC_MOVLW, popGetLit(lit+1));
4667 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4669 rFalseIfx.condition ^= 1;
4670 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4673 emitpLabel(truelbl->key);
4675 if(ifx) ifx->generated = 1;
4681 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4682 i = (lit >> (size*8)) & 0xff;
4684 emitpcode(POC_MOVLW, popGetLit(i));
4685 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4688 i = (lit >> (size*8)) & 0xff;
4691 emitpcode(POC_MOVLW, popGetLit(i));
4693 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4695 /* this byte of the lit is zero,
4696 *if it's not the last then OR in the variable */
4698 emitpcode(POC_IORFW, popGet(AOP(right),size));
4703 emitpLabel(lbl->key);
4705 rFalseIfx.condition ^= 1;
4706 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4710 emitpLabel(truelbl->key);
4711 if(ifx) ifx->generated = 1;
4715 /* Compare two variables */
4717 DEBUGpic14_emitcode(";sign","%d",sign);
4721 /* Sigh. thus sucks... */
4723 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4724 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4725 emitpcode(POC_MOVLW, popGetLit(0x80));
4726 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4727 emitpcode(POC_XORFW, popGet(AOP(right),size));
4728 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4730 /* Signed char comparison */
4731 /* Special thanks to Nikolai Golovchenko for this snippet */
4732 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4733 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4734 emitpcode(POC_RRFW, popGet(AOP(left),0)); /* could be any register */
4735 emitpcode(POC_XORFW, popGet(AOP(left),0));
4736 emitpcode(POC_XORFW, popGet(AOP(right),0));
4737 emitpcode(POC_ADDLW, popGetLit(0x80));
4739 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4740 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4742 if(ifx) ifx->generated = 1;
4748 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4749 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4753 /* The rest of the bytes of a multi-byte compare */
4757 emitpcode(POC_GOTO, popGetLabel(lbl->key));
4760 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4761 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4766 emitpLabel(lbl->key);
4768 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4769 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
4770 (AOP_TYPE(result) == AOP_REG)) {
4771 emitpcode(POC_CLRF, popGet(AOP(result),0));
4772 emitpcode(POC_RLF, popGet(AOP(result),0));
4774 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4776 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4777 if(ifx) ifx->generated = 1;
4784 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4785 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4786 pic14_outBitC(result);
4788 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4789 /* if the result is used in the next
4790 ifx conditional branch then generate
4791 code a little differently */
4793 genIfxJump (ifx,"c");
4795 pic14_outBitC(result);
4796 /* leave the result in acc */
4802 /*-----------------------------------------------------------------*/
4803 /* genCmpGt :- greater than comparison */
4804 /*-----------------------------------------------------------------*/
4805 static void genCmpGt (iCode *ic, iCode *ifx)
4807 operand *left, *right, *result;
4808 sym_link *letype , *retype;
4812 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4814 right= IC_RIGHT(ic);
4815 result = IC_RESULT(ic);
4817 letype = getSpec(operandType(left));
4818 retype =getSpec(operandType(right));
4819 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4820 /* assign the amsops */
4821 aopOp (left,ic,FALSE);
4822 aopOp (right,ic,FALSE);
4823 aopOp (result,ic,TRUE);
4825 genCmp(right, left, result, ifx, sign);
4827 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4828 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4829 freeAsmop(result,NULL,ic,TRUE);
4832 /*-----------------------------------------------------------------*/
4833 /* genCmpLt - less than comparisons */
4834 /*-----------------------------------------------------------------*/
4835 static void genCmpLt (iCode *ic, iCode *ifx)
4837 operand *left, *right, *result;
4838 sym_link *letype , *retype;
4842 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4844 right= IC_RIGHT(ic);
4845 result = IC_RESULT(ic);
4847 letype = getSpec(operandType(left));
4848 retype =getSpec(operandType(right));
4849 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4851 /* assign the amsops */
4852 aopOp (left,ic,FALSE);
4853 aopOp (right,ic,FALSE);
4854 aopOp (result,ic,TRUE);
4856 genCmp(left, right, result, ifx, sign);
4858 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4859 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4860 freeAsmop(result,NULL,ic,TRUE);
4864 /*-----------------------------------------------------------------*/
4865 /* genc16bit2lit - compare a 16 bit value to a literal */
4866 /*-----------------------------------------------------------------*/
4867 static void genc16bit2lit(operand *op, int lit, int offset)
4872 DEBUGpic14_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
4873 if( (lit&0xff) == 0)
4878 switch( BYTEofLONG(lit,i)) {
4880 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4883 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4886 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4889 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4890 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4895 switch( BYTEofLONG(lit,i)) {
4897 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4901 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4905 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4908 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4910 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4918 /*-----------------------------------------------------------------*/
4919 /* gencjneshort - compare and jump if not equal */
4920 /*-----------------------------------------------------------------*/
4921 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4923 int size = min(AOP_SIZE(left),AOP_SIZE(right));
4928 //unsigned long lit = 0L;
4930 if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4931 emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4934 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4935 DEBUGpic14_AopType(__LINE__,left,right,result);
4937 assert (!pic14_sameRegs (AOP(left), AOP(result)));
4938 assert (!pic14_sameRegs (AOP(right), AOP(result)));
4939 if (AOP_SIZE(result)) {
4940 for (offset = 0; offset < AOP_SIZE(result); offset++)
4941 emitpcode (POC_CLRF, popGet (AOP(result), offset));
4944 assert (AOP_SIZE(left) == AOP_SIZE(right));
4945 //resolveIfx(&rIfx,ifx);
4946 lbl = newiTempLabel (NULL);
4949 mov2w (AOP(right),size);
4950 emitpcode (POC_XORFW, popGet (AOP(left), size));
4954 emitpcode (POC_GOTO, popGetLabel (lbl->key));
4957 emitpLabel (lbl->key);
4958 if (AOP_SIZE(result)) {
4960 emitpcode (POC_INCF, popGet (AOP(result), 0));
4963 genSkipz (ifx, NULL != IC_TRUE(ifx));
4970 DEBUGpic14_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
4971 assert (!pic14_sameRegs (AOP(result), AOP(left)));
4972 assert (!pic14_sameRegs (AOP(result), AOP(right)));
4973 for (offset=0; offset < AOP_SIZE(result); offset++)
4975 emitpcode (POC_CLRF, popGet (AOP(result), offset));
4980 /* if the left side is a literal or
4981 if the right is in a pointer register and left
4983 if ((AOP_TYPE(left) == AOP_LIT) ||
4984 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4989 if(AOP_TYPE(right) == AOP_LIT)
4990 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4992 /* if the right side is a literal then anything goes */
4993 if (AOP_TYPE(right) == AOP_LIT &&
4994 AOP_TYPE(left) != AOP_DIR ) {
4997 genc16bit2lit(left, lit, 0);
4999 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5005 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5006 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5008 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5012 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5020 /* if the right side is in a register or in direct space or
5021 if the left is a pointer register & right is not */
5022 else if (AOP_TYPE(right) == AOP_REG ||
5023 AOP_TYPE(right) == AOP_DIR ||
5024 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5025 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5026 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5027 int lbl_key = lbl->key;
5030 DEBUGpic14_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
5031 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
5032 __FUNCTION__,__LINE__);
5036 /* switch(size) { */
5038 /* genc16bit2lit(left, lit, 0); */
5040 /* emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
5046 if((AOP_TYPE(left) == AOP_DIR) &&
5047 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5049 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5050 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5052 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5054 switch (lit & 0xff) {
5056 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5059 emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
5060 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5061 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5065 emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5066 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5067 //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5068 emitpcode(POC_GOTO,popGetLabel(lbl_key));
5072 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5073 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5078 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5081 if(AOP_TYPE(result) == AOP_CRY) {
5082 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5087 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5089 /* fix me. probably need to check result size too */
5090 //emitpcode(POC_CLRF,popGet(AOP(result),0));
5095 emitpcode(POC_GOTO,popGetLabel(lbl_key));
5105 } else if(AOP_TYPE(right) == AOP_REG &&
5106 AOP_TYPE(left) != AOP_DIR){
5110 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5111 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5112 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5117 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5122 /* right is a pointer reg need both a & b */
5125 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5127 pic14_emitcode("mov","b,%s",l);
5128 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5129 pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
5134 emitpcode(POC_INCF,popGet(AOP(result),0));
5136 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5138 emitpLabel(lbl->key);
5140 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5149 /*-----------------------------------------------------------------*/
5150 /* gencjne - compare and jump if not equal */
5151 /*-----------------------------------------------------------------*/
5152 static void gencjne(operand *left, operand *right, iCode *ifx)
5154 symbol *tlbl = newiTempLabel(NULL);
5156 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5157 gencjneshort(left, right, lbl);
5159 pic14_emitcode("mov","a,%s",one);
5160 pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5161 pic14_emitcode("","%05d_DS_:",lbl->key+100);
5162 pic14_emitcode("clr","a");
5163 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5165 emitpLabel(lbl->key);
5166 emitpLabel(tlbl->key);
5171 /*-----------------------------------------------------------------*/
5172 /* genCmpEq - generates code for equal to */
5173 /*-----------------------------------------------------------------*/
5174 static void genCmpEq (iCode *ic, iCode *ifx)
5176 operand *left, *right, *result;
5178 symbol *false_label;
5181 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5184 DEBUGpic14_emitcode ("; ifx is non-null","");
5186 DEBUGpic14_emitcode ("; ifx is null","");
5188 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5189 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5190 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5192 DEBUGpic14_AopType(__LINE__,left,right,result);
5194 /* if literal, move literal to right */
5195 if (op_isLitLike (IC_LEFT(ic))) {
5196 operand *tmp = right ;
5202 if (ifx && !IC_TRUE(ifx))
5204 assert (IC_FALSE(ifx));
5205 false_label = IC_FALSE(ifx);
5208 size = min(AOP_SIZE(left),AOP_SIZE(right));
5209 assert(!pic14_sameRegs(AOP(result),AOP(left)));
5210 assert(!pic14_sameRegs(AOP(result),AOP(right)));
5212 /* assume left != right */
5215 for (i=0; i < AOP_SIZE(result); i++)
5217 emitpcode(POC_CLRF, popGet(AOP(result),i));
5221 if (AOP_TYPE(right) == AOP_LIT)
5223 unsigned long lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
5225 size = AOP_SIZE(left);
5226 assert(!op_isLitLike(left));
5231 mov2w(AOP(left), 0);
5232 for (i=1; i < size; i++)
5233 emitpcode(POC_IORFW,popGet(AOP(left),i));
5234 /* now Z is set iff `left == right' */
5236 if (!false_label) false_label = newiTempLabel(NULL);
5237 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5241 for (i=0; i < size; i++)
5244 emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
5245 /* now Z is cleared if `left != right' */
5247 if (!false_label) false_label = newiTempLabel(NULL);
5248 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5255 /* right is no literal */
5258 for (i=0; i < size; i++)
5260 mov2w(AOP(right),i);
5261 emitpcode(POC_XORFW,popGet(AOP(left),i));
5262 /* now Z is cleared if `left != right' */
5264 if (!false_label) false_label = newiTempLabel(NULL);
5265 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5269 /* if we reach here, left == right */
5271 if (AOP_SIZE(result) > 0)
5273 emitpcode(POC_INCF, popGet(AOP(result),0));
5276 if (ifx && IC_TRUE(ifx))
5278 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5281 if (false_label && (!ifx || IC_TRUE(ifx)))
5282 emitpLabel(false_label->key);
5284 if (ifx) ifx->generated = 1;
5286 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5287 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5288 freeAsmop(result,NULL,ic,TRUE);
5291 /*-----------------------------------------------------------------*/
5292 /* ifxForOp - returns the icode containing the ifx for operand */
5293 /*-----------------------------------------------------------------*/
5294 static iCode *ifxForOp ( operand *op, iCode *ic )
5297 /* if true symbol then needs to be assigned */
5298 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5299 if (IS_TRUE_SYMOP(op))
5302 /* if this has register type condition and
5303 the next instruction is ifx with the same operand
5304 and live to of the operand is upto the ifx only then */
5306 ic->next->op == IFX &&
5307 IC_COND(ic->next)->key == op->key &&
5308 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5312 ic->next->op == IFX &&
5313 IC_COND(ic->next)->key == op->key) {
5314 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5318 DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5320 ic->next->op == IFX)
5321 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5324 ic->next->op == IFX &&
5325 IC_COND(ic->next)->key == op->key) {
5326 DEBUGpic14_emitcode ("; "," key is okay");
5327 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5328 OP_SYMBOL(op)->liveTo,
5335 /*-----------------------------------------------------------------*/
5336 /* genAndOp - for && operation */
5337 /*-----------------------------------------------------------------*/
5338 static void genAndOp (iCode *ic)
5340 operand *left,*right, *result;
5344 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5345 /* note here that && operations that are in an
5346 if statement are taken away by backPatchLabels
5347 only those used in arthmetic operations remain */
5348 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5349 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5350 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5352 DEBUGpic14_AopType(__LINE__,left,right,result);
5354 emitpcode(POC_MOVFW,popGet(AOP(left),0));
5355 emitpcode(POC_ANDFW,popGet(AOP(right),0));
5356 emitpcode(POC_MOVWF,popGet(AOP(result),0));
5358 /* if both are bit variables */
5359 /* if (AOP_TYPE(left) == AOP_CRY && */
5360 /* AOP_TYPE(right) == AOP_CRY ) { */
5361 /* pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5362 /* pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5363 /* pic14_outBitC(result); */
5365 /* tlbl = newiTempLabel(NULL); */
5366 /* pic14_toBoolean(left); */
5367 /* pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5368 /* pic14_toBoolean(right); */
5369 /* pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5370 /* pic14_outBitAcc(result); */
5373 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5374 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5375 freeAsmop(result,NULL,ic,TRUE);
5379 /*-----------------------------------------------------------------*/
5380 /* genOrOp - for || operation */
5381 /*-----------------------------------------------------------------*/
5384 modified this code, but it doesn't appear to ever get called
5387 static void genOrOp (iCode *ic)
5389 operand *left,*right, *result;
5393 /* note here that || operations that are in an
5394 if statement are taken away by backPatchLabels
5395 only those used in arthmetic operations remain */
5397 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5398 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5399 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5400 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5402 DEBUGpic14_AopType(__LINE__,left,right,result);
5404 for (i=0; i < AOP_SIZE(result); i++)
5406 emitpcode(POC_CLRF, popGet(AOP(result), i));
5409 tlbl = newiTempLabel(NULL);
5410 pic14_toBoolean(left);
5412 emitpcode(POC_GOTO, popGetLabel(tlbl->key));
5413 pic14_toBoolean(right);
5414 emitpLabel(tlbl->key);
5415 /* here Z is clear IFF `left || right' */
5417 emitpcode(POC_INCF, popGet(AOP(result), 0));
5419 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5420 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5421 freeAsmop(result,NULL,ic,TRUE);
5424 /*-----------------------------------------------------------------*/
5425 /* isLiteralBit - test if lit == 2^n */
5426 /*-----------------------------------------------------------------*/
5427 static int isLiteralBit(unsigned long lit)
5429 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5430 0x100L,0x200L,0x400L,0x800L,
5431 0x1000L,0x2000L,0x4000L,0x8000L,
5432 0x10000L,0x20000L,0x40000L,0x80000L,
5433 0x100000L,0x200000L,0x400000L,0x800000L,
5434 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5435 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5439 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5440 for(idx = 0; idx < 32; idx++)
5446 /*-----------------------------------------------------------------*/
5447 /* continueIfTrue - */
5448 /*-----------------------------------------------------------------*/
5449 static void continueIfTrue (iCode *ic)
5452 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5454 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5458 /*-----------------------------------------------------------------*/
5460 /*-----------------------------------------------------------------*/
5461 static void jumpIfTrue (iCode *ic)
5464 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5466 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5470 /*-----------------------------------------------------------------*/
5471 /* jmpTrueOrFalse - */
5472 /*-----------------------------------------------------------------*/
5473 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5476 // ugly but optimized by peephole
5477 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5479 symbol *nlbl = newiTempLabel(NULL);
5480 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5481 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5482 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5483 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5486 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5487 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5492 /*-----------------------------------------------------------------*/
5493 /* genAnd - code for and */
5494 /*-----------------------------------------------------------------*/
5495 static void genAnd (iCode *ic, iCode *ifx)
5497 operand *left, *right, *result;
5499 unsigned long lit = 0L;
5504 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5505 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5506 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5507 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5509 resolveIfx(&rIfx,ifx);
5511 /* if left is a literal & right is not then exchange them */
5512 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5513 AOP_NEEDSACC(left)) {
5514 operand *tmp = right ;
5519 /* if result = right then exchange them */
5520 if(pic14_sameRegs(AOP(result),AOP(right))){
5521 operand *tmp = right ;
5526 /* if right is bit then exchange them */
5527 if (AOP_TYPE(right) == AOP_CRY &&
5528 AOP_TYPE(left) != AOP_CRY){
5529 operand *tmp = right ;
5533 if(AOP_TYPE(right) == AOP_LIT)
5534 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5536 size = AOP_SIZE(result);
5538 DEBUGpic14_AopType(__LINE__,left,right,result);
5541 // result = bit & yy;
5542 if (AOP_TYPE(left) == AOP_CRY){
5543 // c = bit & literal;
5544 if(AOP_TYPE(right) == AOP_LIT){
5546 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5549 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5552 if(size && (AOP_TYPE(result) == AOP_CRY)){
5553 pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5556 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5560 pic14_emitcode("clr","c");
5563 if (AOP_TYPE(right) == AOP_CRY){
5565 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5566 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5569 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5571 pic14_emitcode("rrc","a");
5572 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5578 pic14_outBitC(result);
5580 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5581 genIfxJump(ifx, "c");
5585 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5586 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5587 if((AOP_TYPE(right) == AOP_LIT) &&
5588 (AOP_TYPE(result) == AOP_CRY) &&
5589 (AOP_TYPE(left) != AOP_CRY)){
5590 int posbit = isLiteralBit(lit);
5594 //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5597 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5602 while (posbit > 7) {
5606 emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5607 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5608 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5615 symbol *tlbl = newiTempLabel(NULL);
5616 int sizel = AOP_SIZE(left);
5618 pic14_emitcode("setb","c");
5620 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5621 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5623 if((posbit = isLiteralBit(bytelit)) != 0)
5624 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5626 if(bytelit != 0x0FFL)
5627 pic14_emitcode("anl","a,%s",
5628 aopGet(AOP(right),offset,FALSE,TRUE));
5629 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5634 // bit = left & literal
5636 pic14_emitcode("clr","c");
5637 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5639 // if(left & literal)
5642 jmpTrueOrFalse(ifx, tlbl);
5646 pic14_outBitC(result);
5650 /* if left is same as result */
5651 if(pic14_sameRegs(AOP(result),AOP(left))){
5653 for(;size--; offset++,lit>>=8) {
5654 if(AOP_TYPE(right) == AOP_LIT){
5655 switch(lit & 0xff) {
5657 /* and'ing with 0 has clears the result */
5658 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5661 /* and'ing with 0xff is a nop when the result and left are the same */
5666 int p = my_powof2( (~lit) & 0xff );
5668 /* only one bit is set in the literal, so use a bcf instruction */
5669 emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5672 if(know_W != (int)(lit&0xff))
5673 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5675 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5680 if (AOP_TYPE(left) == AOP_ACC) {
5681 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5683 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5684 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5691 // left & result in different registers
5692 if(AOP_TYPE(result) == AOP_CRY){
5694 // if(size), result in bit
5695 // if(!size && ifx), conditional oper: if(left & right)
5696 symbol *tlbl = newiTempLabel(NULL);
5697 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5699 pic14_emitcode("setb","c");
5701 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5702 pic14_emitcode("anl","a,%s",
5703 aopGet(AOP(left),offset,FALSE,FALSE));
5704 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5709 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5710 pic14_outBitC(result);
5712 jmpTrueOrFalse(ifx, tlbl);
5714 for(;(size--);offset++) {
5716 // result = left & right
5717 if(AOP_TYPE(right) == AOP_LIT){
5718 int t = (lit >> (offset*8)) & 0x0FFL;
5721 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5724 if(AOP_TYPE(left) != AOP_ACC) {
5725 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5727 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5730 if(AOP_TYPE(left) == AOP_ACC) {
5731 emitpcode(POC_ANDLW, popGetLit(t));
5733 emitpcode(POC_MOVLW, popGetLit(t));
5734 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5736 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5741 if (AOP_TYPE(left) == AOP_ACC) {
5742 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5744 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5745 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5747 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5753 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5754 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5755 freeAsmop(result,NULL,ic,TRUE);
5758 /*-----------------------------------------------------------------*/
5759 /* genOr - code for or */
5760 /*-----------------------------------------------------------------*/
5761 static void genOr (iCode *ic, iCode *ifx)
5763 operand *left, *right, *result;
5765 unsigned long lit = 0L;
5768 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5770 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5771 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5772 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5774 DEBUGpic14_AopType(__LINE__,left,right,result);
5776 /* if left is a literal & right is not then exchange them */
5777 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5778 AOP_NEEDSACC(left)) {
5779 operand *tmp = right ;
5784 /* if result = right then exchange them */
5785 if(pic14_sameRegs(AOP(result),AOP(right))){
5786 operand *tmp = right ;
5791 /* if right is bit then exchange them */
5792 if (AOP_TYPE(right) == AOP_CRY &&
5793 AOP_TYPE(left) != AOP_CRY){
5794 operand *tmp = right ;
5799 DEBUGpic14_AopType(__LINE__,left,right,result);
5801 if(AOP_TYPE(right) == AOP_LIT)
5802 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5804 size = AOP_SIZE(result);
5808 if (AOP_TYPE(left) == AOP_CRY){
5809 if(AOP_TYPE(right) == AOP_LIT){
5810 // c = bit & literal;
5812 // lit != 0 => result = 1
5813 if(AOP_TYPE(result) == AOP_CRY){
5815 emitpcode(POC_BSF, popGet(AOP(result),0));
5816 //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5817 // AOP(result)->aopu.aop_dir,
5818 // AOP(result)->aopu.aop_dir);
5820 continueIfTrue(ifx);
5824 // lit == 0 => result = left
5825 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5827 pic14_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5830 if (AOP_TYPE(right) == AOP_CRY){
5831 if(pic14_sameRegs(AOP(result),AOP(left))){
5833 emitpcode(POC_BCF, popGet(AOP(result),0));
5834 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5835 emitpcode(POC_BSF, popGet(AOP(result),0));
5837 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5838 AOP(result)->aopu.aop_dir,
5839 AOP(result)->aopu.aop_dir);
5840 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5841 AOP(right)->aopu.aop_dir,
5842 AOP(right)->aopu.aop_dir);
5843 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5844 AOP(result)->aopu.aop_dir,
5845 AOP(result)->aopu.aop_dir);
5847 if( AOP_TYPE(result) == AOP_ACC) {
5848 emitpcode(POC_MOVLW, popGetLit(0));
5849 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5850 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5851 emitpcode(POC_MOVLW, popGetLit(1));
5855 emitpcode(POC_BCF, popGet(AOP(result),0));
5856 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5857 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5858 emitpcode(POC_BSF, popGet(AOP(result),0));
5860 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5861 AOP(result)->aopu.aop_dir,
5862 AOP(result)->aopu.aop_dir);
5863 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5864 AOP(right)->aopu.aop_dir,
5865 AOP(right)->aopu.aop_dir);
5866 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5867 AOP(left)->aopu.aop_dir,
5868 AOP(left)->aopu.aop_dir);
5869 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5870 AOP(result)->aopu.aop_dir,
5871 AOP(result)->aopu.aop_dir);
5876 symbol *tlbl = newiTempLabel(NULL);
5877 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5880 emitpcode(POC_BCF, popGet(AOP(result),0));
5881 if( AOP_TYPE(right) == AOP_ACC) {
5882 emitpcode(POC_IORLW, popGetLit(0));
5884 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5885 emitpcode(POC_BSF, popGet(AOP(result),0));
5890 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5891 pic14_emitcode(";XXX setb","c");
5892 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5893 AOP(left)->aopu.aop_dir,tlbl->key+100);
5894 pic14_toBoolean(right);
5895 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5896 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5897 jmpTrueOrFalse(ifx, tlbl);
5901 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5908 pic14_outBitC(result);
5910 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5911 genIfxJump(ifx, "c");
5915 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5916 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5917 if((AOP_TYPE(right) == AOP_LIT) &&
5918 (AOP_TYPE(result) == AOP_CRY) &&
5919 (AOP_TYPE(left) != AOP_CRY)){
5921 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5924 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5926 continueIfTrue(ifx);
5929 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5930 // lit = 0, result = boolean(left)
5932 pic14_emitcode(";XXX setb","c");
5933 pic14_toBoolean(right);
5935 symbol *tlbl = newiTempLabel(NULL);
5936 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5938 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5940 genIfxJump (ifx,"a");
5944 pic14_outBitC(result);
5948 /* if left is same as result */
5949 if(pic14_sameRegs(AOP(result),AOP(left))){
5951 for(;size--; offset++,lit>>=8) {
5952 if(AOP_TYPE(right) == AOP_LIT){
5953 if((lit & 0xff) == 0)
5954 /* or'ing with 0 has no effect */
5957 int p = my_powof2(lit & 0xff);
5959 /* only one bit is set in the literal, so use a bsf instruction */
5961 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5963 if(know_W != (int)(lit & 0xff))
5964 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5965 know_W = lit & 0xff;
5966 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5971 if (AOP_TYPE(left) == AOP_ACC) {
5972 emitpcode(POC_IORFW, popGet(AOP(right),offset));
5973 pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5975 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
5976 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5978 pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5979 pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5985 // left & result in different registers
5986 if(AOP_TYPE(result) == AOP_CRY){
5988 // if(size), result in bit
5989 // if(!size && ifx), conditional oper: if(left | right)
5990 symbol *tlbl = newiTempLabel(NULL);
5991 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5992 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5996 pic14_emitcode(";XXX setb","c");
5998 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5999 pic14_emitcode(";XXX orl","a,%s",
6000 aopGet(AOP(left),offset,FALSE,FALSE));
6001 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6006 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6007 pic14_outBitC(result);
6009 jmpTrueOrFalse(ifx, tlbl);
6010 } else for(;(size--);offset++){
6012 // result = left | right
6013 if(AOP_TYPE(right) == AOP_LIT){
6014 int t = (lit >> (offset*8)) & 0x0FFL;
6017 if (AOP_TYPE(left) != AOP_ACC) {
6018 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
6020 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6024 if (AOP_TYPE(left) == AOP_ACC) {
6025 emitpcode(POC_IORLW, popGetLit(t));
6027 emitpcode(POC_MOVLW, popGetLit(t));
6028 emitpcode(POC_IORFW, popGet(AOP(left),offset));
6030 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6035 // faster than result <- left, anl result,right
6036 // and better if result is SFR
6037 if (AOP_TYPE(left) == AOP_ACC) {
6038 emitpcode(POC_IORFW,popGet(AOP(right),offset));
6040 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6041 emitpcode(POC_IORFW,popGet(AOP(left),offset));
6043 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6048 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6049 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6050 freeAsmop(result,NULL,ic,TRUE);
6053 /*-----------------------------------------------------------------*/
6054 /* genXor - code for xclusive or */
6055 /*-----------------------------------------------------------------*/
6056 static void genXor (iCode *ic, iCode *ifx)
6058 operand *left, *right, *result;
6060 unsigned long lit = 0L;
6063 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6065 aopOp((left = IC_LEFT(ic)),ic,FALSE);
6066 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6067 aopOp((result=IC_RESULT(ic)),ic,TRUE);
6069 /* if left is a literal & right is not ||
6070 if left needs acc & right does not */
6071 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6072 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6073 operand *tmp = right ;
6078 /* if result = right then exchange them */
6079 if(pic14_sameRegs(AOP(result),AOP(right))){
6080 operand *tmp = right ;
6085 /* if right is bit then exchange them */
6086 if (AOP_TYPE(right) == AOP_CRY &&
6087 AOP_TYPE(left) != AOP_CRY){
6088 operand *tmp = right ;
6092 if(AOP_TYPE(right) == AOP_LIT)
6093 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6095 size = AOP_SIZE(result);
6099 if (AOP_TYPE(left) == AOP_CRY){
6100 if(AOP_TYPE(right) == AOP_LIT){
6101 // c = bit & literal;
6103 // lit>>1 != 0 => result = 1
6104 if(AOP_TYPE(result) == AOP_CRY){
6106 {emitpcode(POC_BSF, popGet(AOP(result),offset));
6107 pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6109 continueIfTrue(ifx);
6112 pic14_emitcode("setb","c");
6116 // lit == 0, result = left
6117 if(size && pic14_sameRegs(AOP(result),AOP(left)))
6119 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6121 // lit == 1, result = not(left)
6122 if(size && pic14_sameRegs(AOP(result),AOP(left))){
6123 emitpcode(POC_MOVLW, popGet(AOP(result),offset));
6124 emitpcode(POC_XORWF, popGet(AOP(result),offset));
6125 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6128 assert ( !"incomplete genXor" );
6129 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6130 pic14_emitcode("cpl","c");
6137 symbol *tlbl = newiTempLabel(NULL);
6138 if (AOP_TYPE(right) == AOP_CRY){
6140 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6143 int sizer = AOP_SIZE(right);
6145 // if val>>1 != 0, result = 1
6146 pic14_emitcode("setb","c");
6148 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6150 // test the msb of the lsb
6151 pic14_emitcode("anl","a,#0xfe");
6152 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6156 pic14_emitcode("rrc","a");
6158 pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6159 pic14_emitcode("cpl","c");
6160 pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6165 pic14_outBitC(result);
6167 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6168 genIfxJump(ifx, "c");
6172 if(pic14_sameRegs(AOP(result),AOP(left))){
6173 /* if left is same as result */
6174 for(;size--; offset++) {
6175 if(AOP_TYPE(right) == AOP_LIT){
6176 int t = (lit >> (offset*8)) & 0x0FFL;
6180 if (IS_AOP_PREG(left)) {
6181 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6182 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6183 aopPut(AOP(result),"a",offset);
6185 emitpcode(POC_MOVLW, popGetLit(t));
6186 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6187 pic14_emitcode("xrl","%s,%s",
6188 aopGet(AOP(left),offset,FALSE,TRUE),
6189 aopGet(AOP(right),offset,FALSE,FALSE));
6192 if (AOP_TYPE(left) == AOP_ACC)
6193 pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6195 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6196 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6198 if (IS_AOP_PREG(left)) {
6199 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6200 aopPut(AOP(result),"a",offset);
6202 pic14_emitcode("xrl","%s,a",
6203 aopGet(AOP(left),offset,FALSE,TRUE));
6209 // left & result in different registers
6210 if(AOP_TYPE(result) == AOP_CRY){
6212 // if(size), result in bit
6213 // if(!size && ifx), conditional oper: if(left ^ right)
6214 symbol *tlbl = newiTempLabel(NULL);
6215 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6217 pic14_emitcode("setb","c");
6219 if((AOP_TYPE(right) == AOP_LIT) &&
6220 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6221 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6223 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6224 pic14_emitcode("xrl","a,%s",
6225 aopGet(AOP(left),offset,FALSE,FALSE));
6227 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6232 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6233 pic14_outBitC(result);
6235 jmpTrueOrFalse(ifx, tlbl);
6236 } else for(;(size--);offset++){
6238 // result = left & right
6239 if(AOP_TYPE(right) == AOP_LIT){
6240 int t = (lit >> (offset*8)) & 0x0FFL;
6243 if (AOP_TYPE(left) != AOP_ACC) {
6244 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6246 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6247 pic14_emitcode("movf","%s,w",
6248 aopGet(AOP(left),offset,FALSE,FALSE));
6249 pic14_emitcode("movwf","%s",
6250 aopGet(AOP(result),offset,FALSE,FALSE));
6253 if (AOP_TYPE(left) == AOP_ACC) {
6254 emitpcode(POC_XORLW, popGetLit(t));
6256 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6258 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6261 if (AOP_TYPE(left) == AOP_ACC) {
6262 emitpcode(POC_XORLW, popGetLit(t));
6264 emitpcode(POC_MOVLW, popGetLit(t));
6265 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6267 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6268 pic14_emitcode("movlw","0x%x",t);
6269 pic14_emitcode("xorwf","%s,w",
6270 aopGet(AOP(left),offset,FALSE,FALSE));
6271 pic14_emitcode("movwf","%s",
6272 aopGet(AOP(result),offset,FALSE,FALSE));
6278 // faster than result <- left, anl result,right
6279 // and better if result is SFR
6280 if (AOP_TYPE(left) == AOP_ACC) {
6281 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6283 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6284 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6286 if ( AOP_TYPE(result) != AOP_ACC){
6287 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6293 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6294 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6295 freeAsmop(result,NULL,ic,TRUE);
6298 /*-----------------------------------------------------------------*/
6299 /* genInline - write the inline code out */
6300 /*-----------------------------------------------------------------*/
6301 static void genInline (iCode *ic)
6303 char *buffer, *bp, *bp1;
6306 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6308 _G.inLine += (!options.asmpeep);
6310 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6311 strcpy(buffer,IC_INLINE(ic));
6313 /* emit each line as a code */
6319 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6327 /* print label, use this special format with NULL directive
6328 * to denote that the argument should not be indented with tab */
6329 addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6336 if ((bp1 != bp) && *bp1)
6337 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6341 _G.inLine -= (!options.asmpeep);
6344 /*-----------------------------------------------------------------*/
6345 /* genRRC - rotate right with carry */
6346 /*-----------------------------------------------------------------*/
6347 static void genRRC (iCode *ic)
6349 operand *left , *result ;
6350 int size, offset = 0, same;
6353 /* rotate right with carry */
6355 result=IC_RESULT(ic);
6356 aopOp (left,ic,FALSE);
6357 aopOp (result,ic,FALSE);
6359 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6361 same = pic14_sameRegs(AOP(result),AOP(left));
6363 size = AOP_SIZE(result);
6365 /* get the lsb and put it into the carry */
6366 emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6373 emitpcode(POC_RRF, popGet(AOP(left),offset));
6375 emitpcode(POC_RRFW, popGet(AOP(left),offset));
6376 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6382 freeAsmop(left,NULL,ic,TRUE);
6383 freeAsmop(result,NULL,ic,TRUE);
6386 /*-----------------------------------------------------------------*/
6387 /* genRLC - generate code for rotate left with carry */
6388 /*-----------------------------------------------------------------*/
6389 static void genRLC (iCode *ic)
6391 operand *left , *result ;
6392 int size, offset = 0;
6396 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6397 /* rotate right with carry */
6399 result=IC_RESULT(ic);
6400 aopOp (left,ic,FALSE);
6401 aopOp (result,ic,FALSE);
6403 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6405 same = pic14_sameRegs(AOP(result),AOP(left));
6407 /* move it to the result */
6408 size = AOP_SIZE(result);
6410 /* get the msb and put it into the carry */
6411 emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6418 emitpcode(POC_RLF, popGet(AOP(left),offset));
6420 emitpcode(POC_RLFW, popGet(AOP(left),offset));
6421 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6428 freeAsmop(left,NULL,ic,TRUE);
6429 freeAsmop(result,NULL,ic,TRUE);
6432 /*-----------------------------------------------------------------*/
6433 /* genGetHbit - generates code get highest order bit */
6434 /*-----------------------------------------------------------------*/
6435 static void genGetHbit (iCode *ic)
6437 operand *left, *result;
6439 result=IC_RESULT(ic);
6440 aopOp (left,ic,FALSE);
6441 aopOp (result,ic,FALSE);
6444 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6445 /* get the highest order byte into a */
6446 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6447 if(AOP_TYPE(result) == AOP_CRY){
6448 pic14_emitcode("rlc","a");
6449 pic14_outBitC(result);
6452 pic14_emitcode("rl","a");
6453 pic14_emitcode("anl","a,#0x01");
6454 pic14_outAcc(result);
6458 freeAsmop(left,NULL,ic,TRUE);
6459 freeAsmop(result,NULL,ic,TRUE);
6462 /*-----------------------------------------------------------------*/
6463 /* AccLsh - shift left accumulator by known count */
6464 /* MARK: pic14 always rotates through CARRY! */
6465 /*-----------------------------------------------------------------*/
6466 static void AccLsh (pCodeOp *pcop,int shCount)
6469 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6470 shCount &= 0x0007; // shCount : 0..7
6477 emitpcode(POC_RLF,pcop);
6481 emitpcode(POC_RLF,pcop);
6482 emitpcode(POC_RLF,pcop);
6485 emitpcode(POC_RLF,pcop);
6486 emitpcode(POC_RLF,pcop);
6487 emitpcode(POC_RLF,pcop);
6490 emitpcode(POC_SWAPF,pcop);
6493 emitpcode(POC_SWAPF,pcop);
6494 emitpcode(POC_RLF,pcop);
6497 emitpcode(POC_SWAPF,pcop);
6498 emitpcode(POC_RLF,pcop);
6499 emitpcode(POC_RLF,pcop);
6502 emitpcode(POC_RRFW,pcop);
6503 emitpcode(POC_RRF,pcop);
6506 /* clear invalid bits */
6507 emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6508 emitpcode(POC_ANDWF, pcop);
6511 /*-----------------------------------------------------------------*/
6512 /* AccRsh - shift right accumulator by known count */
6513 /* MARK: pic14 always rotates through CARRY! */
6514 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6515 /* 1: mask out invalid bits (zero-extend) */
6516 /* 2: sign-extend result (pretty slow) */
6517 /*-----------------------------------------------------------------*/
6518 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6521 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6522 shCount &= 0x0007; // shCount : 0..7
6528 /* load sign if needed */
6529 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6530 else if (mask_mode == 1) emitCLRC;
6531 emitpcode(POC_RRF,pcop);
6535 /* load sign if needed */
6536 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6537 emitpcode(POC_RRF,pcop);
6538 /* load sign if needed */
6539 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6540 emitpcode(POC_RRF,pcop);
6541 if (mask_mode == 2) return;
6544 /* load sign if needed */
6545 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6546 emitpcode(POC_RRF,pcop);
6547 /* load sign if needed */
6548 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6549 emitpcode(POC_RRF,pcop);
6550 /* load sign if needed */
6551 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6552 emitpcode(POC_RRF,pcop);
6553 if (mask_mode == 2) return;
6556 emitpcode(POC_SWAPF,pcop);
6559 emitpcode(POC_SWAPF,pcop);
6560 emitpcode(POC_RRF,pcop);
6563 emitpcode(POC_SWAPF,pcop);
6564 emitpcode(POC_RRF,pcop);
6565 emitpcode(POC_RRF,pcop);
6571 emitpcode(POC_RLFW,pcop);
6572 emitpcode(POC_CLRF,pcop);
6574 emitpcode(POC_COMF,pcop);
6577 emitpcode(POC_RLFW,pcop);
6578 emitpcode(POC_RLF,pcop);
6585 /* leave invalid bits undefined */
6589 /* clear invalid bits -- zero-extend */
6590 emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6591 emitpcode(POC_ANDWF, pcop);
6593 if (mask_mode == 2) {
6595 emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6596 emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6597 emitpcode(POC_IORWF, pcop);
6602 /*-----------------------------------------------------------------*/
6603 /* AccSRsh - signed right shift accumulator by known count */
6604 /*-----------------------------------------------------------------*/
6605 static void AccSRsh (int shCount)
6608 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6611 pic14_emitcode("mov","c,acc.7");
6612 pic14_emitcode("rrc","a");
6613 } else if(shCount == 2){
6614 pic14_emitcode("mov","c,acc.7");
6615 pic14_emitcode("rrc","a");
6616 pic14_emitcode("mov","c,acc.7");
6617 pic14_emitcode("rrc","a");
6619 tlbl = newiTempLabel(NULL);
6620 /* rotate right accumulator */
6621 AccRol(8 - shCount);
6622 /* and kill the higher order bits */
6623 pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6624 pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6625 pic14_emitcode("orl","a,#0x%02x",
6626 (unsigned char)~SRMask[shCount]);
6627 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6632 /*-----------------------------------------------------------------*/
6633 /* shiftR1Left2Result - shift right one byte from left to result */
6634 /*-----------------------------------------------------------------*/
6635 static void shiftR1Left2ResultSigned (operand *left, int offl,
6636 operand *result, int offr,
6642 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6644 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6648 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6650 emitpcode(POC_RRF, popGet(AOP(result),offr));
6652 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6653 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6659 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6661 emitpcode(POC_RRF, popGet(AOP(result),offr));
6663 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6664 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6666 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6667 emitpcode(POC_RRF, popGet(AOP(result),offr));
6673 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6675 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6676 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6679 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6680 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6681 emitpcode(POC_ANDLW, popGetLit(0x1f));
6683 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6684 emitpcode(POC_IORLW, popGetLit(0xe0));
6686 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6690 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6691 emitpcode(POC_ANDLW, popGetLit(0x0f));
6692 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6693 emitpcode(POC_IORLW, popGetLit(0xf0));
6694 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6698 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6700 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6701 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6703 emitpcode(POC_RRFW, popGet(AOP(result),offr));
6704 emitpcode(POC_ANDLW, popGetLit(0x07));
6705 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6706 emitpcode(POC_IORLW, popGetLit(0xf8));
6707 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6712 emitpcode(POC_MOVLW, popGetLit(0x00));
6713 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6714 emitpcode(POC_MOVLW, popGetLit(0xfe));
6715 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6716 emitpcode(POC_IORLW, popGetLit(0x01));
6717 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6719 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6720 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6721 emitpcode(POC_DECF, popGet(AOP(result),offr));
6722 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6723 emitpcode(POC_BCF, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6729 emitpcode(POC_MOVLW, popGetLit(0x00));
6730 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6731 emitpcode(POC_MOVLW, popGetLit(0xff));
6732 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6734 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6735 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6736 emitpcode(POC_DECF, popGet(AOP(result),offr));
6744 /*-----------------------------------------------------------------*/
6745 /* shiftR1Left2Result - shift right one byte from left to result */
6746 /*-----------------------------------------------------------------*/
6747 static void shiftR1Left2Result (operand *left, int offl,
6748 operand *result, int offr,
6749 int shCount, int sign)
6754 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6756 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6758 /* Copy the msb into the carry if signed. */
6760 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6770 emitpcode(POC_RRF, popGet(AOP(result),offr));
6772 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6773 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6779 emitpcode(POC_RRF, popGet(AOP(result),offr));
6781 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6782 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6785 emitpcode(POC_RRF, popGet(AOP(result),offr));
6790 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6792 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6793 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6796 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6797 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6798 emitpcode(POC_ANDLW, popGetLit(0x1f));
6799 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6803 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6804 emitpcode(POC_ANDLW, popGetLit(0x0f));
6805 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6809 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6810 emitpcode(POC_ANDLW, popGetLit(0x0f));
6811 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6813 emitpcode(POC_RRF, popGet(AOP(result),offr));
6818 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6819 emitpcode(POC_ANDLW, popGetLit(0x80));
6820 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6821 emitpcode(POC_RLF, popGet(AOP(result),offr));
6822 emitpcode(POC_RLF, popGet(AOP(result),offr));
6827 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6828 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6829 emitpcode(POC_RLF, popGet(AOP(result),offr));
6838 /*-----------------------------------------------------------------*/
6839 /* shiftL1Left2Result - shift left one byte from left to result */
6840 /*-----------------------------------------------------------------*/
6841 static void shiftL1Left2Result (operand *left, int offl,
6842 operand *result, int offr, int shCount)
6848 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6850 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6851 DEBUGpic14_emitcode ("; ***","same = %d",same);
6852 // l = aopGet(AOP(left),offl,FALSE,FALSE);
6854 /* shift left accumulator */
6855 //AccLsh(shCount); // don't comment out just yet...
6856 // aopPut(AOP(result),"a",offr);
6860 /* Shift left 1 bit position */
6861 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6863 emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6865 emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6866 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6870 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6871 emitpcode(POC_ANDLW,popGetLit(0x7e));
6872 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6873 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6876 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6877 emitpcode(POC_ANDLW,popGetLit(0x3e));
6878 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6879 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6880 emitpcode(POC_RLF, popGet(AOP(result),offr));
6883 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6884 emitpcode(POC_ANDLW, popGetLit(0xf0));
6885 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6888 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6889 emitpcode(POC_ANDLW, popGetLit(0xf0));
6890 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6891 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6894 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6895 emitpcode(POC_ANDLW, popGetLit(0x30));
6896 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6897 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6898 emitpcode(POC_RLF, popGet(AOP(result),offr));
6901 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6902 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6903 emitpcode(POC_RRF, popGet(AOP(result),offr));
6907 DEBUGpic14_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6913 /*-----------------------------------------------------------------*/
6914 /* movLeft2Result - move byte from left to result */
6915 /*-----------------------------------------------------------------*/
6916 static void movLeft2Result (operand *left, int offl,
6917 operand *result, int offr)
6921 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6922 if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6923 l = aopGet(AOP(left),offl,FALSE,FALSE);
6925 if (*l == '@' && (IS_AOP_PREG(result))) {
6926 pic14_emitcode("mov","a,%s",l);
6927 aopPut(AOP(result),"a",offr);
6929 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6930 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6935 /*-----------------------------------------------------------------*/
6936 /* shiftLeft_Left2ResultLit - shift left by known count */
6937 /*-----------------------------------------------------------------*/
6939 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6941 int size, same, offr, i;
6943 size = AOP_SIZE(left);
6944 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6946 same = pic14_sameRegs (AOP(left), AOP(result));
6949 shCount = shCount & 0x07;
6955 case 0: /* takes 0 or 2N cycles (for offr==0) */
6956 if (!same || offr) {
6957 for (i=size-1; i >= 0; i--)
6958 movLeft2Result (left, i, result, offr + i);
6962 case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6964 shiftLeft_Left2ResultLit (left, result, 8 * offr);
6965 shiftLeft_Left2ResultLit (result, result, shCount);
6966 return; /* prevent clearing result again */
6969 for (i=0; i < size; i++) {
6970 if (same && !offr) {
6971 emitpcode (POC_RLF, popGet (AOP(left), i));
6973 emitpcode (POC_RLFW, popGet (AOP(left), i));
6974 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6980 case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
6981 /* works in-place/with offr as well */
6982 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
6983 emitpcode (POC_ANDLW, popGetLit (0xF0));
6984 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
6986 for (i = size - 2; i >= 0; i--)
6988 emitpcode (POC_SWAPFW, popGet (AOP(left), i));
6989 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6990 emitpcode (POC_ANDLW, popGetLit (0x0F));
6991 emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
6992 emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
6996 case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
6997 /* works in-place/with offr as well */
6998 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
6999 for (i = size-2; i >= 0; i--) {
7000 emitpcode (POC_RRFW, popGet (AOP(left), i));
7001 emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
7003 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7004 emitpcode (POC_RRF, popGet (AOP(result), offr));
7008 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
7009 shiftLeft_Left2ResultLit (result, result, 1);
7010 return; /* prevent clearing result again */
7016 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7020 /*-----------------------------------------------------------------*/
7021 /* shiftRight_Left2ResultLit - shift right by known count */
7022 /*-----------------------------------------------------------------*/
7024 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
7026 int size, same, offr, i;
7028 size = AOP_SIZE(left);
7029 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7031 same = pic14_sameRegs (AOP(left), AOP(result));
7034 shCount = shCount & 0x07;
7042 case 0: /* takes 0 or 2N cycles (for offr==0) */
7043 if (!same || offr) {
7044 for (i=0; i < size; i++)
7045 movLeft2Result (left, i + offr, result, i);
7049 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7050 emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7052 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7053 shiftRight_Left2ResultLit (result, result, shCount, sign);
7054 return; /* prevent sign-extending result again */
7058 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7061 for (i = size-1; i >= 0; i--) {
7062 if (same && !offr) {
7063 emitpcode (POC_RRF, popGet (AOP(left), i));
7065 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7066 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7072 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7073 /* works in-place/with offr as well */
7074 emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7075 emitpcode (POC_ANDLW, popGetLit (0x0F));
7076 emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7078 for (i = 1; i < size; i++)
7080 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7081 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7082 emitpcode (POC_ANDLW, popGetLit (0xF0));
7083 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7084 emitpcode (POC_XORWF, popGet (AOP(result), i));
7089 emitpcode (POC_MOVLW, popGetLit (0xF0));
7090 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7091 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7095 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7096 /* works in-place/with offr as well */
7097 emitpcode (POC_RLFW, popGet (AOP(left), offr));
7098 for (i = 0; i < size-1; i++) {
7099 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7100 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7102 emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7104 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7107 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7112 shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7113 shiftRight_Left2ResultLit (result, result, 1, sign);
7114 return; /* prevent sign extending result again */
7119 addSign (result, size, sign);
7123 /*-----------------------------------------------------------------*/
7124 /* shiftL2Left2Result - shift left two bytes from left to result */
7125 /*-----------------------------------------------------------------*/
7126 static void shiftL2Left2Result (operand *left, int offl,
7127 operand *result, int offr, int shCount)
7131 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7133 if(pic14_sameRegs(AOP(result), AOP(left))) {
7141 emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7142 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7143 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7147 emitpcode(POC_RLF, popGet(AOP(result),offr));
7148 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7154 emitpcode(POC_MOVLW, popGetLit(0x0f));
7155 emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7156 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7157 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7158 emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7159 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7160 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7162 emitpcode(POC_RLF, popGet(AOP(result),offr));
7163 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7167 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7168 emitpcode(POC_RRF, popGet(AOP(result),offr));
7169 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7170 emitpcode(POC_RRF, popGet(AOP(result),offr));
7171 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7172 emitpcode(POC_ANDLW,popGetLit(0xc0));
7173 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7174 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7175 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7176 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7179 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7180 emitpcode(POC_RRFW, popGet(AOP(result),offr));
7181 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7182 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7183 emitpcode(POC_RRF, popGet(AOP(result),offr));
7193 /* note, use a mov/add for the shift since the mov has a
7194 chance of getting optimized out */
7195 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7196 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7197 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7198 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7199 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7203 emitpcode(POC_RLF, popGet(AOP(result),offr));
7204 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7210 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7211 emitpcode(POC_ANDLW, popGetLit(0xF0));
7212 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7213 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7214 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7215 emitpcode(POC_ANDLW, popGetLit(0xF0));
7216 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7217 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7221 emitpcode(POC_RLF, popGet(AOP(result),offr));
7222 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7226 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7227 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7228 emitpcode(POC_RRFW, popGet(AOP(result),offl));
7229 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7231 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7232 emitpcode(POC_RRF, popGet(AOP(result),offr));
7233 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7234 emitpcode(POC_ANDLW,popGetLit(0xc0));
7235 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7236 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7237 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7238 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7241 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7242 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7243 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7244 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7245 emitpcode(POC_RRF, popGet(AOP(result),offr));
7251 /*-----------------------------------------------------------------*/
7252 /* shiftR2Left2Result - shift right two bytes from left to result */
7253 /*-----------------------------------------------------------------*/
7254 static void shiftR2Left2Result (operand *left, int offl,
7255 operand *result, int offr,
7256 int shCount, int sign)
7261 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7262 same = pic14_sameRegs(AOP(result), AOP(left));
7264 if(same && ((offl + MSB16) == offr)){
7266 /* don't crash result[offr] */
7267 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7268 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7271 movLeft2Result(left,offl, result, offr);
7272 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7275 /* a:x >> shCount (x = lsb(result))*/
7278 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7280 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7289 emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7294 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7295 emitpcode(POC_RRF,popGet(AOP(result),offr));
7297 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7298 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7299 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7300 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7305 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7308 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7309 emitpcode(POC_RRF,popGet(AOP(result),offr));
7316 emitpcode(POC_MOVLW, popGetLit(0xf0));
7317 emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7318 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7320 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7321 emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7322 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7323 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7325 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7326 emitpcode(POC_ANDLW, popGetLit(0x0f));
7327 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7329 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7330 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7331 emitpcode(POC_ANDLW, popGetLit(0xf0));
7332 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7333 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7337 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7338 emitpcode(POC_RRF, popGet(AOP(result),offr));
7342 emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7343 emitpcode(POC_BTFSC,
7344 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7345 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7353 emitpcode(POC_RLF, popGet(AOP(result),offr));
7354 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7356 emitpcode(POC_RLF, popGet(AOP(result),offr));
7357 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7358 emitpcode(POC_RLFW, popGet(AOP(result),offr));
7359 emitpcode(POC_ANDLW,popGetLit(0x03));
7361 emitpcode(POC_BTFSC,
7362 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7363 emitpcode(POC_IORLW,popGetLit(0xfc));
7365 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7366 emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7367 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7368 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7370 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7371 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7372 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7373 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7374 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7375 emitpcode(POC_RLF, popGet(AOP(result),offr));
7376 emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7377 emitpcode(POC_ANDLW,popGetLit(0x03));
7379 emitpcode(POC_BTFSC,
7380 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7381 emitpcode(POC_IORLW,popGetLit(0xfc));
7383 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7384 //emitpcode(POC_RLF, popGet(AOP(result),offr));
7391 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7392 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7393 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7394 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7397 emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7399 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7403 /*-----------------------------------------------------------------*/
7404 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7405 /*-----------------------------------------------------------------*/
7406 static void shiftLLeftOrResult (operand *left, int offl,
7407 operand *result, int offr, int shCount)
7410 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7412 /* shift left accumulator */
7413 AccLsh(left,offl,shCount);
7414 /* or with result */
7415 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7416 assert ( !"broken (modifies left, fails for left==result))" );
7419 /*-----------------------------------------------------------------*/
7420 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7421 /*-----------------------------------------------------------------*/
7422 static void shiftRLeftOrResult (operand *left, int offl,
7423 operand *result, int offr, int shCount)
7426 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7428 /* shift right accumulator */
7429 AccRsh(left,offl,shCount);
7430 /* or with result */
7431 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7432 assert ( !"broken (modifies left, fails for left==result))" );
7435 /*-----------------------------------------------------------------*/
7436 /* genlshOne - left shift a one byte quantity by known count */
7437 /*-----------------------------------------------------------------*/
7438 static void genlshOne (operand *result, operand *left, int shCount)
7441 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7442 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7445 /*-----------------------------------------------------------------*/
7446 /* genlshTwo - left shift two bytes by known amount != 0 */
7447 /*-----------------------------------------------------------------*/
7448 static void genlshTwo (operand *result,operand *left, int shCount)
7453 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7454 size = pic14_getDataSize(result);
7456 /* if shCount >= 8 */
7462 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7464 movLeft2Result(left, LSB, result, MSB16);
7466 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7469 /* 1 <= shCount <= 7 */
7472 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7474 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7478 /*-----------------------------------------------------------------*/
7479 /* shiftLLong - shift left one long from left to result */
7480 /* offl = LSB or MSB16 */
7481 /*-----------------------------------------------------------------*/
7482 static void shiftLLong (operand *left, operand *result, int offr )
7485 int size = AOP_SIZE(result);
7488 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7489 if(size >= LSB+offr){
7490 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7492 pic14_emitcode("add","a,acc");
7493 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7494 size >= MSB16+offr && offr != LSB )
7495 pic14_emitcode("xch","a,%s",
7496 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7498 aopPut(AOP(result),"a",LSB+offr);
7501 if(size >= MSB16+offr){
7502 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7503 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7506 pic14_emitcode("rlc","a");
7507 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7508 size >= MSB24+offr && offr != LSB)
7509 pic14_emitcode("xch","a,%s",
7510 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7512 aopPut(AOP(result),"a",MSB16+offr);
7515 if(size >= MSB24+offr){
7516 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7517 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7520 pic14_emitcode("rlc","a");
7521 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7522 size >= MSB32+offr && offr != LSB )
7523 pic14_emitcode("xch","a,%s",
7524 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7526 aopPut(AOP(result),"a",MSB24+offr);
7529 if(size > MSB32+offr){
7530 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7531 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7534 pic14_emitcode("rlc","a");
7535 aopPut(AOP(result),"a",MSB32+offr);
7538 aopPut(AOP(result),zero,LSB);
7541 /*-----------------------------------------------------------------*/
7542 /* genlshFour - shift four byte by a known amount != 0 */
7543 /*-----------------------------------------------------------------*/
7544 static void genlshFour (operand *result, operand *left, int shCount)
7549 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7550 size = AOP_SIZE(result);
7552 /* if shifting more that 3 bytes */
7553 if (shCount >= 24 ) {
7556 /* lowest order of left goes to the highest
7557 order of the destination */
7558 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7560 movLeft2Result(left, LSB, result, MSB32);
7561 aopPut(AOP(result),zero,LSB);
7562 aopPut(AOP(result),zero,MSB16);
7563 aopPut(AOP(result),zero,MSB32);
7567 /* more than two bytes */
7568 else if ( shCount >= 16 ) {
7569 /* lower order two bytes goes to higher order two bytes */
7571 /* if some more remaining */
7573 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7575 movLeft2Result(left, MSB16, result, MSB32);
7576 movLeft2Result(left, LSB, result, MSB24);
7578 aopPut(AOP(result),zero,MSB16);
7579 aopPut(AOP(result),zero,LSB);
7583 /* if more than 1 byte */
7584 else if ( shCount >= 8 ) {
7585 /* lower order three bytes goes to higher order three bytes */
7589 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7591 movLeft2Result(left, LSB, result, MSB16);
7593 else{ /* size = 4 */
7595 movLeft2Result(left, MSB24, result, MSB32);
7596 movLeft2Result(left, MSB16, result, MSB24);
7597 movLeft2Result(left, LSB, result, MSB16);
7598 aopPut(AOP(result),zero,LSB);
7600 else if(shCount == 1)
7601 shiftLLong(left, result, MSB16);
7603 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7604 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7605 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7606 aopPut(AOP(result),zero,LSB);
7611 /* 1 <= shCount <= 7 */
7612 else if(shCount <= 2){
7613 shiftLLong(left, result, LSB);
7615 shiftLLong(result, result, LSB);
7617 /* 3 <= shCount <= 7, optimize */
7619 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7620 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7621 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7627 /*-----------------------------------------------------------------*/
7628 /* genLeftShiftLiteral - left shifting by known count */
7629 /*-----------------------------------------------------------------*/
7630 static void genLeftShiftLiteral (operand *left,
7635 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7639 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7640 freeAsmop(right,NULL,ic,TRUE);
7642 aopOp(left,ic,FALSE);
7643 aopOp(result,ic,FALSE);
7645 size = getSize(operandType(result));
7648 pic14_emitcode("; shift left ","result %d, left %d",size,
7652 /* I suppose that the left size >= result size */
7655 movLeft2Result(left, size, result, size);
7659 else if(shCount >= (size * 8))
7661 aopPut(AOP(result),zero,size);
7665 genlshOne (result,left,shCount);
7670 genlshTwo (result,left,shCount);
7674 genlshFour (result,left,shCount);
7678 freeAsmop(left,NULL,ic,TRUE);
7679 freeAsmop(result,NULL,ic,TRUE);
7683 /*-----------------------------------------------------------------*
7684 * genMultiAsm - repeat assembly instruction for size of register.
7685 * if endian == 1, then the high byte (i.e base address + size of
7686 * register) is used first else the low byte is used first;
7687 *-----------------------------------------------------------------*/
7688 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7694 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7707 emitpcode(poc, popGet(AOP(reg),offset));
7714 /*-----------------------------------------------------------------*/
7715 /* genLeftShift - generates code for left shifting */
7716 /*-----------------------------------------------------------------*/
7717 static void genLeftShift (iCode *ic)
7719 operand *left,*right, *result;
7721 unsigned long lit = 0L;
7723 symbol *tlbl , *tlbl1;
7727 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7729 right = IC_RIGHT(ic);
7731 result = IC_RESULT(ic);
7733 aopOp(right,ic,FALSE);
7734 aopOp(left,ic,FALSE);
7735 aopOp(result,ic,FALSE);
7738 /* if the shift count is known then do it
7739 as efficiently as possible */
7740 if (AOP_TYPE(right) == AOP_LIT) {
7741 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7745 /* shift count is unknown then we have to form
7746 a loop get the loop count in B : Note: we take
7747 only the lower order byte since shifting
7748 more that 32 bits make no sense anyway, ( the
7749 largest size of an object can be only 32 bits ) */
7751 /* this code fails for RIGHT == RESULT */
7752 assert (!pic14_sameRegs (AOP(right), AOP(result)));
7754 /* now move the left to the result if they are not the
7756 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
7757 AOP_SIZE(result) > 1) {
7759 size = AOP_SIZE(result);
7762 l = aopGet(AOP(left),offset,FALSE,TRUE);
7763 if (*l == '@' && (IS_AOP_PREG(result))) {
7765 pic14_emitcode("mov","a,%s",l);
7766 aopPut(AOP(result),"a",offset);
7768 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
7769 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7770 //aopPut(AOP(result),l,offset);
7776 if(AOP_TYPE(left) == AOP_LIT)
7777 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7779 size = AOP_SIZE(result);
7781 /* if it is only one byte then */
7783 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7784 emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7785 emitpcode(POC_ANDLW, popGetLit(0xf0));
7786 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7787 emitpcode(POC_MOVFW, popGet(AOP(left),0));
7788 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7789 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7790 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7791 emitpcode(POC_RLFW, popGet(AOP(result),0));
7792 emitpcode(POC_ANDLW, popGetLit(0xfe));
7793 emitpcode(POC_ADDFW, popGet(AOP(result),0));
7794 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7795 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7798 tlbl = newiTempLabel(NULL);
7799 if (!pic14_sameRegs(AOP(left),AOP(result))) {
7800 mov2w (AOP(left), 0);
7801 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7804 emitpcode(POC_COMFW, popGet(AOP(right),0));
7805 emitpcode(POC_RRF, popGet(AOP(result),0));
7806 emitpLabel(tlbl->key);
7807 emitpcode(POC_RLF, popGet(AOP(result),0));
7808 emitpcode(POC_ADDLW, popGetLit(1));
7810 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7815 if (pic14_sameRegs(AOP(left),AOP(result))) {
7817 tlbl = newiTempLabel(NULL);
7818 emitpcode(POC_COMFW, popGet(AOP(right),0));
7819 genMultiAsm(POC_RRF, result, size,1);
7820 emitpLabel(tlbl->key);
7821 genMultiAsm(POC_RLF, result, size,0);
7822 emitpcode(POC_ADDLW, popGetLit(1));
7824 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7828 //tlbl = newiTempLabel(NULL);
7830 //tlbl1 = newiTempLabel(NULL);
7832 //reAdjustPreg(AOP(result));
7834 //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7835 //pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7836 //l = aopGet(AOP(result),offset,FALSE,FALSE);
7838 //pic14_emitcode("add","a,acc");
7839 //aopPut(AOP(result),"a",offset++);
7841 // l = aopGet(AOP(result),offset,FALSE,FALSE);
7843 // pic14_emitcode("rlc","a");
7844 // aopPut(AOP(result),"a",offset++);
7846 //reAdjustPreg(AOP(result));
7848 //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7849 //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7852 tlbl = newiTempLabel(NULL);
7853 tlbl1= newiTempLabel(NULL);
7855 size = AOP_SIZE(result);
7858 pctemp = popGetTempReg(); /* grab a temporary working register. */
7860 emitpcode(POC_MOVFW, popGet(AOP(right),0));
7862 /* offset should be 0, 1 or 3 */
7863 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7865 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
7867 emitpcode(POC_MOVWF, pctemp);
7870 emitpLabel(tlbl->key);
7873 emitpcode(POC_RLF, popGet(AOP(result),0));
7875 emitpcode(POC_RLF, popGet(AOP(result),offset++));
7877 emitpcode(POC_DECFSZ, pctemp);
7878 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7879 emitpLabel(tlbl1->key);
7881 popReleaseTempReg(pctemp);
7885 freeAsmop (right,NULL,ic,TRUE);
7886 freeAsmop(left,NULL,ic,TRUE);
7887 freeAsmop(result,NULL,ic,TRUE);
7892 /*-----------------------------------------------------------------*/
7893 /* genrshOne - right shift a one byte quantity by known count */
7894 /*-----------------------------------------------------------------*/
7895 static void genrshOne (operand *result, operand *left,
7896 int shCount, int sign)
7899 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7900 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7903 /*-----------------------------------------------------------------*/
7904 /* genrshTwo - right shift two bytes by known amount != 0 */
7905 /*-----------------------------------------------------------------*/
7906 static void genrshTwo (operand *result,operand *left,
7907 int shCount, int sign)
7910 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7911 /* if shCount >= 8 */
7915 shiftR1Left2Result(left, MSB16, result, LSB,
7918 movLeft2Result(left, MSB16, result, LSB);
7920 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7923 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7924 emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7928 /* 1 <= shCount <= 7 */
7930 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
7933 /*-----------------------------------------------------------------*/
7934 /* shiftRLong - shift right one long from left to result */
7935 /* offl = LSB or MSB16 */
7936 /*-----------------------------------------------------------------*/
7937 static void shiftRLong (operand *left, int offl,
7938 operand *result, int sign)
7943 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7945 size = AOP_SIZE(left);
7946 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7949 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7953 assert (offl >= 0 && offl < size);
7955 same = pic14_sameRegs (AOP(left), AOP(result));
7957 /* perform the shift */
7960 if (same && !offl) {
7961 emitpcode (POC_RRF, popGet (AOP(result), size));
7963 emitpcode (POC_RRFW, popGet (AOP(left), size));
7964 emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7968 addSign (result, AOP_SIZE(left) - offl, sign);
7971 /*-----------------------------------------------------------------*/
7972 /* genrshFour - shift four byte by a known amount != 0 */
7973 /*-----------------------------------------------------------------*/
7974 static void genrshFour (operand *result, operand *left,
7975 int shCount, int sign)
7978 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7979 /* if shifting more that 3 bytes */
7980 if(shCount >= 24 ) {
7983 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7985 movLeft2Result(left, MSB32, result, LSB);
7987 addSign(result, MSB16, sign);
7989 else if(shCount >= 16){
7992 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7994 movLeft2Result(left, MSB24, result, LSB);
7995 movLeft2Result(left, MSB32, result, MSB16);
7997 addSign(result, MSB24, sign);
7999 else if(shCount >= 8){
8002 shiftRLong(left, MSB16, result, sign);
8003 else if(shCount == 0){
8004 movLeft2Result(left, MSB16, result, LSB);
8005 movLeft2Result(left, MSB24, result, MSB16);
8006 movLeft2Result(left, MSB32, result, MSB24);
8007 addSign(result, MSB32, sign);
8010 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8011 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8012 /* the last shift is signed */
8013 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8014 addSign(result, MSB32, sign);
8017 else{ /* 1 <= shCount <= 7 */
8019 shiftRLong(left, LSB, result, sign);
8021 shiftRLong(result, LSB, result, sign);
8024 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8025 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8026 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8031 /*-----------------------------------------------------------------*/
8032 /* genRightShiftLiteral - right shifting by known count */
8033 /*-----------------------------------------------------------------*/
8034 static void genRightShiftLiteral (operand *left,
8040 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8044 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8045 freeAsmop(right,NULL,ic,TRUE);
8047 aopOp(left,ic,FALSE);
8048 aopOp(result,ic,FALSE);
8051 pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8055 lsize = pic14_getDataSize(left);
8056 res_size = pic14_getDataSize(result);
8057 /* test the LEFT size !!! */
8059 /* I suppose that the left size >= result size */
8062 movLeft2Result(left, res_size, result, res_size);
8065 else if(shCount >= (lsize * 8)){
8068 emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8070 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8071 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8076 emitpcode(POC_MOVLW, popGetLit(0));
8077 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8078 emitpcode(POC_MOVLW, popGetLit(0xff));
8080 emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8085 emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8092 genrshOne (result,left,shCount,sign);
8096 genrshTwo (result,left,shCount,sign);
8100 genrshFour (result,left,shCount,sign);
8108 freeAsmop(left,NULL,ic,TRUE);
8109 freeAsmop(result,NULL,ic,TRUE);
8114 /*-----------------------------------------------------------------*/
8115 /* genSignedRightShift - right shift of signed number */
8116 /*-----------------------------------------------------------------*/
8117 static void genSignedRightShift (iCode *ic)
8119 operand *right, *left, *result;
8122 symbol *tlbl, *tlbl1 ;
8125 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8127 /* we do it the hard way put the shift count in b
8128 and loop thru preserving the sign */
8130 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8132 right = IC_RIGHT(ic);
8134 result = IC_RESULT(ic);
8136 aopOp(right,ic,FALSE);
8137 aopOp(left,ic,FALSE);
8138 aopOp(result,ic,FALSE);
8141 if ( AOP_TYPE(right) == AOP_LIT) {
8142 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8143 //genRightShiftLiteral (left,right,result,ic,1);
8146 /* shift count is unknown then we have to form
8147 a loop get the loop count in B : Note: we take
8148 only the lower order byte since shifting
8149 more that 32 bits make no sense anyway, ( the
8150 largest size of an object can be only 32 bits ) */
8152 //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8153 //pic14_emitcode("inc","b");
8154 //freeAsmop (right,NULL,ic,TRUE);
8155 //aopOp(left,ic,FALSE);
8156 //aopOp(result,ic,FALSE);
8158 /* now move the left to the result if they are not the
8160 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
8161 AOP_SIZE(result) > 1) {
8163 size = AOP_SIZE(result);
8167 l = aopGet(AOP(left),offset,FALSE,TRUE);
8168 if (*l == '@' && IS_AOP_PREG(result)) {
8169 pic14_emitcode("mov","a,%s",l);
8170 aopPut(AOP(result),"a",offset);
8172 aopPut(AOP(result),l,offset);
8174 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8175 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8181 /* mov the highest order bit to OVR */
8182 tlbl = newiTempLabel(NULL);
8183 tlbl1= newiTempLabel(NULL);
8185 size = AOP_SIZE(result);
8188 pctemp = popGetTempReg(); /* grab a temporary working register. */
8190 emitpcode(POC_MOVFW, popGet(AOP(right),0));
8192 /* offset should be 0, 1 or 3 */
8193 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8195 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8197 emitpcode(POC_MOVWF, pctemp);
8200 emitpLabel(tlbl->key);
8202 emitpcode(POC_RLFW, popGet(AOP(result),offset));
8203 emitpcode(POC_RRF, popGet(AOP(result),offset));
8206 emitpcode(POC_RRF, popGet(AOP(result),--offset));
8209 emitpcode(POC_DECFSZ, pctemp);
8210 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8211 emitpLabel(tlbl1->key);
8213 popReleaseTempReg(pctemp);
8215 size = AOP_SIZE(result);
8217 pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8218 pic14_emitcode("rlc","a");
8219 pic14_emitcode("mov","ov,c");
8220 /* if it is only one byte then */
8222 l = aopGet(AOP(left),0,FALSE,FALSE);
8224 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8225 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8226 pic14_emitcode("mov","c,ov");
8227 pic14_emitcode("rrc","a");
8228 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8229 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8230 aopPut(AOP(result),"a",0);
8234 reAdjustPreg(AOP(result));
8235 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8236 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8237 pic14_emitcode("mov","c,ov");
8239 l = aopGet(AOP(result),offset,FALSE,FALSE);
8241 pic14_emitcode("rrc","a");
8242 aopPut(AOP(result),"a",offset--);
8244 reAdjustPreg(AOP(result));
8245 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8246 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8251 freeAsmop(left,NULL,ic,TRUE);
8252 freeAsmop(result,NULL,ic,TRUE);
8253 freeAsmop(right,NULL,ic,TRUE);
8257 /*-----------------------------------------------------------------*/
8258 /* loadSignToC - load the operand's sign bit into CARRY */
8259 /*-----------------------------------------------------------------*/
8261 static void loadSignToC (operand *op)
8264 assert (op && AOP(op) && AOP_SIZE(op));
8267 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8271 /*-----------------------------------------------------------------*/
8272 /* genRightShift - generate code for right shifting */
8273 /*-----------------------------------------------------------------*/
8274 static void genGenericShift (iCode *ic, int shiftRight)
8276 operand *right, *left, *result;
8279 symbol *tlbl, *tlbl1, *inverselbl;
8282 /* if signed then we do it the hard way preserve the
8283 sign bit moving it inwards */
8284 retype = getSpec(operandType(IC_RESULT(ic)));
8285 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8287 /* signed & unsigned types are treated the same : i.e. the
8288 signed is NOT propagated inwards : quoting from the
8289 ANSI - standard : "for E1 >> E2, is equivalent to division
8290 by 2**E2 if unsigned or if it has a non-negative value,
8291 otherwise the result is implementation defined ", MY definition
8292 is that the sign does not get propagated */
8294 right = IC_RIGHT(ic);
8296 result = IC_RESULT(ic);
8298 aopOp(right,ic,FALSE);
8299 aopOp(left,ic,FALSE);
8300 aopOp(result,ic,FALSE);
8302 /* if the shift count is known then do it
8303 as efficiently as possible */
8304 if (AOP_TYPE(right) == AOP_LIT) {
8305 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8309 shiftRight = !shiftRight;
8313 shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8315 shiftLeft_Left2ResultLit (left, result, lit);
8316 //genRightShiftLiteral (left,right,result,ic, 0);
8320 /* shift count is unknown then we have to form
8321 a loop get the loop count in B : Note: we take
8322 only the lower order byte since shifting
8323 more that 32 bits make no sense anyway, ( the
8324 largest size of an object can be only 32 bits ) */
8326 /* we must not overwrite the shift counter */
8327 assert (!pic14_sameRegs(AOP(right),AOP(result)));
8329 /* now move the left to the result if they are not the
8331 if (!pic14_sameRegs(AOP(left),AOP(result)))
8333 size = min(AOP_SIZE(result), AOP_SIZE(left));
8335 mov2w(AOP(left), size);
8336 movwf(AOP(result), size);
8338 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8341 tlbl = newiTempLabel(NULL);
8342 tlbl1= newiTempLabel(NULL);
8344 size = AOP_SIZE(result);
8346 mov2w(AOP(right),0);
8347 if (!SPEC_USIGN(operandType(right)))
8349 inverselbl = newiTempLabel(NULL);
8350 /* signed shift count -- invert shift direction for c<0 */
8351 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8352 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8354 emitpcode(POC_SUBLW, popGetLit(0)); /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8355 /* check for `a = b >> c' with `-c == 0' */
8357 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8358 emitpLabel(tlbl->key);
8359 /* propagate the sign bit inwards for SIGNED result */
8360 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8361 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8362 emitpcode(POC_ADDLW, popGetLit(1)); /* clears CARRY (unless W==0 afterwards) */
8364 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8366 if (!SPEC_USIGN(operandType(right)))
8368 symbol *inv_loop = newiTempLabel(NULL);
8370 shiftRight = !shiftRight; /* invert shift direction */
8372 /* we came here from the code above -- we are done */
8373 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8375 /* emit code for shifting N<0 steps, count is already in W */
8376 emitpLabel(inverselbl->key);
8377 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8378 emitpLabel(inv_loop->key);
8379 /* propagate the sign bit inwards for SIGNED result */
8380 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8381 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8382 emitpcode(POC_ADDLW, popGetLit(1));
8384 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8387 emitpLabel(tlbl1->key);
8389 freeAsmop(left,NULL,ic,TRUE);
8390 freeAsmop (right,NULL,ic,TRUE);
8391 freeAsmop(result,NULL,ic,TRUE);
8394 static void genRightShift (iCode *ic)
8396 genGenericShift(ic, 1);
8399 static void genLeftShift (iCode *ic)
8401 genGenericShift(ic, 0);
8404 /*-----------------------------------------------------------------*/
8405 /* SetIrp - Set IRP bit */
8406 /*-----------------------------------------------------------------*/
8407 void SetIrp(operand *result) {
8409 if (AOP_TYPE(result) == AOP_LIT) {
8410 unsigned lit = (unsigned)operandLitValue(result);
8416 if (PCOP(AOP(result))->type == PO_LITERAL) {
8417 int addrs = PCOL(AOP(result))->lit;
8423 emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8424 if(AOP_SIZE(result) > 1) {
8425 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8433 setup_fsr (operand *ptr)
8436 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8438 /* also setup-up IRP */
8442 /*-----------------------------------------------------------------*/
8443 /* emitPtrByteGet - emits code to get a byte into WREG from an */
8444 /* arbitrary pointer (__code, __data, generic) */
8445 /*-----------------------------------------------------------------*/
8447 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8453 if (!alreadyAddressed) setup_fsr (src);
8454 emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8458 assert( AOP_SIZE(src) == 2 );
8460 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8462 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8463 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
8464 call_libraryfunc ("__gptrget1");
8468 assert( AOP_SIZE(src) == 3 );
8470 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8472 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8474 call_libraryfunc ("__gptrget1");
8478 assert( !"unhandled pointer type" );
8483 /*-----------------------------------------------------------------*/
8484 /* emitPtrByteSet - emits code to set a byte from src through a */
8485 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR). */
8486 /*-----------------------------------------------------------------*/
8488 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8494 if (!alreadyAddressed) setup_fsr (dst);
8495 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8499 assert( !"trying to assign to __code pointer" );
8503 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8505 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8507 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8509 call_libraryfunc ("__gptrput1");
8513 assert( !"unhandled pointer type" );
8518 /*-----------------------------------------------------------------*/
8519 /* genUnpackBits - generates code for unpacking bits */
8520 /*-----------------------------------------------------------------*/
8521 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8523 int rsize; /* result size */
8524 sym_link *etype; /* bitfield type information */
8525 int blen; /* bitfield length */
8526 int bstr; /* bitfield starting bit within byte */
8529 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8530 etype = getSpec(operandType(result));
8531 rsize = getSize (operandType (result));
8532 blen = SPEC_BLEN (etype);
8533 bstr = SPEC_BSTR (etype);
8535 /* single bit field case */
8537 if (ifx) { /* that is for an if statement */
8540 resolveIfx(&rIfx,ifx);
8541 if (ptype == -1) /* direct */
8542 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8544 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8545 emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8546 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8550 assert (!pic14_sameRegs (AOP(result), AOP(left)));
8551 for (i=0; i < AOP_SIZE(result); i++)
8552 emitpcode (POC_CLRF, popGet (AOP(result), i));
8557 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8558 /* adjust result below */
8564 emitPtrByteGet (left, ptype, FALSE);
8565 emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8567 /* adjust result below */
8571 assert( !"unhandled pointer type" );
8574 /* move sign-/zero extended bit to result */
8575 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8576 emitpcode (POC_INCF, popGet (AOP(result), 0));
8578 emitpcode (POC_DECF, popGet (AOP(result), 0));
8580 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8584 else if (blen <= 8 && ((blen + bstr) <= 8))
8589 for (i=0; i < AOP_SIZE(result); i++)
8590 emitpcode (POC_CLRF, popGet (AOP(result), i));
8595 mov2w(AOP(left), 0);
8601 emitPtrByteGet (left, ptype, FALSE);
8605 assert( !"unhandled pointer type" );
8609 emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8610 movwf(AOP(result), 0);
8611 AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8613 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8615 /* signed bitfield */
8616 assert (bstr + blen > 0);
8617 emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8618 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8619 emitpcode(POC_IORWF, popGet(AOP(result),0));
8621 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8625 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8629 /*-----------------------------------------------------------------*/
8630 /* genDataPointerGet - generates code when ptr offset is known */
8631 /*-----------------------------------------------------------------*/
8632 static void genDataPointerGet (operand *left,
8636 int size , offset = 0;
8639 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8642 /* optimization - most of the time, left and result are the same
8643 * address, but different types. for the pic code, we could omit
8646 aopOp(result,ic,TRUE);
8648 if (pic14_sameRegs (AOP(left), AOP(result)))
8651 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8653 //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8655 size = AOP_SIZE(result);
8656 if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8660 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8661 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8665 freeAsmop(left,NULL,ic,TRUE);
8666 freeAsmop(result,NULL,ic,TRUE);
8670 /*-----------------------------------------------------------------*/
8671 /* genNearPointerGet - pic14_emitcode for near pointer fetch */
8672 /*-----------------------------------------------------------------*/
8673 static void genNearPointerGet (operand *left,
8678 sym_link *ltype = operandType(left);
8679 sym_link *rtype = operandType(result);
8680 sym_link *retype= getSpec(rtype); /* bitfield type information */
8684 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8687 aopOp(left,ic,FALSE);
8689 /* if left is rematerialisable and
8690 result is not bit variable type and
8691 the left is pointer to data space i.e
8692 lower 128 bytes of space */
8693 if (AOP_TYPE(left) == AOP_PCODE && //AOP_TYPE(left) == AOP_IMMD &&
8694 !IS_BITVAR(retype) &&
8695 DCL_TYPE(ltype) == POINTER) {
8696 genDataPointerGet (left,result,ic);
8700 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8701 aopOp (result,ic,FALSE);
8703 /* Check if can access directly instead of via a pointer */
8704 if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8705 && AOP_SIZE(result) == 1)
8710 if (IS_BITFIELD(getSpec(operandType(result))))
8712 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8716 /* If the pointer value is not in a the FSR then need to put it in */
8717 /* Must set/reset IRP bit for use with FSR. */
8722 /* if bitfield then unpack the bits */
8724 /* we have can just get the values */
8725 int size = AOP_SIZE(result);
8728 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8732 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8734 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8735 if (AOP_TYPE(result) == AOP_LIT) {
8736 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8738 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8740 if (size && !direct)
8741 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8746 /* now some housekeeping stuff */
8748 /* we had to allocate for this iCode */
8749 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8750 freeAsmop(NULL,aop,ic,TRUE);
8752 /* we did not allocate which means left
8753 already in a pointer register, then
8754 if size > 0 && this could be used again
8755 we have to point it back to where it
8757 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8758 if (AOP_SIZE(result) > 1 &&
8759 !OP_SYMBOL(left)->remat &&
8760 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8762 int size = AOP_SIZE(result) - 1;
8764 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8770 freeAsmop(left,NULL,ic,TRUE);
8771 freeAsmop(result,NULL,ic,TRUE);
8776 /*-----------------------------------------------------------------*/
8777 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch */
8778 /*-----------------------------------------------------------------*/
8779 static void genPagedPointerGet (operand *left,
8786 sym_link *rtype, *retype;
8789 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8791 rtype = operandType(result);
8792 retype= getSpec(rtype);
8794 aopOp(left,ic,FALSE);
8796 /* if the value is already in a pointer register
8797 then don't need anything more */
8798 if (!AOP_INPREG(AOP(left))) {
8799 /* otherwise get a free pointer register */
8801 preg = getFreePtr(ic,&aop,FALSE);
8802 pic14_emitcode("mov","%s,%s",
8804 aopGet(AOP(left),0,FALSE,TRUE));
8805 rname = preg->name ;
8807 rname = aopGet(AOP(left),0,FALSE,FALSE);
8809 freeAsmop(left,NULL,ic,TRUE);
8810 aopOp (result,ic,FALSE);
8812 /* if bitfield then unpack the bits */
8813 if (IS_BITFIELD(retype))
8814 genUnpackBits (result,left,rname,PPOINTER,0);
8816 /* we have can just get the values */
8817 int size = AOP_SIZE(result);
8822 pic14_emitcode("movx","a,@%s",rname);
8823 aopPut(AOP(result),"a",offset);
8828 pic14_emitcode("inc","%s",rname);
8832 /* now some housekeeping stuff */
8834 /* we had to allocate for this iCode */
8835 freeAsmop(NULL,aop,ic,TRUE);
8837 /* we did not allocate which means left
8838 already in a pointer register, then
8839 if size > 0 && this could be used again
8840 we have to point it back to where it
8842 if (AOP_SIZE(result) > 1 &&
8843 !OP_SYMBOL(left)->remat &&
8844 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8846 int size = AOP_SIZE(result) - 1;
8848 pic14_emitcode("dec","%s",rname);
8853 freeAsmop(result,NULL,ic,TRUE);
8858 /*-----------------------------------------------------------------*/
8859 /* genFarPointerGet - gget value from far space */
8860 /*-----------------------------------------------------------------*/
8861 static void genFarPointerGet (operand *left,
8862 operand *result, iCode *ic)
8865 sym_link *retype = getSpec(operandType(result));
8868 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8870 aopOp(left,ic,FALSE);
8872 /* if the operand is already in dptr
8873 then we do nothing else we move the value to dptr */
8874 if (AOP_TYPE(left) != AOP_STR) {
8875 /* if this is remateriazable */
8876 if (AOP_TYPE(left) == AOP_IMMD)
8877 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8878 else { /* we need to get it byte by byte */
8879 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8880 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8881 if (options.model == MODEL_FLAT24)
8883 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8887 /* so dptr know contains the address */
8888 freeAsmop(left,NULL,ic,TRUE);
8889 aopOp(result,ic,FALSE);
8891 /* if bit then unpack */
8892 if (IS_BITFIELD(retype))
8893 genUnpackBits(result,left,"dptr",FPOINTER,0);
8895 size = AOP_SIZE(result);
8899 pic14_emitcode("movx","a,@dptr");
8900 aopPut(AOP(result),"a",offset++);
8902 pic14_emitcode("inc","dptr");
8906 freeAsmop(result,NULL,ic,TRUE);
8911 /*-----------------------------------------------------------------*/
8912 /* genCodePointerGet - get value from code space */
8913 /*-----------------------------------------------------------------*/
8914 static void genCodePointerGet (operand *left,
8915 operand *result, iCode *ic)
8918 sym_link *retype = getSpec(operandType(result));
8920 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8922 aopOp(left,ic,FALSE);
8924 /* if the operand is already in dptr
8925 then we do nothing else we move the value to dptr */
8926 if (AOP_TYPE(left) != AOP_STR) {
8927 /* if this is remateriazable */
8928 if (AOP_TYPE(left) == AOP_IMMD)
8929 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8930 else { /* we need to get it byte by byte */
8931 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8932 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8933 if (options.model == MODEL_FLAT24)
8935 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8939 /* so dptr know contains the address */
8940 freeAsmop(left,NULL,ic,TRUE);
8941 aopOp(result,ic,FALSE);
8943 /* if bit then unpack */
8944 if (IS_BITFIELD(retype))
8945 genUnpackBits(result,left,"dptr",CPOINTER,0);
8947 size = AOP_SIZE(result);
8951 pic14_emitcode("clr","a");
8952 pic14_emitcode("movc","a,@a+dptr");
8953 aopPut(AOP(result),"a",offset++);
8955 pic14_emitcode("inc","dptr");
8959 freeAsmop(result,NULL,ic,TRUE);
8962 /*-----------------------------------------------------------------*/
8963 /* genGenPointerGet - gget value from generic pointer space */
8964 /*-----------------------------------------------------------------*/
8965 static void genGenPointerGet (operand *left,
8966 operand *result, iCode *ic)
8969 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8970 aopOp(left,ic,FALSE);
8971 aopOp(result,ic,FALSE);
8974 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8976 if (IS_BITFIELD(getSpec(operandType(result))))
8978 genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
8983 /* emit call to __gptrget */
8984 char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
8985 int size = AOP_SIZE(result);
8988 assert (size > 0 && size <= 4);
8990 /* pass arguments */
8991 assert (AOP_SIZE(left) == 3);
8992 mov2w(AOP(left), 0);
8993 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8994 mov2w(AOP(left), 1);
8995 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8996 mov2w(AOP(left), 2);
8997 call_libraryfunc (func[size]);
9000 movwf (AOP(result), --size);
9002 emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
9003 movwf (AOP(result), size);
9007 freeAsmop(left,NULL,ic,TRUE);
9008 freeAsmop(result,NULL,ic,TRUE);
9012 /*-----------------------------------------------------------------*/
9013 /* genConstPointerGet - get value from const generic pointer space */
9014 /*-----------------------------------------------------------------*/
9015 static void genConstPointerGet (operand *left,
9016 operand *result, iCode *ic)
9018 //sym_link *retype = getSpec(operandType(result));
9020 symbol *albl, *blbl;//, *clbl;
9027 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9028 aopOp(left,ic,FALSE);
9029 aopOp(result,ic,FALSE);
9031 size = AOP_SIZE(result);
9033 DEBUGpic14_AopType(__LINE__,left,NULL,result);
9035 DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
9037 lit = op_isLitLike (left);
9038 poc = lit ? POC_MOVLW : POC_MOVFW;
9040 if (IS_BITFIELD(getSpec(operandType(result))))
9042 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
9047 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
9048 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
9049 assert (size > 0 && size <= 4);
9052 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9054 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9055 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
9056 call_libraryfunc (func[size]);
9058 movwf(AOP(result),size-1);
9059 for (i = 1; i < size; i++)
9061 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
9062 movwf(AOP(result),size - 1 - i);
9067 freeAsmop(left,NULL,ic,TRUE);
9068 freeAsmop(result,NULL,ic,TRUE);
9071 /*-----------------------------------------------------------------*/
9072 /* genPointerGet - generate code for pointer get */
9073 /*-----------------------------------------------------------------*/
9074 static void genPointerGet (iCode *ic)
9076 operand *left, *result ;
9077 sym_link *type, *etype;
9081 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9084 result = IC_RESULT(ic) ;
9086 /* depending on the type of pointer we need to
9087 move it to the correct pointer register */
9088 type = operandType(left);
9089 etype = getSpec(type);
9091 if (IS_PTR_CONST(type))
9092 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9094 /* if left is of type of pointer then it is simple */
9095 if (IS_PTR(type) && !IS_FUNC(type->next))
9096 p_type = DCL_TYPE(type);
9098 /* we have to go by the storage class */
9099 p_type = PTR_TYPE(SPEC_OCLS(etype));
9101 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9103 if (SPEC_OCLS(etype)->codesp ) {
9104 DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9105 //p_type = CPOINTER ;
9108 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9109 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9110 /*p_type = FPOINTER ;*/
9112 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9113 DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9114 /* p_type = PPOINTER; */
9116 if (SPEC_OCLS(etype) == idata )
9117 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9118 /* p_type = IPOINTER; */
9120 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9121 /* p_type = POINTER ; */
9124 /* now that we have the pointer type we assign
9125 the pointer values */
9130 genNearPointerGet (left,result,ic);
9134 genPagedPointerGet(left,result,ic);
9138 genFarPointerGet (left,result,ic);
9142 genConstPointerGet (left,result,ic);
9146 genGenPointerGet (left,result,ic);
9149 assert ( !"unhandled pointer type" );
9155 /*-----------------------------------------------------------------*/
9156 /* genPackBits - generates code for packed bit storage */
9157 /*-----------------------------------------------------------------*/
9158 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9160 int blen; /* bitfield length */
9161 int bstr; /* bitfield starting bit within byte */
9162 int litval; /* source literal value (if AOP_LIT) */
9163 unsigned char mask; /* bitmask within current byte */
9166 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9168 blen = SPEC_BLEN (etype);
9169 bstr = SPEC_BSTR (etype);
9171 /* If the bitfield length is less than a byte and does not cross byte boundaries */
9172 if ((blen <= 8) && ((bstr + blen) <= 8))
9174 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9175 (unsigned char) (0xFF >> (8 - bstr)));
9177 if (AOP_TYPE (right) == AOP_LIT)
9179 /* Case with a bitfield length <8 and literal source */
9180 int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9187 if (AOP(result)->type == AOP_PCODE)
9188 pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9190 pcop = popGet(AOP(result),0);
9191 emitpcode(lit?POC_BSF:POC_BCF,pcop);
9196 emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9200 assert( !"trying to assign to bitfield via pointer to __code space" );
9204 emitPtrByteGet(result, p_type, FALSE);
9206 emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9208 emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9210 emitPtrByteSet(result, p_type, TRUE);
9214 assert( !"unhandled pointer type" );
9216 } // switch (p_type)
9219 litval = lit << bstr;
9220 litval &= (~mask) & 0x00ff;
9225 mov2w (AOP(result), 0);
9226 if ((litval|mask) != 0x00ff)
9227 emitpcode(POC_ANDLW, popGetLit (mask));
9229 emitpcode(POC_IORLW, popGetLit (litval));
9230 movwf (AOP(result), 0);
9235 emitPtrByteGet(result, p_type, FALSE);
9236 if ((litval|mask) != 0x00ff)
9237 emitpcode(POC_ANDLW, popGetLit (mask));
9239 emitpcode(POC_IORLW, popGetLit (litval));
9240 emitPtrByteSet(result, p_type, TRUE);
9244 assert( !"trying to assign to bitfield via pointer to __code space" );
9248 assert( !"unhandled pointer type" );
9255 /* right is no literal */
9260 /* Note more efficient code, of pre clearing bit then only setting it if required,
9261 * can only be done if it is known that the result is not a SFR */
9262 emitpcode(POC_RRFW,popGet(AOP(right),0));
9264 emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9266 emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9271 emitPtrByteGet (result, p_type, FALSE);
9272 emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9273 emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9274 emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9275 emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9276 emitPtrByteSet (result, p_type, TRUE);
9280 assert( !"trying to assign to bitfield via pointer to __code space" );
9284 assert( !"unhandled pointer type" );
9289 /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9290 pCodeOp *temp = popGetTempReg ();
9292 mov2w (AOP(right), 0);
9294 emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9296 emitpcode(POC_MOVWF, temp);
9298 AccLsh (temp, bstr);
9304 mov2w (AOP(result), 0);
9305 emitpcode(POC_ANDLW, popGetLit (mask));
9306 emitpcode(POC_IORFW, temp);
9307 movwf (AOP(result), 0);
9312 emitPtrByteGet (result, p_type, FALSE);
9313 emitpcode(POC_ANDLW, popGetLit (mask));
9314 emitpcode(POC_IORFW, temp);
9315 emitPtrByteSet (result, p_type, TRUE);
9319 assert( !"trying to assign to bitfield via pointer to __code space" );
9323 assert( !"unhandled pointer type" );
9327 popReleaseTempReg (temp);
9329 } // if (AOP(right)->type != AOP_LIT)
9331 } // if (blen <= 8 && ((blen + bstr) <= 8))
9333 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9337 bitpatternFromVal (value *val)
9344 assert (sizeof (float) == sizeof (long));
9346 //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));
9348 switch (SPEC_NOUN(val->type))
9352 return (unsigned long)floatFromVal (val);
9356 float_long.d = floatFromVal (val);
9357 return float_long.l;
9360 assert( !"unhandled value type" );
9364 float_long.d = floatFromVal (val);
9365 return float_long.l;
9368 /*-----------------------------------------------------------------*/
9369 /* genDataPointerSet - remat pointer to data space */
9370 /*-----------------------------------------------------------------*/
9371 static void genDataPointerSet(operand *right,
9375 int size, offset = 0 ;
9379 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9380 aopOp(right,ic,FALSE);
9381 aopOp(result,ic,FALSE);
9383 assert (IS_SYMOP(result));
9384 assert (IS_PTR(OP_SYM_TYPE(result)));
9386 size = AOP_SIZE(right);
9387 ressize = getSize(OP_SYM_ETYPE(result));
9388 if (size > ressize) size = ressize;
9389 //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9391 //assert( !"what's going on here?" );
9394 if ( AOP_TYPE(result) == AOP_PCODE) {
9395 fprintf(stderr,"genDataPointerSet %s, %d\n",
9396 AOP(result)->aopu.pcop->name,
9397 PCOI(AOP(result)->aopu.pcop)->offset);
9401 // tsd, was l+1 - the underline `_' prefix was being stripped
9403 emitpComment ("%s:%u: size=%d/%d, offset=%i", __FILE__,__LINE__, size, ressize, offset);
9405 if (AOP_TYPE(right) == AOP_LIT) {
9406 /* XXX: might be float... */
9407 unsigned int lit = bitpatternFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9408 lit = lit >> (8*offset);
9409 //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9411 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9412 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9414 emitpcode(POC_CLRF, popGet(AOP(result),offset));
9417 //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9418 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9419 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9425 freeAsmop(right,NULL,ic,TRUE);
9426 freeAsmop(result,NULL,ic,TRUE);
9429 /*-----------------------------------------------------------------*/
9430 /* genNearPointerSet - pic14_emitcode for near pointer put */
9431 /*-----------------------------------------------------------------*/
9432 static void genNearPointerSet (operand *right,
9437 sym_link *ptype = operandType(result);
9438 sym_link *retype = getSpec(operandType(right));
9439 sym_link *letype = getSpec(ptype);
9444 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9445 aopOp(result,ic,FALSE);
9448 /* if the result is rematerializable &
9449 in data space & not a bit variable */
9450 //if (AOP_TYPE(result) == AOP_IMMD &&
9451 if (AOP_TYPE(result) == AOP_PCODE &&
9452 DCL_TYPE(ptype) == POINTER &&
9453 !IS_BITVAR (retype) &&
9454 !IS_BITVAR (letype)) {
9455 genDataPointerSet (right,result,ic);
9456 freeAsmop(result,NULL,ic,TRUE);
9461 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9462 aopOp(right,ic,FALSE);
9463 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9465 /* Check if can access directly instead of via a pointer */
9466 if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9470 if (IS_BITFIELD (letype))
9472 genPackBits (letype, result, right, direct?-1:POINTER);
9476 /* If the pointer value is not in a the FSR then need to put it in */
9477 /* Must set/reset IRP bit for use with FSR. */
9478 /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9483 /* we have can just get the values */
9484 int size = AOP_SIZE(right);
9487 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9489 char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9491 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9493 if (AOP_TYPE(right) == AOP_LIT) {
9494 emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9496 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9499 emitpcode(POC_MOVWF,popGet(AOP(result),0));
9501 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9503 if (size && !direct)
9504 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9509 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9510 /* now some housekeeping stuff */
9512 /* we had to allocate for this iCode */
9513 freeAsmop(NULL,aop,ic,TRUE);
9515 /* we did not allocate which means left
9516 already in a pointer register, then
9517 if size > 0 && this could be used again
9518 we have to point it back to where it
9520 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9521 if (AOP_SIZE(right) > 1 &&
9522 !OP_SYMBOL(result)->remat &&
9523 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9525 int size = AOP_SIZE(right) - 1;
9527 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9531 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9534 freeAsmop(right,NULL,ic,TRUE);
9535 freeAsmop(result,NULL,ic,TRUE);
9539 /*-----------------------------------------------------------------*/
9540 /* genPagedPointerSet - pic14_emitcode for Paged pointer put */
9541 /*-----------------------------------------------------------------*/
9542 static void genPagedPointerSet (operand *right,
9552 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9554 retype= getSpec(operandType(right));
9556 aopOp(result,ic,FALSE);
9558 /* if the value is already in a pointer register
9559 then don't need anything more */
9560 if (!AOP_INPREG(AOP(result))) {
9561 /* otherwise get a free pointer register */
9563 preg = getFreePtr(ic,&aop,FALSE);
9564 pic14_emitcode("mov","%s,%s",
9566 aopGet(AOP(result),0,FALSE,TRUE));
9567 rname = preg->name ;
9569 rname = aopGet(AOP(result),0,FALSE,FALSE);
9571 freeAsmop(result,NULL,ic,TRUE);
9572 aopOp (right,ic,FALSE);
9574 /* if bitfield then unpack the bits */
9575 if (IS_BITFIELD(retype))
9576 genPackBits (retype,result,right,rname,PPOINTER);
9578 /* we have can just get the values */
9579 int size = AOP_SIZE(right);
9583 l = aopGet(AOP(right),offset,FALSE,TRUE);
9586 pic14_emitcode("movx","@%s,a",rname);
9589 pic14_emitcode("inc","%s",rname);
9595 /* now some housekeeping stuff */
9597 /* we had to allocate for this iCode */
9598 freeAsmop(NULL,aop,ic,TRUE);
9600 /* we did not allocate which means left
9601 already in a pointer register, then
9602 if size > 0 && this could be used again
9603 we have to point it back to where it
9605 if (AOP_SIZE(right) > 1 &&
9606 !OP_SYMBOL(result)->remat &&
9607 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9609 int size = AOP_SIZE(right) - 1;
9611 pic14_emitcode("dec","%s",rname);
9616 freeAsmop(right,NULL,ic,TRUE);
9621 /*-----------------------------------------------------------------*/
9622 /* genFarPointerSet - set value from far space */
9623 /*-----------------------------------------------------------------*/
9624 static void genFarPointerSet (operand *right,
9625 operand *result, iCode *ic)
9628 sym_link *retype = getSpec(operandType(right));
9631 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9632 aopOp(result,ic,FALSE);
9634 /* if the operand is already in dptr
9635 then we do nothing else we move the value to dptr */
9636 if (AOP_TYPE(result) != AOP_STR) {
9637 /* if this is remateriazable */
9638 if (AOP_TYPE(result) == AOP_IMMD)
9639 pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9640 else { /* we need to get it byte by byte */
9641 pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9642 pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9643 if (options.model == MODEL_FLAT24)
9645 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9649 /* so dptr know contains the address */
9650 freeAsmop(result,NULL,ic,TRUE);
9651 aopOp(right,ic,FALSE);
9653 /* if bit then unpack */
9654 if (IS_BITFIELD(retype))
9655 genPackBits(retype,result,right,"dptr",FPOINTER);
9657 size = AOP_SIZE(right);
9661 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9663 pic14_emitcode("movx","@dptr,a");
9665 pic14_emitcode("inc","dptr");
9669 freeAsmop(right,NULL,ic,TRUE);
9673 /*-----------------------------------------------------------------*/
9674 /* genGenPointerSet - set value from generic pointer space */
9675 /*-----------------------------------------------------------------*/
9676 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9678 sym_link *retype = getSpec(operandType(result));
9681 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9682 aopOp(right,ic,FALSE);
9683 aopOp(result,ic,FALSE);
9686 DEBUGpic14_AopType(__LINE__,right,NULL,result);
9688 if (IS_BITFIELD(retype))
9690 genPackBits (retype, result, right, GPOINTER);
9695 /* emit call to __gptrput */
9696 char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9697 int size = AOP_SIZE(right);
9700 assert (size == getSize(OP_SYM_ETYPE(result)));
9701 assert (size > 0 && size <= 4);
9703 /* pass arguments */
9704 /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9710 mov2w_op (right, off);
9711 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9716 assert (AOP_SIZE(result) == 3);
9717 mov2w(AOP(result), 0);
9718 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9719 mov2w(AOP(result), 1);
9720 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9721 mov2w(AOP(result), 2);
9722 call_libraryfunc (func[size]);
9725 freeAsmop(right,NULL,ic,TRUE);
9726 freeAsmop(result,NULL,ic,TRUE);
9729 /*-----------------------------------------------------------------*/
9730 /* genPointerSet - stores the value into a pointer location */
9731 /*-----------------------------------------------------------------*/
9732 static void genPointerSet (iCode *ic)
9734 operand *right, *result ;
9735 sym_link *type, *etype;
9739 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9741 right = IC_RIGHT(ic);
9742 result = IC_RESULT(ic) ;
9744 /* depending on the type of pointer we need to
9745 move it to the correct pointer register */
9746 type = operandType(result);
9747 etype = getSpec(type);
9748 /* if left is of type of pointer then it is simple */
9749 if (IS_PTR(type) && !IS_FUNC(type->next)) {
9750 p_type = DCL_TYPE(type);
9753 /* we have to go by the storage class */
9754 p_type = PTR_TYPE(SPEC_OCLS(etype));
9756 /* if (SPEC_OCLS(etype)->codesp ) { */
9757 /* p_type = CPOINTER ; */
9760 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9761 /* p_type = FPOINTER ; */
9763 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9764 /* p_type = PPOINTER ; */
9766 /* if (SPEC_OCLS(etype) == idata ) */
9767 /* p_type = IPOINTER ; */
9769 /* p_type = POINTER ; */
9772 /* now that we have the pointer type we assign
9773 the pointer values */
9778 genNearPointerSet (right,result,ic);
9782 genPagedPointerSet (right,result,ic);
9786 genFarPointerSet (right,result,ic);
9790 genGenPointerSet (right,result,ic);
9794 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9795 "genPointerSet: illegal pointer type");
9799 /*-----------------------------------------------------------------*/
9800 /* genIfx - generate code for Ifx statement */
9801 /*-----------------------------------------------------------------*/
9802 static void genIfx (iCode *ic, iCode *popIc)
9804 operand *cond = IC_COND(ic);
9808 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9810 aopOp(cond,ic,FALSE);
9812 /* get the value into acc */
9813 if (AOP_TYPE(cond) != AOP_CRY)
9814 pic14_toBoolean(cond);
9817 /* the result is now in the accumulator */
9818 freeAsmop(cond,NULL,ic,TRUE);
9820 /* if there was something to be popped then do it */
9826 assert (!"genIfx not implemented for bit variables...");
9830 /* now Z if set iff !cond */
9833 assert (!IC_FALSE(ic));
9835 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9838 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9846 /*-----------------------------------------------------------------*/
9847 /* genAddrOf - generates code for address of */
9848 /*-----------------------------------------------------------------*/
9849 static void genAddrOf (iCode *ic)
9851 operand *right, *result, *left;
9855 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9858 //aopOp(IC_RESULT(ic),ic,FALSE);
9860 aopOp((left=IC_LEFT(ic)),ic,FALSE);
9861 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9862 aopOp((result=IC_RESULT(ic)),ic,TRUE);
9864 DEBUGpic14_AopType(__LINE__,left,right,result);
9865 assert (IS_SYMOP (left));
9867 /* sanity check: generic pointers to code space are not yet supported,
9868 * pionters to codespace must not be assigned addresses of __data values. */
9870 fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9871 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)));
9872 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)));
9873 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)));
9874 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)));
9877 if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9878 fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9879 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9880 OP_SYMBOL(left)->name);
9881 } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9882 fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9883 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9884 OP_SYMBOL(left)->name);
9887 size = AOP_SIZE(IC_RESULT(ic));
9888 if (IS_GENPTR(OP_SYM_TYPE(result))) {
9890 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9895 /* fixing bug #863624, reported from (errolv) */
9896 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9897 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9900 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9901 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9906 if (IS_GENPTR(OP_SYM_TYPE(result)))
9908 /* provide correct tag */
9909 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9910 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9911 movwf (AOP(result), 2);
9914 freeAsmop(left,NULL,ic,FALSE);
9915 freeAsmop(result,NULL,ic,TRUE);
9920 /*-----------------------------------------------------------------*/
9921 /* genFarFarAssign - assignment when both are in far space */
9922 /*-----------------------------------------------------------------*/
9923 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9925 int size = AOP_SIZE(right);
9928 /* first push the right side on to the stack */
9930 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9932 pic14_emitcode ("push","acc");
9935 freeAsmop(right,NULL,ic,FALSE);
9936 /* now assign DPTR to result */
9937 aopOp(result,ic,FALSE);
9938 size = AOP_SIZE(result);
9940 pic14_emitcode ("pop","acc");
9941 aopPut(AOP(result),"a",--offset);
9943 freeAsmop(result,NULL,ic,FALSE);
9948 /*-----------------------------------------------------------------*/
9949 /* genAssign - generate code for assignment */
9950 /*-----------------------------------------------------------------*/
9951 static void genAssign (iCode *ic)
9953 operand *result, *right;
9954 int size, offset,know_W;
9955 unsigned long lit = 0L;
9957 result = IC_RESULT(ic);
9958 right = IC_RIGHT(ic) ;
9961 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9963 /* if they are the same */
9964 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9967 aopOp(right,ic,FALSE);
9968 aopOp(result,ic,TRUE);
9970 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9972 /* if they are the same registers */
9973 if (pic14_sameRegs(AOP(right),AOP(result)))
9976 /* special case: assign from __code */
9977 if (!IS_ITEMP(right) /* --> iTemps never reside in __code */
9978 && IS_SYMOP (right) /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
9979 && !IS_FUNC(OP_SYM_TYPE(right)) /* --> we would want its address instead of the first instruction */
9980 && !IS_CODEPTR(OP_SYM_TYPE(right)) /* --> get symbols address instread */
9981 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
9983 emitpComment ("genAssign from CODESPACE");
9984 genConstPointerGet (right, result, ic);
9988 /* just for symmetry reasons... */
9989 if (!IS_ITEMP(result)
9990 && IS_SYMOP (result)
9991 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
9993 assert ( !"cannot write to CODESPACE" );
9996 /* if the result is a bit */
9997 if (AOP_TYPE(result) == AOP_CRY) {
9999 /* if the right size is a literal then
10000 we know what the value is */
10001 if (AOP_TYPE(right) == AOP_LIT) {
10003 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10004 popGet(AOP(result),0));
10006 if (((int) operandLitValue(right)))
10007 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10008 AOP(result)->aopu.aop_dir,
10009 AOP(result)->aopu.aop_dir);
10011 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10012 AOP(result)->aopu.aop_dir,
10013 AOP(result)->aopu.aop_dir);
10017 /* the right is also a bit variable */
10018 if (AOP_TYPE(right) == AOP_CRY) {
10019 emitpcode(POC_BCF, popGet(AOP(result),0));
10020 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10021 emitpcode(POC_BSF, popGet(AOP(result),0));
10023 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10024 AOP(result)->aopu.aop_dir,
10025 AOP(result)->aopu.aop_dir);
10026 pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
10027 AOP(right)->aopu.aop_dir,
10028 AOP(right)->aopu.aop_dir);
10029 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10030 AOP(result)->aopu.aop_dir,
10031 AOP(result)->aopu.aop_dir);
10035 /* we need to or */
10036 emitpcode(POC_BCF, popGet(AOP(result),0));
10037 pic14_toBoolean(right);
10039 emitpcode(POC_BSF, popGet(AOP(result),0));
10040 //aopPut(AOP(result),"a",0);
10044 /* bit variables done */
10046 size = AOP_SIZE(result);
10048 if(AOP_TYPE(right) == AOP_LIT)
10049 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10051 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
10052 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10053 if(aopIdx(AOP(result),0) == 4) {
10054 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10055 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10056 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10059 DEBUGpic14_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
10064 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10065 if(AOP_TYPE(right) == AOP_LIT) {
10067 if(know_W != (int)(lit&0xff))
10068 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10070 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10072 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10076 } else if (AOP_TYPE(right) == AOP_CRY) {
10077 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10079 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10080 emitpcode(POC_INCF, popGet(AOP(result),0));
10083 mov2w_op (right, offset);
10084 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10092 freeAsmop (right,NULL,ic,FALSE);
10093 freeAsmop (result,NULL,ic,TRUE);
10096 /*-----------------------------------------------------------------*/
10097 /* genJumpTab - genrates code for jump table */
10098 /*-----------------------------------------------------------------*/
10099 static void genJumpTab (iCode *ic)
10105 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10107 aopOp(IC_JTCOND(ic),ic,FALSE);
10108 /* get the condition into accumulator */
10109 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10111 /* multiply by three */
10112 pic14_emitcode("add","a,acc");
10113 pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10115 jtab = newiTempLabel(NULL);
10116 pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10117 pic14_emitcode("jmp","@a+dptr");
10118 pic14_emitcode("","%05d_DS_:",jtab->key+100);
10120 emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10121 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10122 emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10123 emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10125 emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10126 emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10127 emitpLabel(jtab->key);
10129 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10131 /* now generate the jump labels */
10132 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10133 jtab = setNextItem(IC_JTLABELS(ic))) {
10134 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10135 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10141 /*-----------------------------------------------------------------*/
10142 /* genMixedOperation - gen code for operators between mixed types */
10143 /*-----------------------------------------------------------------*/
10145 TSD - Written for the PIC port - but this unfortunately is buggy.
10146 This routine is good in that it is able to efficiently promote
10147 types to different (larger) sizes. Unfortunately, the temporary
10148 variables that are optimized out by this routine are sometimes
10149 used in other places. So until I know how to really parse the
10150 iCode tree, I'm going to not be using this routine :(.
10152 static int genMixedOperation (iCode *ic)
10156 operand *result = IC_RESULT(ic);
10157 sym_link *ctype = operandType(IC_LEFT(ic));
10158 operand *right = IC_RIGHT(ic);
10164 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10166 pic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10172 nextright = IC_RIGHT(nextic);
10173 nextleft = IC_LEFT(nextic);
10174 nextresult = IC_RESULT(nextic);
10176 aopOp(right,ic,FALSE);
10177 aopOp(result,ic,FALSE);
10178 aopOp(nextright, nextic, FALSE);
10179 aopOp(nextleft, nextic, FALSE);
10180 aopOp(nextresult, nextic, FALSE);
10182 if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10184 operand *t = right;
10188 pic14_emitcode(";remove right +","");
10190 } else if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10192 operand *t = right;
10196 pic14_emitcode(";remove left +","");
10200 big = AOP_SIZE(nextleft);
10201 small = AOP_SIZE(nextright);
10203 switch(nextic->op) {
10206 pic14_emitcode(";optimize a +","");
10207 /* if unsigned or not an integral type */
10208 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10209 pic14_emitcode(";add a bit to something","");
10212 pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10214 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10215 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10216 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10218 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10226 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10227 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10228 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10231 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10233 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10234 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10235 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10236 pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10237 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10240 pic14_emitcode("rlf","known_zero,w");
10247 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10248 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10249 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10251 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10261 freeAsmop(right,NULL,ic,TRUE);
10262 freeAsmop(result,NULL,ic,TRUE);
10263 freeAsmop(nextright,NULL,ic,TRUE);
10264 freeAsmop(nextleft,NULL,ic,TRUE);
10266 nextic->generated = 1;
10273 /*-----------------------------------------------------------------*/
10274 /* genCast - gen code for casting */
10275 /*-----------------------------------------------------------------*/
10276 static void genCast (iCode *ic)
10278 operand *result = IC_RESULT(ic);
10279 sym_link *restype = operandType(result);
10280 sym_link *rtype = operandType(IC_RIGHT(ic));
10281 operand *right = IC_RIGHT(ic);
10285 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10286 /* if they are equivalent then do nothing */
10287 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10290 aopOp(right,ic,FALSE) ;
10291 aopOp(result,ic,FALSE);
10293 DEBUGpic14_AopType(__LINE__,NULL,right,result);
10295 /* if the result is a bit */
10296 if (AOP_TYPE(result) == AOP_CRY) {
10297 assert(!"assigning to bit variables is not supported");
10300 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10302 size = AOP_SIZE(result);
10304 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10306 emitpcode(POC_CLRF, popGet(AOP(result),0));
10307 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10308 emitpcode(POC_INCF, popGet(AOP(result),0));
10311 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
10316 if (IS_PTR(restype))
10318 operand *result = IC_RESULT(ic);
10319 //operand *left = IC_LEFT(ic);
10320 operand *right = IC_RIGHT(ic);
10323 /* copy common part */
10324 int max, size = AOP_SIZE(result);
10325 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10326 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10328 /* warn if we discard generic opinter tag */
10329 if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10331 //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10337 mov2w_op (right, size);
10338 movwf (AOP(result), size);
10341 /* upcast into generic pointer type? */
10342 if (IS_GENPTR(restype)
10343 && (size < AOP_SIZE(result))
10344 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10346 //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10349 switch (DCL_TYPE(rtype))
10351 case POINTER: /* __data */
10352 case FPOINTER: /* __data */
10353 assert (AOP_SIZE(right) == 2);
10354 tag = GPTRTAG_DATA;
10357 case CPOINTER: /* __code */
10358 assert (AOP_SIZE(right) == 2);
10359 tag = GPTRTAG_CODE;
10362 case GPOINTER: /* unknown destination, __data or __code */
10363 /* assume __data space (address of immediate) */
10364 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10365 if (AOP(right)->code)
10366 tag = GPTRTAG_CODE;
10368 tag = GPTRTAG_DATA;
10372 assert (!"unhandled pointer type");
10375 /* convert other values into pointers to __data space */
10376 tag = GPTRTAG_DATA;
10379 assert (AOP_SIZE(result) == 3);
10381 emitpcode(POC_CLRF, popGet(AOP(result), 2));
10383 emitpcode(POC_MOVLW, popGetLit(tag));
10384 movwf(AOP(result), 2);
10387 addSign(result, max, 0);
10392 /* if they are the same size : or less */
10393 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10395 /* if they are in the same place */
10396 if (pic14_sameRegs(AOP(right),AOP(result)))
10399 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10400 if (IS_PTR_CONST(rtype))
10401 DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10402 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10403 DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10405 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10406 emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10407 emitpcode(POC_MOVWF, popGet(AOP(result),0));
10408 emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10409 emitpcode(POC_MOVWF, popGet(AOP(result),1));
10410 if(AOP_SIZE(result) <2)
10411 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10415 /* if they in different places then copy */
10416 size = AOP_SIZE(result);
10419 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10420 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10422 //aopPut(AOP(result),
10423 // aopGet(AOP(right),offset,FALSE,FALSE),
10432 /* so we now know that the size of destination is greater
10433 than the size of the source.
10434 Now, if the next iCode is an operator then we might be
10435 able to optimize the operation without performing a cast.
10437 if(0 && genMixedOperation(ic)) {
10438 /* XXX: cannot optimize: must copy regs! */
10442 /* we move to result for the size of source */
10443 size = AOP_SIZE(right);
10446 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10447 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10451 addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10454 freeAsmop(right,NULL,ic,TRUE);
10455 freeAsmop(result,NULL,ic,TRUE);
10459 /*-----------------------------------------------------------------*/
10460 /* genDjnz - generate decrement & jump if not zero instrucion */
10461 /*-----------------------------------------------------------------*/
10462 static int genDjnz (iCode *ic, iCode *ifx)
10464 symbol *lbl, *lbl1;
10466 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10471 /* if the if condition has a false label
10472 then we cannot save */
10476 /* if the minus is not of the form
10478 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10479 !IS_OP_LITERAL(IC_RIGHT(ic)))
10482 if (operandLitValue(IC_RIGHT(ic)) != 1)
10485 /* if the size of this greater than one then no
10487 if (getSize(operandType(IC_RESULT(ic))) > 1)
10490 /* otherwise we can save BIG */
10491 lbl = newiTempLabel(NULL);
10492 lbl1= newiTempLabel(NULL);
10494 aopOp(IC_RESULT(ic),ic,FALSE);
10496 if (IS_AOP_PREG(IC_RESULT(ic))) {
10497 pic14_emitcode("dec","%s",
10498 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10499 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10500 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10504 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10505 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10507 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10508 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10511 /* pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10512 /* pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10513 /* pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10514 /* pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10517 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10518 ifx->generated = 1;
10522 /*-----------------------------------------------------------------*/
10523 /* genReceive - generate code for a receive iCode */
10524 /*-----------------------------------------------------------------*/
10525 static void genReceive (iCode *ic)
10528 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10530 if (isOperandInFarSpace(IC_RESULT(ic)) &&
10531 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10532 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10534 int size = getSize(operandType(IC_RESULT(ic)));
10535 int offset = fReturnSizePic - size;
10537 pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10538 fReturn[fReturnSizePic - offset - 1] : "acc"));
10541 aopOp(IC_RESULT(ic),ic,FALSE);
10542 size = AOP_SIZE(IC_RESULT(ic));
10545 pic14_emitcode ("pop","acc");
10546 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10551 aopOp(IC_RESULT(ic),ic,FALSE);
10553 assignResultValue(IC_RESULT(ic));
10556 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10559 /*-----------------------------------------------------------------*/
10560 /* genDummyRead - generate code for dummy read of volatiles */
10561 /*-----------------------------------------------------------------*/
10563 genDummyRead (iCode * ic)
10566 pic14_emitcode ("; genDummyRead","");
10567 pic14_emitcode ("; not implemented","");
10572 /*-----------------------------------------------------------------*/
10573 /* genpic14Code - generate code for pic14 based controllers */
10574 /*-----------------------------------------------------------------*/
10576 * At this point, ralloc.c has gone through the iCode and attempted
10577 * to optimize in a way suitable for a PIC. Now we've got to generate
10578 * PIC instructions that correspond to the iCode.
10580 * Once the instructions are generated, we'll pass through both the
10581 * peep hole optimizer and the pCode optimizer.
10582 *-----------------------------------------------------------------*/
10584 void genpic14Code (iCode *lic)
10591 lineHead = lineCurr = NULL;
10593 pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10596 /* if debug information required */
10597 if (options.debug && currFunc) {
10599 debugFile->writeFunction (currFunc, lic);
10604 for (ic = lic ; ic ; ic = ic->next ) {
10606 //DEBUGpic14_emitcode(";ic","");
10607 //fprintf (stderr, "in ic loop\n");
10608 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10609 //ic->lineno, printCLine(ic->filename, ic->lineno));
10611 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10613 //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10614 cline = printCLine (ic->filename, ic->lineno);
10615 if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10616 addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10617 //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10620 if (options.iCodeInAsm) {
10621 emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10623 /* if the result is marked as
10624 spilt and rematerializable or code for
10625 this has already been generated then
10627 if (resultRemat(ic) || ic->generated )
10630 /* depending on the operation */
10649 /* IPOP happens only when trying to restore a
10650 spilt live range, if there is an ifx statement
10651 following this pop then the if statement might
10652 be using some of the registers being popped which
10653 would destory the contents of the register so
10654 we need to check for this condition and handle it */
10656 ic->next->op == IFX &&
10657 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10658 genIfx (ic->next,ic);
10676 genEndFunction (ic);
10696 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10713 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
10717 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10724 /* note these two are xlated by algebraic equivalence
10725 during parsing SDCC.y */
10726 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10727 "got '>=' or '<=' shouldn't have come here");
10731 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10743 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10747 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10751 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10775 genRightShift (ic);
10778 case GET_VALUE_AT_ADDRESS:
10783 if (POINTER_SET(ic))
10810 addSet(&_G.sendSet,ic);
10813 case DUMMY_READ_VOLATILE:
10818 fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10825 /* now we are ready to call the
10826 peep hole optimizer */
10827 if (!options.nopeep) {
10828 peepHole (&lineHead);
10830 /* now do the actual printing */
10831 printLine (lineHead,codeOutFile);
10834 DFPRINTF((stderr,"printing pBlock\n\n"));
10835 printpBlock(stdout,pb);
10841 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10842 * (meaning: representing its own address) or not (referencing its contents).
10843 * This can only be decided based on the operand's type. */
10845 aop_isLitLike (asmop *aop)
10848 if (aop->type == AOP_LIT) return 1;
10849 if (aop->type == AOP_IMMD) return 1;
10850 if ((aop->type == AOP_PCODE) &&
10851 ((aop->aopu.pcop->type == PO_LITERAL)))
10853 /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10854 * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10861 op_isLitLike (operand *op)
10864 if (aop_isLitLike (AOP(op))) return 1;
10865 if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10866 if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;