1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
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)
9 This program is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 In other words, you are welcome to use, share and improve this program.
24 You are forbidden to forbid anyone else to use, share and improve
25 what you give them. Help stamp out software-hoarding!
28 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
29 Made everything static
30 -------------------------------------------------------------------------*/
36 #include "SDCCglobl.h"
39 #ifdef HAVE_SYS_ISA_DEFS_H
40 #include <sys/isa_defs.h>
42 #ifdef HAVE_MACHINE_ENDIAN_H
43 #include <machine/endian.h>
48 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
49 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
50 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
57 #include "SDCCpeeph.h"
63 static int labelOffset=0;
64 static int debug_verbose=1;
65 static int optimized_for_speed = 0;
67 /* max_key keeps track of the largest label number used in
68 a function. This is then used to adjust the label offset
69 for the next function.
72 static int GpsuedoStkPtr=0;
74 unsigned int pic14aopLiteral (value *val, int offset);
75 const char *AopType(short type);
76 static iCode *ifxForOp ( operand *op, iCode *ic );
78 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
80 /* this is the down and dirty file with all kinds of
81 kludgy & hacky stuff. This is what it is all about
82 CODE GENERATION for a specific MCU . some of the
83 routines may be reusable, will have to see */
85 static char *zero = "#0x00";
86 static char *one = "#0x01";
87 static char *spname = "sp";
89 char *fReturnpic14[] = {"FSR","dph","b","a" };
90 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
91 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
92 static char **fReturn = fReturnpic14;
94 static char *accUse[] = {"a","b"};
96 //static short rbank = -1;
108 /* Resolved ifx structure. This structure stores information
109 about an iCode ifx that makes it easier to generate code.
111 typedef struct resolvedIfx {
112 symbol *lbl; /* pointer to a label */
113 int condition; /* true or false ifx */
114 int generated; /* set true when the code associated with the ifx
118 extern int pic14_ptrRegReq ;
119 extern int pic14_nRegs;
120 extern FILE *codeOutFile;
121 static void saverbank (int, iCode *,bool);
123 static lineNode *lineHead = NULL;
124 static lineNode *lineCurr = NULL;
126 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
127 0xE0, 0xC0, 0x80, 0x00};
128 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
129 0x07, 0x03, 0x01, 0x00};
133 /*-----------------------------------------------------------------*/
134 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
135 /* exponent of 2 is returned, otherwise -1 is */
137 /* note that this is similar to the function `powof2' in SDCCsymt */
141 /*-----------------------------------------------------------------*/
142 static int my_powof2 (unsigned long num)
145 if( (num & (num-1)) == 0) {
158 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
161 DEBUGpic14_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
163 ((result) ? AopType(AOP_TYPE(result)) : "-"),
164 ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
165 ((left) ? AopType(AOP_TYPE(left)) : "-"),
166 ((left) ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
167 ((right) ? AopType(AOP_TYPE(right)) : "-"),
168 ((right) ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
169 ((result) ? AOP_SIZE(result) : 0));
173 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
176 char lb[INITIAL_INLINEASM];
186 sprintf(lb,"%s\t",inst);
188 sprintf(lb,"%s",inst);
189 vsprintf(lb+(strlen(lb)),fmt,ap);
193 while (isspace(*lbp)) lbp++;
196 lineCurr = (lineCurr ?
197 connectLine(lineCurr,newLineNode(lb)) :
198 (lineHead = newLineNode(lb)));
199 lineCurr->isInline = _G.inLine;
200 lineCurr->isDebug = _G.debugLine;
202 addpCode2pBlock(pb,newpCodeCharP(lb));
208 static void emitpLabel(int key)
210 addpCode2pBlock(pb,newpCodeLabel(key+100+labelOffset));
213 void emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
217 addpCode2pBlock(pb,newpCode(poc,pcop));
219 DEBUGpic14_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
222 void emitpcodeNULLop(PIC_OPCODE poc)
225 addpCode2pBlock(pb,newpCode(poc,NULL));
229 /*-----------------------------------------------------------------*/
230 /* pic14_emitcode - writes the code into a file : for now it is simple */
231 /*-----------------------------------------------------------------*/
232 void pic14_emitcode (char *inst,char *fmt, ...)
235 char lb[INITIAL_INLINEASM];
242 sprintf(lb,"%s\t",inst);
244 sprintf(lb,"%s",inst);
245 vsprintf(lb+(strlen(lb)),fmt,ap);
249 while (isspace(*lbp)) lbp++;
252 lineCurr = (lineCurr ?
253 connectLine(lineCurr,newLineNode(lb)) :
254 (lineHead = newLineNode(lb)));
255 lineCurr->isInline = _G.inLine;
256 lineCurr->isDebug = _G.debugLine;
259 addpCode2pBlock(pb,newpCodeCharP(lb));
265 /*-----------------------------------------------------------------*/
266 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
267 /*-----------------------------------------------------------------*/
268 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
270 bool r0iu = FALSE , r1iu = FALSE;
271 bool r0ou = FALSE , r1ou = FALSE;
273 /* the logic: if r0 & r1 used in the instruction
274 then we are in trouble otherwise */
276 /* first check if r0 & r1 are used by this
277 instruction, in which case we are in trouble */
278 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
279 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
284 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
285 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
287 /* if no usage of r0 then return it */
288 if (!r0iu && !r0ou) {
289 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
290 (*aopp)->type = AOP_R0;
292 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
295 /* if no usage of r1 then return it */
296 if (!r1iu && !r1ou) {
297 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
298 (*aopp)->type = AOP_R1;
300 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
303 /* now we know they both have usage */
304 /* if r0 not used in this instruction */
306 /* push it if not already pushed */
308 pic14_emitcode ("push","%s",
309 pic14_regWithIdx(R0_IDX)->dname);
313 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
314 (*aopp)->type = AOP_R0;
316 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
319 /* if r1 not used then */
322 /* push it if not already pushed */
324 pic14_emitcode ("push","%s",
325 pic14_regWithIdx(R1_IDX)->dname);
329 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
330 (*aopp)->type = AOP_R1;
331 return pic14_regWithIdx(R1_IDX);
335 /* I said end of world but not quite end of world yet */
336 /* if this is a result then we can push it on the stack*/
338 (*aopp)->type = AOP_STK;
342 /* other wise this is true end of the world */
343 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
344 "getFreePtr should never reach here");
348 /*-----------------------------------------------------------------*/
349 /* newAsmop - creates a new asmOp */
350 /*-----------------------------------------------------------------*/
351 asmop *newAsmop (short type)
355 aop = Safe_calloc(1,sizeof(asmop));
360 static void genSetDPTR(int n)
364 pic14_emitcode(";", "Select standard DPTR");
365 pic14_emitcode("mov", "dps, #0x00");
369 pic14_emitcode(";", "Select alternate DPTR");
370 pic14_emitcode("mov", "dps, #0x01");
374 /*-----------------------------------------------------------------*/
375 /* resolveIfx - converts an iCode ifx into a form more useful for */
376 /* generating code */
377 /*-----------------------------------------------------------------*/
378 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
383 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
385 resIfx->condition = 1; /* assume that the ifx is true */
386 resIfx->generated = 0; /* indicate that the ifx has not been used */
389 resIfx->lbl = newiTempLabel(NULL); /* oops, there is no ifx. so create a label */
390 DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
391 __FUNCTION__,__LINE__,resIfx->lbl->key);
394 resIfx->lbl = IC_TRUE(ifx);
396 resIfx->lbl = IC_FALSE(ifx);
397 resIfx->condition = 0;
400 DEBUGpic14_emitcode("; ***","ifx true is non-null");
402 DEBUGpic14_emitcode("; ***","ifx false is non-null");
405 DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
408 /*-----------------------------------------------------------------*/
409 /* pointerCode - returns the code for a pointer type */
410 /*-----------------------------------------------------------------*/
411 static int pointerCode (sym_link *etype)
414 return PTR_TYPE(SPEC_OCLS(etype));
418 /*-----------------------------------------------------------------*/
419 /* aopForSym - for a true symbol */
420 /*-----------------------------------------------------------------*/
421 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
424 memmap *space= SPEC_OCLS(sym->etype);
426 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
427 /* if already has one */
431 /* assign depending on the storage class */
432 /* if it is on the stack or indirectly addressable */
433 /* space we need to assign either r0 or r1 to it */
434 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
435 sym->aop = aop = newAsmop(0);
436 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
437 aop->size = getSize(sym->type);
439 /* now assign the address of the variable to
440 the pointer register */
441 if (aop->type != AOP_STK) {
445 pic14_emitcode("push","acc");
447 pic14_emitcode("mov","a,_bp");
448 pic14_emitcode("add","a,#0x%02x",
450 ((char)(sym->stack - _G.nRegsSaved )) :
451 ((char)sym->stack)) & 0xff);
452 pic14_emitcode("mov","%s,a",
453 aop->aopu.aop_ptr->name);
456 pic14_emitcode("pop","acc");
458 pic14_emitcode("mov","%s,#%s",
459 aop->aopu.aop_ptr->name,
461 aop->paged = space->paged;
463 aop->aopu.aop_stk = sym->stack;
467 if (sym->onStack && options.stack10bit)
469 /* It's on the 10 bit stack, which is located in
473 //DEBUGpic14_emitcode(";","%d",__LINE__);
476 pic14_emitcode("push","acc");
478 pic14_emitcode("mov","a,_bp");
479 pic14_emitcode("add","a,#0x%02x",
481 ((char)(sym->stack - _G.nRegsSaved )) :
482 ((char)sym->stack)) & 0xff);
485 pic14_emitcode ("mov","dpx1,#0x40");
486 pic14_emitcode ("mov","dph1,#0x00");
487 pic14_emitcode ("mov","dpl1, a");
491 pic14_emitcode("pop","acc");
493 sym->aop = aop = newAsmop(AOP_DPTR2);
494 aop->size = getSize(sym->type);
498 //DEBUGpic14_emitcode(";","%d",__LINE__);
499 /* if in bit space */
500 if (IN_BITSPACE(space)) {
501 sym->aop = aop = newAsmop (AOP_CRY);
502 aop->aopu.aop_dir = sym->rname ;
503 aop->size = getSize(sym->type);
504 //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
507 /* if it is in direct space */
508 if (IN_DIRSPACE(space)) {
509 sym->aop = aop = newAsmop (AOP_DIR);
510 aop->aopu.aop_dir = sym->rname ;
511 aop->size = getSize(sym->type);
512 DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
516 /* special case for a function */
517 if (IS_FUNC(sym->type)) {
518 sym->aop = aop = newAsmop(AOP_IMMD);
519 //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
520 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
521 strcpy(aop->aopu.aop_immd,sym->rname);
522 aop->size = FPTRSIZE;
527 /* only remaining is far space */
528 /* in which case DPTR gets the address */
529 sym->aop = aop = newAsmop(AOP_DPTR);
530 pic14_emitcode ("mov","dptr,#%s", sym->rname);
531 aop->size = getSize(sym->type);
533 DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
534 /* if it is in code space */
535 if (IN_CODESPACE(space))
541 /*-----------------------------------------------------------------*/
542 /* aopForRemat - rematerialzes an object */
543 /*-----------------------------------------------------------------*/
544 static asmop *aopForRemat (symbol *sym)
546 iCode *ic = sym->rematiCode;
547 asmop *aop = newAsmop(AOP_IMMD);
549 DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
552 val += (int) operandLitValue(IC_RIGHT(ic));
553 else if (ic->op == '-')
554 val -= (int) operandLitValue(IC_RIGHT(ic));
558 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
562 sprintf(buffer,"(%s %c 0x%04x)",
563 OP_SYMBOL(IC_LEFT(ic))->rname,
564 val >= 0 ? '+' : '-',
567 strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
569 //DEBUGpic14_emitcode(";","%s",buffer);
570 aop->aopu.aop_immd = Safe_calloc(1,strlen(buffer)+1);
571 strcpy(aop->aopu.aop_immd,buffer);
575 int aopIdx (asmop *aop, int offset)
580 if(aop->type != AOP_REG)
583 return aop->aopu.aop_reg[offset]->rIdx;
586 /*-----------------------------------------------------------------*/
587 /* regsInCommon - two operands have some registers in common */
588 /*-----------------------------------------------------------------*/
589 static bool regsInCommon (operand *op1, operand *op2)
594 /* if they have registers in common */
595 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
598 sym1 = OP_SYMBOL(op1);
599 sym2 = OP_SYMBOL(op2);
601 if (sym1->nRegs == 0 || sym2->nRegs == 0)
604 for (i = 0 ; i < sym1->nRegs ; i++) {
609 for (j = 0 ; j < sym2->nRegs ;j++ ) {
613 if (sym2->regs[j] == sym1->regs[i])
621 /*-----------------------------------------------------------------*/
622 /* operandsEqu - equivalent */
623 /*-----------------------------------------------------------------*/
624 static bool operandsEqu ( operand *op1, operand *op2)
628 /* if they not symbols */
629 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
632 sym1 = OP_SYMBOL(op1);
633 sym2 = OP_SYMBOL(op2);
635 /* if both are itemps & one is spilt
636 and the other is not then false */
637 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
638 sym1->isspilt != sym2->isspilt )
641 /* if they are the same */
645 if (strcmp(sym1->rname,sym2->rname) == 0)
649 /* if left is a tmp & right is not */
653 (sym1->usl.spillLoc == sym2))
660 (sym2->usl.spillLoc == sym1))
666 /*-----------------------------------------------------------------*/
667 /* pic14_sameRegs - two asmops have the same registers */
668 /*-----------------------------------------------------------------*/
669 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
676 if (aop1->type != AOP_REG ||
677 aop2->type != AOP_REG )
680 if (aop1->size != aop2->size )
683 for (i = 0 ; i < aop1->size ; i++ )
684 if (aop1->aopu.aop_reg[i] !=
685 aop2->aopu.aop_reg[i] )
691 /*-----------------------------------------------------------------*/
692 /* aopOp - allocates an asmop for an operand : */
693 /*-----------------------------------------------------------------*/
694 void aopOp (operand *op, iCode *ic, bool result)
703 // DEBUGpic14_emitcode(";","%d",__LINE__);
704 /* if this a literal */
705 if (IS_OP_LITERAL(op)) {
706 op->aop = aop = newAsmop(AOP_LIT);
707 aop->aopu.aop_lit = op->operand.valOperand;
708 aop->size = getSize(operandType(op));
712 /* if already has a asmop then continue */
716 /* if the underlying symbol has a aop */
717 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
718 DEBUGpic14_emitcode(";","%d",__LINE__);
719 op->aop = OP_SYMBOL(op)->aop;
723 /* if this is a true symbol */
724 if (IS_TRUE_SYMOP(op)) {
725 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
726 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
730 /* this is a temporary : this has
736 e) can be a return use only */
741 /* if the type is a conditional */
742 if (sym->regType == REG_CND) {
743 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
748 /* if it is spilt then two situations
750 b) has a spill location */
751 if (sym->isspilt || sym->nRegs == 0) {
753 DEBUGpic14_emitcode(";","%d",__LINE__);
754 /* rematerialize it NOW */
756 sym->aop = op->aop = aop =
758 aop->size = getSize(sym->type);
764 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
765 aop->size = getSize(sym->type);
766 for ( i = 0 ; i < 2 ; i++ )
767 aop->aopu.aop_str[i] = accUse[i];
768 DEBUGpic14_emitcode(";","%d",__LINE__);
774 aop = op->aop = sym->aop = newAsmop(AOP_STR);
775 aop->size = getSize(sym->type);
776 for ( i = 0 ; i < fReturnSizePic ; i++ )
777 aop->aopu.aop_str[i] = fReturn[i];
778 DEBUGpic14_emitcode(";","%d",__LINE__);
782 /* else spill location */
783 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
784 /* force a new aop if sizes differ */
785 sym->usl.spillLoc->aop = NULL;
787 DEBUGpic14_emitcode(";","%s %d %s",__FUNCTION__,__LINE__,sym->usl.spillLoc->rname);
788 sym->aop = op->aop = aop =
789 aopForSym(ic,sym->usl.spillLoc,result);
790 aop->size = getSize(sym->type);
794 /* must be in a register */
795 sym->aop = op->aop = aop = newAsmop(AOP_REG);
796 aop->size = sym->nRegs;
797 for ( i = 0 ; i < sym->nRegs ;i++)
798 aop->aopu.aop_reg[i] = sym->regs[i];
801 /*-----------------------------------------------------------------*/
802 /* freeAsmop - free up the asmop given to an operand */
803 /*----------------------------------------------------------------*/
804 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
821 /* depending on the asmop type only three cases need work AOP_RO
822 , AOP_R1 && AOP_STK */
828 pic14_emitcode ("pop","ar0");
832 bitVectUnSetBit(ic->rUsed,R0_IDX);
838 pic14_emitcode ("pop","ar1");
842 bitVectUnSetBit(ic->rUsed,R1_IDX);
848 int stk = aop->aopu.aop_stk + aop->size;
849 bitVectUnSetBit(ic->rUsed,R0_IDX);
850 bitVectUnSetBit(ic->rUsed,R1_IDX);
852 getFreePtr(ic,&aop,FALSE);
854 if (options.stack10bit)
856 /* I'm not sure what to do here yet... */
859 "*** Warning: probably generating bad code for "
860 "10 bit stack mode.\n");
864 pic14_emitcode ("mov","a,_bp");
865 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
866 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
868 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
872 pic14_emitcode("pop","acc");
873 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
875 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
878 freeAsmop(op,NULL,ic,TRUE);
880 pic14_emitcode("pop","ar0");
885 pic14_emitcode("pop","ar1");
893 /* all other cases just dealloc */
897 OP_SYMBOL(op)->aop = NULL;
898 /* if the symbol has a spill */
900 SPIL_LOC(op)->aop = NULL;
905 /*-----------------------------------------------------------------*/
906 /* aopGet - for fetching value of the aop */
907 /*-----------------------------------------------------------------*/
908 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
913 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
914 /* offset is greater than
916 if (offset > (aop->size - 1) &&
917 aop->type != AOP_LIT)
920 /* depending on type */
925 DEBUGpic14_emitcode(";","%d",__LINE__);
926 /* if we need to increment it */
927 while (offset > aop->coff) {
928 pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);
932 while (offset < aop->coff) {
933 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
939 pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
940 return (dname ? "acc" : "a");
942 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
943 rs = Safe_calloc(1,strlen(s)+1);
949 DEBUGpic14_emitcode(";","%d",__LINE__);
950 if (aop->type == AOP_DPTR2)
955 while (offset > aop->coff) {
956 pic14_emitcode ("inc","dptr");
960 while (offset < aop->coff) {
961 pic14_emitcode("lcall","__decdptr");
967 pic14_emitcode("clr","a");
968 pic14_emitcode("movc","a,@a+dptr");
971 pic14_emitcode("movx","a,@dptr");
974 if (aop->type == AOP_DPTR2)
979 return (dname ? "acc" : "a");
983 DEBUGpic14_emitcode(";","%d",__LINE__);
985 sprintf (s,"%s",aop->aopu.aop_immd);
988 sprintf(s,"(%s >> %d)",
994 rs = Safe_calloc(1,strlen(s)+1);
1000 sprintf(s,"(%s + %d)",
1004 sprintf(s,"%s",aop->aopu.aop_dir);
1005 rs = Safe_calloc(1,strlen(s)+1);
1011 return aop->aopu.aop_reg[offset]->dname;
1013 return aop->aopu.aop_reg[offset]->name;
1016 //pic14_emitcode(";","%d",__LINE__);
1017 return aop->aopu.aop_dir;
1020 DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1021 return "AOP_accumulator_bug";
1024 sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1025 rs = Safe_calloc(1,strlen(s)+1);
1030 DEBUGpic14_emitcode(";","%d",__LINE__);
1031 aop->coff = offset ;
1032 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1036 return aop->aopu.aop_str[offset];
1040 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1041 "aopget got unsupported aop->type");
1045 /*-----------------------------------------------------------------*/
1046 /* popGetLabel - create a new pCodeOp of type PO_LABEL */
1047 /*-----------------------------------------------------------------*/
1048 pCodeOp *popGetLabel(unsigned int key)
1051 DEBUGpic14_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1056 return newpCodeOpLabel(key+100+labelOffset);
1059 /*-----------------------------------------------------------------*/
1060 /* popCopyReg - copy a pcode operator */
1061 /*-----------------------------------------------------------------*/
1062 pCodeOp *popCopyReg(pCodeOpReg *pc)
1066 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1067 pcor->pcop.type = pc->pcop.type;
1068 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1069 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1071 pcor->rIdx = pc->rIdx;
1073 //DEBUGpic14_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1078 /*-----------------------------------------------------------------*/
1079 /* popCopy - copy a pcode operator */
1080 /*-----------------------------------------------------------------*/
1081 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
1085 pcop = Safe_calloc(1,sizeof(pCodeOpBit) );
1086 pcop->type = PO_BIT;
1087 if(!(pcop->name = Safe_strdup(pc->name)))
1088 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1089 ((pCodeOpBit *)pcop)->bit = bitval;
1091 ((pCodeOpBit *)pcop)->inBitSpace = 0; //(pc->type == PO_BIT) ? 1 : 0;
1096 /*-----------------------------------------------------------------*/
1097 /* popGet - asm operator to pcode operator conversion */
1098 /*-----------------------------------------------------------------*/
1099 pCodeOp *popGetLit(unsigned int lit)
1102 return newpCodeOpLit(lit);
1106 /*-----------------------------------------------------------------*/
1107 /* popGet - asm operator to pcode operator conversion */
1108 /*-----------------------------------------------------------------*/
1109 pCodeOp *popGetWithString(char *str)
1115 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1119 pcop = newpCodeOp(str,PO_STR);
1124 pCodeOp *popRegFromString(char *str)
1127 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1128 pcop->type = PO_GPR_REGISTER;
1130 PCOR(pcop)->rIdx = -1;
1131 PCOR(pcop)->r = NULL;
1133 DEBUGpic14_emitcode(";","%d",__LINE__);
1134 pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1139 pCodeOp *popRegFromIdx(int rIdx)
1143 DEBUGpic14_emitcode ("; ***","%s,%d , rIdx=0x%x",
1144 __FUNCTION__,__LINE__,rIdx);
1146 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1148 PCOR(pcop)->rIdx = rIdx;
1149 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1150 PCOR(pcop)->r->isFree = 0;
1151 PCOR(pcop)->r->wasUsed = 1;
1153 pcop->type = PCOR(pcop)->r->pc_type;
1158 /*-----------------------------------------------------------------*/
1159 /* popGet - asm operator to pcode operator conversion */
1160 /*-----------------------------------------------------------------*/
1161 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1168 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1169 /* offset is greater than
1172 if (offset > (aop->size - 1) &&
1173 aop->type != AOP_LIT)
1174 return NULL; //zero;
1176 /* depending on type */
1177 switch (aop->type) {
1184 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1185 //pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1186 //pcop->type = PO_SFR_REGISTER;
1188 //PCOR(pcop)->rIdx = -1;
1189 //PCOR(pcop)->r = NULL;
1190 // Really nasty hack to check for temporary registers
1192 //pcop->name = Safe_strdup("BAD_REGISTER");
1197 DEBUGpic14_emitcode(";","%d",__LINE__);
1198 pcop = Safe_calloc(1,sizeof(pCodeOp) );
1199 pcop->type = PO_IMMEDIATE;
1201 // sprintf (s,"%s",aop->aopu.aop_immd);
1204 sprintf(s,"(%s >> %d)",
1209 aop->aopu.aop_immd);
1210 pcop->name = Safe_calloc(1,strlen(s)+1);
1211 strcpy(pcop->name,s);
1215 pcop = Safe_calloc(1,sizeof(pCodeOp) );
1216 pcop->type = PO_DIR;
1218 sprintf(s,"(%s + %d)",
1222 sprintf(s,"%s",aop->aopu.aop_dir);
1223 pcop->name = Safe_calloc(1,strlen(s)+1);
1224 strcpy(pcop->name,s);
1229 int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1231 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1232 PCOR(pcop)->rIdx = rIdx;
1233 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1234 pcop->type = PCOR(pcop)->r->pc_type;
1235 rs = aop->aopu.aop_reg[offset]->name;
1236 //DEBUGpic14_emitcode(";","%d regiser idx = %d name =%s",__LINE__,rIdx,rs);
1241 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1245 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1248 DEBUGpic14_emitcode(";","%d",__LINE__);
1250 pcop = Safe_calloc(1,sizeof(pCodeOp) );
1251 pcop->type = PO_STR;
1253 //aop->coff = offset ;
1254 //if (strcmp(aop->aopu.aop_str[offset],"a") == 0 && dname)
1255 // sprintf(s,"%s","acc");
1257 sprintf(s,"%s",aop->aopu.aop_str[offset]);
1258 pcop->name = Safe_calloc(1,strlen(s)+1);
1259 strcpy(pcop->name,s);
1264 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1265 "popGet got unsupported aop->type");
1268 /*-----------------------------------------------------------------*/
1269 /* aopPut - puts a string for a aop */
1270 /*-----------------------------------------------------------------*/
1271 void aopPut (asmop *aop, char *s, int offset)
1276 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1278 if (aop->size && offset > ( aop->size - 1)) {
1279 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1280 "aopPut got offset > aop->size");
1284 /* will assign value to value */
1285 /* depending on where it is ofcourse */
1286 switch (aop->type) {
1289 sprintf(d,"(%s + %d)",
1290 aop->aopu.aop_dir,offset);
1292 sprintf(d,"%s",aop->aopu.aop_dir);
1295 DEBUGpic14_emitcode(";","%d",__LINE__);
1297 pic14_emitcode("movf","%s,w",s);
1298 pic14_emitcode("movwf","%s",d);
1301 pic14_emitcode(";BUG! should have this:movf","%s,w %d",s,__LINE__);
1302 emitpcode(POC_MOVWF,popGet(aop,offset));
1309 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
1310 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1313 strcmp(s,"r0") == 0 ||
1314 strcmp(s,"r1") == 0 ||
1315 strcmp(s,"r2") == 0 ||
1316 strcmp(s,"r3") == 0 ||
1317 strcmp(s,"r4") == 0 ||
1318 strcmp(s,"r5") == 0 ||
1319 strcmp(s,"r6") == 0 ||
1320 strcmp(s,"r7") == 0 )
1321 pic14_emitcode("mov","%s,%s ; %d",
1322 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1327 pic14_emitcode("movf","%s,w ; %d",s,__LINE__);
1329 pic14_emitcode("movwf","%s",
1330 aop->aopu.aop_reg[offset]->name);
1333 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1334 pcop->type = PO_GPR_REGISTER;
1336 PCOR(pcop)->rIdx = -1;
1337 PCOR(pcop)->r = NULL;
1339 DEBUGpic14_emitcode(";","%d",__LINE__);
1340 pcop->name = Safe_strdup(s);
1341 emitpcode(POC_MOVFW,pcop);
1343 emitpcode(POC_MOVWF,popGet(aop,offset));
1351 if (aop->type == AOP_DPTR2)
1357 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1358 "aopPut writting to code space");
1362 while (offset > aop->coff) {
1364 pic14_emitcode ("inc","dptr");
1367 while (offset < aop->coff) {
1369 pic14_emitcode("lcall","__decdptr");
1374 /* if not in accumulater */
1377 pic14_emitcode ("movx","@dptr,a");
1379 if (aop->type == AOP_DPTR2)
1387 while (offset > aop->coff) {
1389 pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1391 while (offset < aop->coff) {
1393 pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1399 pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1404 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1406 if (strcmp(s,"r0") == 0 ||
1407 strcmp(s,"r1") == 0 ||
1408 strcmp(s,"r2") == 0 ||
1409 strcmp(s,"r3") == 0 ||
1410 strcmp(s,"r4") == 0 ||
1411 strcmp(s,"r5") == 0 ||
1412 strcmp(s,"r6") == 0 ||
1413 strcmp(s,"r7") == 0 ) {
1415 sprintf(buffer,"a%s",s);
1416 pic14_emitcode("mov","@%s,%s",
1417 aop->aopu.aop_ptr->name,buffer);
1419 pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1424 if (strcmp(s,"a") == 0)
1425 pic14_emitcode("push","acc");
1427 pic14_emitcode("push","%s",s);
1432 /* if bit variable */
1433 if (!aop->aopu.aop_dir) {
1434 pic14_emitcode("clr","a");
1435 pic14_emitcode("rlc","a");
1438 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1441 pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1444 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1446 lbl = newiTempLabel(NULL);
1448 if (strcmp(s,"a")) {
1451 pic14_emitcode("clr","c");
1452 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1453 pic14_emitcode("cpl","c");
1454 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1455 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1462 if (strcmp(aop->aopu.aop_str[offset],s))
1463 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1468 if (!offset && (strcmp(s,"acc") == 0))
1471 if (strcmp(aop->aopu.aop_str[offset],s))
1472 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1476 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1477 "aopPut got unsupported aop->type");
1483 /*-----------------------------------------------------------------*/
1484 /* reAdjustPreg - points a register back to where it should */
1485 /*-----------------------------------------------------------------*/
1486 static void reAdjustPreg (asmop *aop)
1490 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1492 if ((size = aop->size) <= 1)
1495 switch (aop->type) {
1499 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1503 if (aop->type == AOP_DPTR2)
1509 pic14_emitcode("lcall","__decdptr");
1512 if (aop->type == AOP_DPTR2)
1522 /*-----------------------------------------------------------------*/
1523 /* genNotFloat - generates not for float operations */
1524 /*-----------------------------------------------------------------*/
1525 static void genNotFloat (operand *op, operand *res)
1531 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1532 /* we will put 127 in the first byte of
1534 aopPut(AOP(res),"#127",0);
1535 size = AOP_SIZE(op) - 1;
1538 l = aopGet(op->aop,offset++,FALSE,FALSE);
1542 pic14_emitcode("orl","a,%s",
1544 offset++,FALSE,FALSE));
1546 tlbl = newiTempLabel(NULL);
1548 tlbl = newiTempLabel(NULL);
1549 aopPut(res->aop,one,1);
1550 pic14_emitcode("jz","%05d_DS_",(tlbl->key+100));
1551 aopPut(res->aop,zero,1);
1552 pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
1554 size = res->aop->size - 2;
1556 /* put zeros in the rest */
1558 aopPut(res->aop,zero,offset++);
1562 /*-----------------------------------------------------------------*/
1563 /* opIsGptr: returns non-zero if the passed operand is */
1564 /* a generic pointer type. */
1565 /*-----------------------------------------------------------------*/
1566 static int opIsGptr(operand *op)
1568 sym_link *type = operandType(op);
1570 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1571 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1579 /*-----------------------------------------------------------------*/
1580 /* pic14_getDataSize - get the operand data size */
1581 /*-----------------------------------------------------------------*/
1582 int pic14_getDataSize(operand *op)
1584 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1587 return AOP_SIZE(op);
1589 // tsd- in the pic port, the genptr size is 1, so this code here
1590 // fails. ( in the 8051 port, the size was 4).
1593 size = AOP_SIZE(op);
1594 if (size == GPTRSIZE)
1596 sym_link *type = operandType(op);
1597 if (IS_GENPTR(type))
1599 /* generic pointer; arithmetic operations
1600 * should ignore the high byte (pointer type).
1603 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1610 /*-----------------------------------------------------------------*/
1611 /* pic14_outAcc - output Acc */
1612 /*-----------------------------------------------------------------*/
1613 void pic14_outAcc(operand *result)
1616 DEBUGpic14_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
1617 DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1620 size = pic14_getDataSize(result);
1622 emitpcode(POC_MOVWF,popGet(AOP(result),0));
1625 /* unsigned or positive */
1627 emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1632 /*-----------------------------------------------------------------*/
1633 /* pic14_outBitC - output a bit C */
1634 /*-----------------------------------------------------------------*/
1635 void pic14_outBitC(operand *result)
1638 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1639 /* if the result is bit */
1640 if (AOP_TYPE(result) == AOP_CRY)
1641 aopPut(AOP(result),"c",0);
1643 pic14_emitcode("clr","a ; %d", __LINE__);
1644 pic14_emitcode("rlc","a");
1645 pic14_outAcc(result);
1649 /*-----------------------------------------------------------------*/
1650 /* pic14_toBoolean - emit code for orl a,operator(sizeop) */
1651 /*-----------------------------------------------------------------*/
1652 void pic14_toBoolean(operand *oper)
1654 int size = AOP_SIZE(oper) - 1;
1657 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1659 if ( AOP_TYPE(oper) != AOP_ACC) {
1660 emitpcode(POC_MOVFW,popGet(AOP(oper),0));
1663 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
1668 /*-----------------------------------------------------------------*/
1669 /* genNot - generate code for ! operation */
1670 /*-----------------------------------------------------------------*/
1671 static void genNot (iCode *ic)
1674 sym_link *optype = operandType(IC_LEFT(ic));
1677 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1678 /* assign asmOps to operand & result */
1679 aopOp (IC_LEFT(ic),ic,FALSE);
1680 aopOp (IC_RESULT(ic),ic,TRUE);
1682 DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1683 /* if in bit space then a special case */
1684 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1685 pic14_emitcode("movlw","1<<%s");
1686 //pic14_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1687 //pic14_emitcode("cpl","c");
1688 //pic14_outBitC(IC_RESULT(ic));
1692 /* if type float then do float */
1693 if (IS_FLOAT(optype)) {
1694 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1698 size = AOP_SIZE(IC_RESULT(ic));
1700 emitpcode(POC_COMFW,popGet(AOP(IC_LEFT(ic)),0));
1701 emitpcode(POC_ANDLW,popGetLit(1));
1702 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
1705 pic14_toBoolean(IC_LEFT(ic));
1707 tlbl = newiTempLabel(NULL);
1708 pic14_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1709 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
1710 pic14_outBitC(IC_RESULT(ic));
1713 /* release the aops */
1714 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1715 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1719 /*-----------------------------------------------------------------*/
1720 /* genCpl - generate code for complement */
1721 /*-----------------------------------------------------------------*/
1722 static void genCpl (iCode *ic)
1728 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1729 /* assign asmOps to operand & result */
1730 aopOp (IC_LEFT(ic),ic,FALSE);
1731 aopOp (IC_RESULT(ic),ic,TRUE);
1733 /* if both are in bit space then
1735 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1736 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1738 pic14_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1739 pic14_emitcode("cpl","c");
1740 pic14_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1744 size = AOP_SIZE(IC_RESULT(ic));
1746 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1748 pic14_emitcode("cpl","a");
1749 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1754 /* release the aops */
1755 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1756 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1759 /*-----------------------------------------------------------------*/
1760 /* genUminusFloat - unary minus for floating points */
1761 /*-----------------------------------------------------------------*/
1762 static void genUminusFloat(operand *op,operand *result)
1764 int size ,offset =0 ;
1767 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1768 /* for this we just need to flip the
1769 first it then copy the rest in place */
1770 size = AOP_SIZE(op) - 1;
1771 l = aopGet(AOP(op),3,FALSE,FALSE);
1775 pic14_emitcode("cpl","acc.7");
1776 aopPut(AOP(result),"a",3);
1780 aopGet(AOP(op),offset,FALSE,FALSE),
1786 /*-----------------------------------------------------------------*/
1787 /* genUminus - unary minus code generation */
1788 /*-----------------------------------------------------------------*/
1789 static void genUminus (iCode *ic)
1792 sym_link *optype, *rtype;
1795 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1797 aopOp(IC_LEFT(ic),ic,FALSE);
1798 aopOp(IC_RESULT(ic),ic,TRUE);
1800 /* if both in bit space then special
1802 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1803 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1805 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0));
1806 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
1807 emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0));
1812 optype = operandType(IC_LEFT(ic));
1813 rtype = operandType(IC_RESULT(ic));
1815 /* if float then do float stuff */
1816 if (IS_FLOAT(optype)) {
1817 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1821 /* otherwise subtract from zero by taking the 2's complement */
1822 size = AOP_SIZE(IC_LEFT(ic));
1824 for(i=0; i<size; i++) {
1825 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
1826 emitpcode(POC_COMF, popGet(AOP(IC_LEFT(ic)),i));
1828 emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
1829 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
1833 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0));
1834 for(i=1; i<size; i++) {
1836 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),i));
1840 /* release the aops */
1841 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1842 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1845 /*-----------------------------------------------------------------*/
1846 /* saveRegisters - will look for a call and save the registers */
1847 /*-----------------------------------------------------------------*/
1848 static void saveRegisters(iCode *lic)
1855 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1857 for (ic = lic ; ic ; ic = ic->next)
1858 if (ic->op == CALL || ic->op == PCALL)
1862 fprintf(stderr,"found parameter push with no function call\n");
1866 /* if the registers have been saved already then
1868 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
1871 /* find the registers in use at this time
1872 and push them away to safety */
1873 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1877 if (options.useXstack) {
1878 if (bitVectBitValue(rsave,R0_IDX))
1879 pic14_emitcode("mov","b,r0");
1880 pic14_emitcode("mov","r0,%s",spname);
1881 for (i = 0 ; i < pic14_nRegs ; i++) {
1882 if (bitVectBitValue(rsave,i)) {
1884 pic14_emitcode("mov","a,b");
1886 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
1887 pic14_emitcode("movx","@r0,a");
1888 pic14_emitcode("inc","r0");
1891 pic14_emitcode("mov","%s,r0",spname);
1892 if (bitVectBitValue(rsave,R0_IDX))
1893 pic14_emitcode("mov","r0,b");
1895 for (i = 0 ; i < pic14_nRegs ; i++) {
1896 if (bitVectBitValue(rsave,i))
1897 pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
1900 dtype = operandType(IC_LEFT(ic));
1901 if (currFunc && dtype &&
1902 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
1903 IFFUNC_ISISR(currFunc->type) &&
1906 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
1909 /*-----------------------------------------------------------------*/
1910 /* unsaveRegisters - pop the pushed registers */
1911 /*-----------------------------------------------------------------*/
1912 static void unsaveRegisters (iCode *ic)
1917 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1918 /* find the registers in use at this time
1919 and push them away to safety */
1920 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1923 if (options.useXstack) {
1924 pic14_emitcode("mov","r0,%s",spname);
1925 for (i = pic14_nRegs ; i >= 0 ; i--) {
1926 if (bitVectBitValue(rsave,i)) {
1927 pic14_emitcode("dec","r0");
1928 pic14_emitcode("movx","a,@r0");
1930 pic14_emitcode("mov","b,a");
1932 pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
1936 pic14_emitcode("mov","%s,r0",spname);
1937 if (bitVectBitValue(rsave,R0_IDX))
1938 pic14_emitcode("mov","r0,b");
1940 for (i = pic14_nRegs ; i >= 0 ; i--) {
1941 if (bitVectBitValue(rsave,i))
1942 pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
1948 /*-----------------------------------------------------------------*/
1950 /*-----------------------------------------------------------------*/
1951 static void pushSide(operand * oper, int size)
1955 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1957 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1958 if (AOP_TYPE(oper) != AOP_REG &&
1959 AOP_TYPE(oper) != AOP_DIR &&
1961 pic14_emitcode("mov","a,%s",l);
1962 pic14_emitcode("push","acc");
1964 pic14_emitcode("push","%s",l);
1969 /*-----------------------------------------------------------------*/
1970 /* assignResultValue - */
1971 /*-----------------------------------------------------------------*/
1972 static void assignResultValue(operand * oper)
1974 int size = AOP_SIZE(oper);
1976 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1978 if(!GpsuedoStkPtr) {
1979 /* The last byte in the assignment is in W */
1981 emitpcode(POC_MOVWF, popGet(AOP(oper),size));
1986 emitpcode(POC_MOVFW,popRegFromIdx(GpsuedoStkPtr-1 + Gstack_base_addr));
1988 emitpcode(POC_MOVWF, popGet(AOP(oper),size));
1993 /*-----------------------------------------------------------------*/
1994 /* genIpush - genrate code for pushing this gets a little complex */
1995 /*-----------------------------------------------------------------*/
1996 static void genIpush (iCode *ic)
1999 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2001 int size, offset = 0 ;
2005 /* if this is not a parm push : ie. it is spill push
2006 and spill push is always done on the local stack */
2007 if (!ic->parmPush) {
2009 /* and the item is spilt then do nothing */
2010 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2013 aopOp(IC_LEFT(ic),ic,FALSE);
2014 size = AOP_SIZE(IC_LEFT(ic));
2015 /* push it on the stack */
2017 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2022 pic14_emitcode("push","%s",l);
2027 /* this is a paramter push: in this case we call
2028 the routine to find the call and save those
2029 registers that need to be saved */
2032 /* then do the push */
2033 aopOp(IC_LEFT(ic),ic,FALSE);
2036 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2037 size = AOP_SIZE(IC_LEFT(ic));
2040 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2041 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
2042 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2044 pic14_emitcode("mov","a,%s",l);
2045 pic14_emitcode("push","acc");
2047 pic14_emitcode("push","%s",l);
2050 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2054 /*-----------------------------------------------------------------*/
2055 /* genIpop - recover the registers: can happen only for spilling */
2056 /*-----------------------------------------------------------------*/
2057 static void genIpop (iCode *ic)
2059 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2064 /* if the temp was not pushed then */
2065 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2068 aopOp(IC_LEFT(ic),ic,FALSE);
2069 size = AOP_SIZE(IC_LEFT(ic));
2072 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2075 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2079 /*-----------------------------------------------------------------*/
2080 /* unsaverbank - restores the resgister bank from stack */
2081 /*-----------------------------------------------------------------*/
2082 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2084 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2090 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2092 if (options.useXstack) {
2094 r = getFreePtr(ic,&aop,FALSE);
2097 pic14_emitcode("mov","%s,_spx",r->name);
2098 pic14_emitcode("movx","a,@%s",r->name);
2099 pic14_emitcode("mov","psw,a");
2100 pic14_emitcode("dec","%s",r->name);
2103 pic14_emitcode ("pop","psw");
2106 for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2107 if (options.useXstack) {
2108 pic14_emitcode("movx","a,@%s",r->name);
2109 //pic14_emitcode("mov","(%s+%d),a",
2110 // regspic14[i].base,8*bank+regspic14[i].offset);
2111 pic14_emitcode("dec","%s",r->name);
2114 pic14_emitcode("pop",""); //"(%s+%d)",
2115 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2118 if (options.useXstack) {
2120 pic14_emitcode("mov","_spx,%s",r->name);
2121 freeAsmop(NULL,aop,ic,TRUE);
2127 /*-----------------------------------------------------------------*/
2128 /* saverbank - saves an entire register bank on the stack */
2129 /*-----------------------------------------------------------------*/
2130 static void saverbank (int bank, iCode *ic, bool pushPsw)
2132 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2138 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2139 if (options.useXstack) {
2142 r = getFreePtr(ic,&aop,FALSE);
2143 pic14_emitcode("mov","%s,_spx",r->name);
2147 for (i = 0 ; i < pic14_nRegs ;i++) {
2148 if (options.useXstack) {
2149 pic14_emitcode("inc","%s",r->name);
2150 //pic14_emitcode("mov","a,(%s+%d)",
2151 // regspic14[i].base,8*bank+regspic14[i].offset);
2152 pic14_emitcode("movx","@%s,a",r->name);
2154 pic14_emitcode("push","");// "(%s+%d)",
2155 //regspic14[i].base,8*bank+regspic14[i].offset);
2159 if (options.useXstack) {
2160 pic14_emitcode("mov","a,psw");
2161 pic14_emitcode("movx","@%s,a",r->name);
2162 pic14_emitcode("inc","%s",r->name);
2163 pic14_emitcode("mov","_spx,%s",r->name);
2164 freeAsmop (NULL,aop,ic,TRUE);
2167 pic14_emitcode("push","psw");
2169 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2175 /*-----------------------------------------------------------------*/
2176 /* genCall - generates a call statement */
2177 /*-----------------------------------------------------------------*/
2178 static void genCall (iCode *ic)
2182 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2184 /* if caller saves & we have not saved then */
2188 /* if we are calling a function that is not using
2189 the same register bank then we need to save the
2190 destination registers on the stack */
2191 dtype = operandType(IC_LEFT(ic));
2192 if (currFunc && dtype &&
2193 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2194 IFFUNC_ISISR(currFunc->type) &&
2197 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2199 /* if send set is not empty the assign */
2202 /* For the Pic port, there is no data stack.
2203 * So parameters passed to functions are stored
2204 * in registers. (The pCode optimizer will get
2205 * rid of most of these :).
2207 int psuedoStkPtr=-1;
2208 int firstTimeThruLoop = 1;
2210 _G.sendSet = reverseSet(_G.sendSet);
2212 /* First figure how many parameters are getting passed */
2213 for (sic = setFirstItem(_G.sendSet) ; sic ;
2214 sic = setNextItem(_G.sendSet)) {
2216 aopOp(IC_LEFT(sic),sic,FALSE);
2217 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2218 freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2221 for (sic = setFirstItem(_G.sendSet) ; sic ;
2222 sic = setNextItem(_G.sendSet)) {
2223 int size, offset = 0;
2225 aopOp(IC_LEFT(sic),sic,FALSE);
2226 size = AOP_SIZE(IC_LEFT(sic));
2230 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2231 AopType(AOP_TYPE(IC_LEFT(sic))));
2233 if(!firstTimeThruLoop) {
2234 /* If this is not the first time we've been through the loop
2235 * then we need to save the parameter in a temporary
2236 * register. The last byte of the last parameter is
2238 emitpcode(POC_MOVWF,popRegFromIdx(--psuedoStkPtr + Gstack_base_addr));
2241 firstTimeThruLoop=0;
2243 //if (strcmp(l,fReturn[offset])) {
2245 if ( ((AOP(IC_LEFT(sic))->type) == AOP_IMMD) ||
2246 ((AOP(IC_LEFT(sic))->type) == AOP_LIT) )
2247 emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(sic)),offset));
2249 emitpcode(POC_MOVFW,popGet(AOP(IC_LEFT(sic)),offset));
2254 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2259 emitpcode(POC_CALL,popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2260 OP_SYMBOL(IC_LEFT(ic))->rname :
2261 OP_SYMBOL(IC_LEFT(ic))->name));
2264 /* if we need assign a result value */
2265 if ((IS_ITEMP(IC_RESULT(ic)) &&
2266 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2267 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2268 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2271 aopOp(IC_RESULT(ic),ic,FALSE);
2274 assignResultValue(IC_RESULT(ic));
2276 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2277 AopType(AOP_TYPE(IC_RESULT(ic))));
2279 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2282 /* adjust the stack for parameters if
2284 if (ic->parmBytes) {
2286 if (ic->parmBytes > 3) {
2287 pic14_emitcode("mov","a,%s",spname);
2288 pic14_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2289 pic14_emitcode("mov","%s,a",spname);
2291 for ( i = 0 ; i < ic->parmBytes ;i++)
2292 pic14_emitcode("dec","%s",spname);
2296 /* if register bank was saved then pop them */
2298 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2300 /* if we hade saved some registers then unsave them */
2301 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2302 unsaveRegisters (ic);
2307 /*-----------------------------------------------------------------*/
2308 /* genPcall - generates a call by pointer statement */
2309 /*-----------------------------------------------------------------*/
2310 static void genPcall (iCode *ic)
2313 symbol *rlbl = newiTempLabel(NULL);
2316 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2317 /* if caller saves & we have not saved then */
2321 /* if we are calling a function that is not using
2322 the same register bank then we need to save the
2323 destination registers on the stack */
2324 dtype = operandType(IC_LEFT(ic));
2325 if (currFunc && dtype &&
2326 IFFUNC_ISISR(currFunc->type) &&
2327 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2328 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2331 /* push the return address on to the stack */
2332 pic14_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
2333 pic14_emitcode("push","acc");
2334 pic14_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
2335 pic14_emitcode("push","acc");
2337 if (options.model == MODEL_FLAT24)
2339 pic14_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
2340 pic14_emitcode("push","acc");
2343 /* now push the calling address */
2344 aopOp(IC_LEFT(ic),ic,FALSE);
2346 pushSide(IC_LEFT(ic), FPTRSIZE);
2348 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2350 /* if send set is not empty the assign */
2354 for (sic = setFirstItem(_G.sendSet) ; sic ;
2355 sic = setNextItem(_G.sendSet)) {
2356 int size, offset = 0;
2357 aopOp(IC_LEFT(sic),sic,FALSE);
2358 size = AOP_SIZE(IC_LEFT(sic));
2360 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2362 if (strcmp(l,fReturn[offset]))
2363 pic14_emitcode("mov","%s,%s",
2368 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2373 pic14_emitcode("ret","");
2374 pic14_emitcode("","%05d_DS_:",(rlbl->key+100));
2377 /* if we need assign a result value */
2378 if ((IS_ITEMP(IC_RESULT(ic)) &&
2379 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2380 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2381 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2384 aopOp(IC_RESULT(ic),ic,FALSE);
2387 assignResultValue(IC_RESULT(ic));
2389 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2392 /* adjust the stack for parameters if
2394 if (ic->parmBytes) {
2396 if (ic->parmBytes > 3) {
2397 pic14_emitcode("mov","a,%s",spname);
2398 pic14_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2399 pic14_emitcode("mov","%s,a",spname);
2401 for ( i = 0 ; i < ic->parmBytes ;i++)
2402 pic14_emitcode("dec","%s",spname);
2406 /* if register bank was saved then unsave them */
2407 if (currFunc && dtype &&
2408 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2409 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2411 /* if we hade saved some registers then
2414 unsaveRegisters (ic);
2418 /*-----------------------------------------------------------------*/
2419 /* resultRemat - result is rematerializable */
2420 /*-----------------------------------------------------------------*/
2421 static int resultRemat (iCode *ic)
2423 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2424 if (SKIP_IC(ic) || ic->op == IFX)
2427 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2428 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2429 if (sym->remat && !POINTER_SET(ic))
2436 #if defined(__BORLANDC__) || defined(_MSC_VER)
2437 #define STRCASECMP stricmp
2439 #define STRCASECMP strcasecmp
2442 /*-----------------------------------------------------------------*/
2443 /* inExcludeList - return 1 if the string is in exclude Reg list */
2444 /*-----------------------------------------------------------------*/
2445 static bool inExcludeList(char *s)
2447 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2451 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2452 if (options.excludeRegs[i] &&
2453 STRCASECMP(options.excludeRegs[i],"none") == 0)
2456 for ( i = 0 ; options.excludeRegs[i]; i++) {
2457 if (options.excludeRegs[i] &&
2458 STRCASECMP(s,options.excludeRegs[i]) == 0)
2465 /*-----------------------------------------------------------------*/
2466 /* genFunction - generated code for function entry */
2467 /*-----------------------------------------------------------------*/
2468 static void genFunction (iCode *ic)
2473 DEBUGpic14_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2475 labelOffset += (max_key+4);
2479 /* create the function header */
2480 pic14_emitcode(";","-----------------------------------------");
2481 pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2482 pic14_emitcode(";","-----------------------------------------");
2484 pic14_emitcode("","%s:",sym->rname);
2485 addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname));
2487 ftype = operandType(IC_LEFT(ic));
2489 /* if critical function then turn interrupts off */
2490 if (IFFUNC_ISCRITICAL(ftype))
2491 pic14_emitcode("clr","ea");
2493 /* here we need to generate the equates for the
2494 register bank if required */
2496 if (FUNC_REGBANK(ftype) != rbank) {
2499 rbank = FUNC_REGBANK(ftype);
2500 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2501 if (strcmp(regspic14[i].base,"0") == 0)
2502 pic14_emitcode("","%s = 0x%02x",
2504 8*rbank+regspic14[i].offset);
2506 pic14_emitcode ("","%s = %s + 0x%02x",
2509 8*rbank+regspic14[i].offset);
2514 /* if this is an interrupt service routine then
2515 save acc, b, dpl, dph */
2516 if (IFFUNC_ISISR(sym->type)) {
2518 if (!inExcludeList("acc"))
2519 pic14_emitcode ("push","acc");
2520 if (!inExcludeList("b"))
2521 pic14_emitcode ("push","b");
2522 if (!inExcludeList("dpl"))
2523 pic14_emitcode ("push","dpl");
2524 if (!inExcludeList("dph"))
2525 pic14_emitcode ("push","dph");
2526 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2528 pic14_emitcode ("push", "dpx");
2529 /* Make sure we're using standard DPTR */
2530 pic14_emitcode ("push", "dps");
2531 pic14_emitcode ("mov", "dps, #0x00");
2532 if (options.stack10bit)
2534 /* This ISR could conceivably use DPTR2. Better save it. */
2535 pic14_emitcode ("push", "dpl1");
2536 pic14_emitcode ("push", "dph1");
2537 pic14_emitcode ("push", "dpx1");
2540 /* if this isr has no bank i.e. is going to
2541 run with bank 0 , then we need to save more
2543 if (!FUNC_REGBANK(sym->type)) {
2545 /* if this function does not call any other
2546 function then we can be economical and
2547 save only those registers that are used */
2548 if (! IFFUNC_HASFCALL(sym->type)) {
2551 /* if any registers used */
2552 if (sym->regsUsed) {
2553 /* save the registers used */
2554 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2555 if (bitVectBitValue(sym->regsUsed,i) ||
2556 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2557 pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2562 /* this function has a function call cannot
2563 determines register usage so we will have the
2565 saverbank(0,ic,FALSE);
2569 /* if callee-save to be used for this function
2570 then save the registers being used in this function */
2571 if (IFFUNC_CALLEESAVES(sym->type)) {
2574 /* if any registers used */
2575 if (sym->regsUsed) {
2576 /* save the registers used */
2577 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2578 if (bitVectBitValue(sym->regsUsed,i) ||
2579 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2580 pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2588 /* set the register bank to the desired value */
2589 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2590 pic14_emitcode("push","psw");
2591 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);
2594 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2596 if (options.useXstack) {
2597 pic14_emitcode("mov","r0,%s",spname);
2598 pic14_emitcode("mov","a,_bp");
2599 pic14_emitcode("movx","@r0,a");
2600 pic14_emitcode("inc","%s",spname);
2604 /* set up the stack */
2605 pic14_emitcode ("push","_bp"); /* save the callers stack */
2607 pic14_emitcode ("mov","_bp,%s",spname);
2610 /* adjust the stack for the function */
2615 werror(W_STACK_OVERFLOW,sym->name);
2617 if (i > 3 && sym->recvSize < 4) {
2619 pic14_emitcode ("mov","a,sp");
2620 pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2621 pic14_emitcode ("mov","sp,a");
2626 pic14_emitcode("inc","sp");
2631 pic14_emitcode ("mov","a,_spx");
2632 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2633 pic14_emitcode ("mov","_spx,a");
2638 /*-----------------------------------------------------------------*/
2639 /* genEndFunction - generates epilogue for functions */
2640 /*-----------------------------------------------------------------*/
2641 static void genEndFunction (iCode *ic)
2643 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2645 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2647 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2649 pic14_emitcode ("mov","%s,_bp",spname);
2652 /* if use external stack but some variables were
2653 added to the local stack then decrement the
2655 if (options.useXstack && sym->stack) {
2656 pic14_emitcode("mov","a,sp");
2657 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2658 pic14_emitcode("mov","sp,a");
2662 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2663 if (options.useXstack) {
2664 pic14_emitcode("mov","r0,%s",spname);
2665 pic14_emitcode("movx","a,@r0");
2666 pic14_emitcode("mov","_bp,a");
2667 pic14_emitcode("dec","%s",spname);
2671 pic14_emitcode ("pop","_bp");
2675 /* restore the register bank */
2676 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2677 pic14_emitcode ("pop","psw");
2679 if (IFFUNC_ISISR(sym->type)) {
2681 /* now we need to restore the registers */
2682 /* if this isr has no bank i.e. is going to
2683 run with bank 0 , then we need to save more
2685 if (!FUNC_REGBANK(sym->type)) {
2687 /* if this function does not call any other
2688 function then we can be economical and
2689 save only those registers that are used */
2690 if (! IFFUNC_HASFCALL(sym->type)) {
2693 /* if any registers used */
2694 if (sym->regsUsed) {
2695 /* save the registers used */
2696 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2697 if (bitVectBitValue(sym->regsUsed,i) ||
2698 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2699 pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2704 /* this function has a function call cannot
2705 determines register usage so we will have the
2707 unsaverbank(0,ic,FALSE);
2711 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2713 if (options.stack10bit)
2715 pic14_emitcode ("pop", "dpx1");
2716 pic14_emitcode ("pop", "dph1");
2717 pic14_emitcode ("pop", "dpl1");
2719 pic14_emitcode ("pop", "dps");
2720 pic14_emitcode ("pop", "dpx");
2722 if (!inExcludeList("dph"))
2723 pic14_emitcode ("pop","dph");
2724 if (!inExcludeList("dpl"))
2725 pic14_emitcode ("pop","dpl");
2726 if (!inExcludeList("b"))
2727 pic14_emitcode ("pop","b");
2728 if (!inExcludeList("acc"))
2729 pic14_emitcode ("pop","acc");
2731 if (IFFUNC_ISCRITICAL(sym->type))
2732 pic14_emitcode("setb","ea");
2734 /* if debug then send end of function */
2735 /* if (options.debug && currFunc) { */
2738 pic14_emitcode(";","C$%s$%d$%d$%d ==.",
2739 FileBaseName(ic->filename),currFunc->lastLine,
2740 ic->level,ic->block);
2741 if (IS_STATIC(currFunc->etype))
2742 pic14_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2744 pic14_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2748 pic14_emitcode ("reti","");
2751 if (IFFUNC_ISCRITICAL(sym->type))
2752 pic14_emitcode("setb","ea");
2754 if (IFFUNC_CALLEESAVES(sym->type)) {
2757 /* if any registers used */
2758 if (sym->regsUsed) {
2759 /* save the registers used */
2760 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2761 if (bitVectBitValue(sym->regsUsed,i) ||
2762 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2763 pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2769 /* if debug then send end of function */
2772 pic14_emitcode(";","C$%s$%d$%d$%d ==.",
2773 FileBaseName(ic->filename),currFunc->lastLine,
2774 ic->level,ic->block);
2775 if (IS_STATIC(currFunc->etype))
2776 pic14_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2778 pic14_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2782 pic14_emitcode ("return","");
2783 emitpcodeNULLop(POC_RETURN);
2785 /* Mark the end of a function */
2786 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL));
2791 /*-----------------------------------------------------------------*/
2792 /* genRet - generate code for return statement */
2793 /*-----------------------------------------------------------------*/
2794 static void genRet (iCode *ic)
2796 int size,offset = 0 , pushed = 0;
2798 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2799 /* if we have no return value then
2800 just generate the "ret" */
2804 /* we have something to return then
2805 move the return value into place */
2806 aopOp(IC_LEFT(ic),ic,FALSE);
2807 size = AOP_SIZE(IC_LEFT(ic));
2811 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2813 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2815 pic14_emitcode("push","%s",l);
2818 l = aopGet(AOP(IC_LEFT(ic)),offset,
2820 if (strcmp(fReturn[offset],l)) {
2821 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
2822 ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
2823 emitpcode(POC_MOVLW, popGet(AOP(IC_LEFT(ic)),offset));
2825 emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset));
2828 emitpcode(POC_MOVWF,popRegFromIdx(offset + Gstack_base_addr));
2829 pic14_emitcode("movwf","%s",fReturn[offset]);
2839 if (strcmp(fReturn[pushed],"a"))
2840 pic14_emitcode("pop",fReturn[pushed]);
2842 pic14_emitcode("pop","acc");
2845 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2848 /* generate a jump to the return label
2849 if the next is not the return statement */
2850 if (!(ic->next && ic->next->op == LABEL &&
2851 IC_LABEL(ic->next) == returnLabel)) {
2853 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
2854 pic14_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
2859 /*-----------------------------------------------------------------*/
2860 /* genLabel - generates a label */
2861 /*-----------------------------------------------------------------*/
2862 static void genLabel (iCode *ic)
2864 /* special case never generate */
2865 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2866 if (IC_LABEL(ic) == entryLabel)
2869 emitpLabel(IC_LABEL(ic)->key);
2870 pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
2873 /*-----------------------------------------------------------------*/
2874 /* genGoto - generates a goto */
2875 /*-----------------------------------------------------------------*/
2877 static void genGoto (iCode *ic)
2879 emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
2880 pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
2884 /*-----------------------------------------------------------------*/
2885 /* genMultbits :- multiplication of bits */
2886 /*-----------------------------------------------------------------*/
2887 static void genMultbits (operand *left,
2891 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2893 if(!pic14_sameRegs(AOP(result),AOP(right)))
2894 emitpcode(POC_BSF, popGet(AOP(result),0));
2896 emitpcode(POC_BTFSC,popGet(AOP(right),0));
2897 emitpcode(POC_BTFSS,popGet(AOP(left),0));
2898 emitpcode(POC_BCF, popGet(AOP(result),0));
2903 /*-----------------------------------------------------------------*/
2904 /* genMultOneByte : 8 bit multiplication & division */
2905 /*-----------------------------------------------------------------*/
2906 static void genMultOneByte (operand *left,
2910 sym_link *opetype = operandType(result);
2915 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2916 DEBUGpic14_AopType(__LINE__,left,right,result);
2918 /* (if two literals, the value is computed before) */
2919 /* if one literal, literal on the right */
2920 if (AOP_TYPE(left) == AOP_LIT){
2926 size = AOP_SIZE(result);
2927 /* signed or unsigned */
2928 pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2929 l = aopGet(AOP(left),0,FALSE,FALSE);
2931 pic14_emitcode("mul","ab");
2932 /* if result size = 1, mul signed = mul unsigned */
2933 aopPut(AOP(result),"a",0);
2935 if (SPEC_USIGN(opetype)){
2936 aopPut(AOP(result),"b",1);
2938 /* for filling the MSBs */
2939 pic14_emitcode("clr","a");
2942 pic14_emitcode("mov","a,b");
2944 /* adjust the MSB if left or right neg */
2946 /* if one literal */
2947 if (AOP_TYPE(right) == AOP_LIT){
2948 /* AND literal negative */
2949 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
2950 /* adjust MSB (c==0 after mul) */
2951 pic14_emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2955 lbl = newiTempLabel(NULL);
2956 pic14_emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2957 pic14_emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
2958 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
2959 pic14_emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2960 lbl = newiTempLabel(NULL);
2961 pic14_emitcode("jc","%05d_DS_",(lbl->key+100));
2962 pic14_emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2963 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
2966 lbl = newiTempLabel(NULL);
2967 pic14_emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
2968 pic14_emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
2969 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
2970 pic14_emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
2971 lbl = newiTempLabel(NULL);
2972 pic14_emitcode("jc","%05d_DS_",(lbl->key+100));
2973 pic14_emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
2974 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
2976 aopPut(AOP(result),"a",1);
2979 pic14_emitcode("rlc","a");
2980 pic14_emitcode("subb","a,acc");
2987 aopPut(AOP(result),"a",offset++);
2991 /*-----------------------------------------------------------------*/
2992 /* genMult - generates code for multiplication */
2993 /*-----------------------------------------------------------------*/
2994 static void genMult (iCode *ic)
2996 operand *left = IC_LEFT(ic);
2997 operand *right = IC_RIGHT(ic);
2998 operand *result= IC_RESULT(ic);
3000 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3001 /* assign the amsops */
3002 aopOp (left,ic,FALSE);
3003 aopOp (right,ic,FALSE);
3004 aopOp (result,ic,TRUE);
3006 DEBUGpic14_AopType(__LINE__,left,right,result);
3008 /* special cases first */
3010 if (AOP_TYPE(left) == AOP_CRY &&
3011 AOP_TYPE(right)== AOP_CRY) {
3012 genMultbits(left,right,result);
3016 /* if both are of size == 1 */
3017 if (AOP_SIZE(left) == 1 &&
3018 AOP_SIZE(right) == 1 ) {
3019 genMultOneByte(left,right,result);
3023 /* should have been converted to function call */
3027 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3028 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3029 freeAsmop(result,NULL,ic,TRUE);
3032 /*-----------------------------------------------------------------*/
3033 /* genDivbits :- division of bits */
3034 /*-----------------------------------------------------------------*/
3035 static void genDivbits (operand *left,
3042 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3043 /* the result must be bit */
3044 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3045 l = aopGet(AOP(left),0,FALSE,FALSE);
3049 pic14_emitcode("div","ab");
3050 pic14_emitcode("rrc","a");
3051 aopPut(AOP(result),"c",0);
3054 /*-----------------------------------------------------------------*/
3055 /* genDivOneByte : 8 bit division */
3056 /*-----------------------------------------------------------------*/
3057 static void genDivOneByte (operand *left,
3061 sym_link *opetype = operandType(result);
3066 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3067 size = AOP_SIZE(result) - 1;
3069 /* signed or unsigned */
3070 if (SPEC_USIGN(opetype)) {
3071 /* unsigned is easy */
3072 pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3073 l = aopGet(AOP(left),0,FALSE,FALSE);
3075 pic14_emitcode("div","ab");
3076 aopPut(AOP(result),"a",0);
3078 aopPut(AOP(result),zero,offset++);
3082 /* signed is a little bit more difficult */
3084 /* save the signs of the operands */
3085 l = aopGet(AOP(left),0,FALSE,FALSE);
3087 pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3088 pic14_emitcode("push","acc"); /* save it on the stack */
3090 /* now sign adjust for both left & right */
3091 l = aopGet(AOP(right),0,FALSE,FALSE);
3093 lbl = newiTempLabel(NULL);
3094 pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3095 pic14_emitcode("cpl","a");
3096 pic14_emitcode("inc","a");
3097 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3098 pic14_emitcode("mov","b,a");
3100 /* sign adjust left side */
3101 l = aopGet(AOP(left),0,FALSE,FALSE);
3104 lbl = newiTempLabel(NULL);
3105 pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3106 pic14_emitcode("cpl","a");
3107 pic14_emitcode("inc","a");
3108 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3110 /* now the division */
3111 pic14_emitcode("div","ab");
3112 /* we are interested in the lower order
3114 pic14_emitcode("mov","b,a");
3115 lbl = newiTempLabel(NULL);
3116 pic14_emitcode("pop","acc");
3117 /* if there was an over flow we don't
3118 adjust the sign of the result */
3119 pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3120 pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3122 pic14_emitcode("clr","a");
3123 pic14_emitcode("subb","a,b");
3124 pic14_emitcode("mov","b,a");
3125 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3127 /* now we are done */
3128 aopPut(AOP(result),"b",0);
3130 pic14_emitcode("mov","c,b.7");
3131 pic14_emitcode("subb","a,acc");
3134 aopPut(AOP(result),"a",offset++);
3138 /*-----------------------------------------------------------------*/
3139 /* genDiv - generates code for division */
3140 /*-----------------------------------------------------------------*/
3141 static void genDiv (iCode *ic)
3143 operand *left = IC_LEFT(ic);
3144 operand *right = IC_RIGHT(ic);
3145 operand *result= IC_RESULT(ic);
3147 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3148 /* assign the amsops */
3149 aopOp (left,ic,FALSE);
3150 aopOp (right,ic,FALSE);
3151 aopOp (result,ic,TRUE);
3153 /* special cases first */
3155 if (AOP_TYPE(left) == AOP_CRY &&
3156 AOP_TYPE(right)== AOP_CRY) {
3157 genDivbits(left,right,result);
3161 /* if both are of size == 1 */
3162 if (AOP_SIZE(left) == 1 &&
3163 AOP_SIZE(right) == 1 ) {
3164 genDivOneByte(left,right,result);
3168 /* should have been converted to function call */
3171 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3172 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3173 freeAsmop(result,NULL,ic,TRUE);
3176 /*-----------------------------------------------------------------*/
3177 /* genModbits :- modulus of bits */
3178 /*-----------------------------------------------------------------*/
3179 static void genModbits (operand *left,
3186 /* the result must be bit */
3187 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3188 l = aopGet(AOP(left),0,FALSE,FALSE);
3192 pic14_emitcode("div","ab");
3193 pic14_emitcode("mov","a,b");
3194 pic14_emitcode("rrc","a");
3195 aopPut(AOP(result),"c",0);
3198 /*-----------------------------------------------------------------*/
3199 /* genModOneByte : 8 bit modulus */
3200 /*-----------------------------------------------------------------*/
3201 static void genModOneByte (operand *left,
3205 sym_link *opetype = operandType(result);
3209 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3210 /* signed or unsigned */
3211 if (SPEC_USIGN(opetype)) {
3212 /* unsigned is easy */
3213 pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3214 l = aopGet(AOP(left),0,FALSE,FALSE);
3216 pic14_emitcode("div","ab");
3217 aopPut(AOP(result),"b",0);
3221 /* signed is a little bit more difficult */
3223 /* save the signs of the operands */
3224 l = aopGet(AOP(left),0,FALSE,FALSE);
3227 pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3228 pic14_emitcode("push","acc"); /* save it on the stack */
3230 /* now sign adjust for both left & right */
3231 l = aopGet(AOP(right),0,FALSE,FALSE);
3234 lbl = newiTempLabel(NULL);
3235 pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3236 pic14_emitcode("cpl","a");
3237 pic14_emitcode("inc","a");
3238 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3239 pic14_emitcode("mov","b,a");
3241 /* sign adjust left side */
3242 l = aopGet(AOP(left),0,FALSE,FALSE);
3245 lbl = newiTempLabel(NULL);
3246 pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3247 pic14_emitcode("cpl","a");
3248 pic14_emitcode("inc","a");
3249 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3251 /* now the multiplication */
3252 pic14_emitcode("div","ab");
3253 /* we are interested in the lower order
3255 lbl = newiTempLabel(NULL);
3256 pic14_emitcode("pop","acc");
3257 /* if there was an over flow we don't
3258 adjust the sign of the result */
3259 pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3260 pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3262 pic14_emitcode("clr","a");
3263 pic14_emitcode("subb","a,b");
3264 pic14_emitcode("mov","b,a");
3265 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3267 /* now we are done */
3268 aopPut(AOP(result),"b",0);
3272 /*-----------------------------------------------------------------*/
3273 /* genMod - generates code for division */
3274 /*-----------------------------------------------------------------*/
3275 static void genMod (iCode *ic)
3277 operand *left = IC_LEFT(ic);
3278 operand *right = IC_RIGHT(ic);
3279 operand *result= IC_RESULT(ic);
3281 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3282 /* assign the amsops */
3283 aopOp (left,ic,FALSE);
3284 aopOp (right,ic,FALSE);
3285 aopOp (result,ic,TRUE);
3287 /* special cases first */
3289 if (AOP_TYPE(left) == AOP_CRY &&
3290 AOP_TYPE(right)== AOP_CRY) {
3291 genModbits(left,right,result);
3295 /* if both are of size == 1 */
3296 if (AOP_SIZE(left) == 1 &&
3297 AOP_SIZE(right) == 1 ) {
3298 genModOneByte(left,right,result);
3302 /* should have been converted to function call */
3306 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3307 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3308 freeAsmop(result,NULL,ic,TRUE);
3311 /*-----------------------------------------------------------------*/
3312 /* genIfxJump :- will create a jump depending on the ifx */
3313 /*-----------------------------------------------------------------*/
3315 note: May need to add parameter to indicate when a variable is in bit space.
3317 static void genIfxJump (iCode *ic, char *jval)
3320 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3321 /* if true label then we jump if condition
3323 if ( IC_TRUE(ic) ) {
3325 if(strcmp(jval,"a") == 0)
3327 else if (strcmp(jval,"c") == 0)
3330 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3331 emitpcode(POC_BTFSC, newpCodeOpBit(jval,-1,1));
3334 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3335 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3339 /* false label is present */
3340 if(strcmp(jval,"a") == 0)
3342 else if (strcmp(jval,"c") == 0)
3345 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3346 emitpcode(POC_BTFSS, newpCodeOpBit(jval,-1,1));
3349 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3350 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3355 /* mark the icode as generated */
3359 /*-----------------------------------------------------------------*/
3361 /*-----------------------------------------------------------------*/
3362 static void genSkip(iCode *ifx,int status_bit)
3367 if ( IC_TRUE(ifx) ) {
3368 switch(status_bit) {
3383 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3384 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3388 switch(status_bit) {
3402 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3403 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3409 /*-----------------------------------------------------------------*/
3411 /*-----------------------------------------------------------------*/
3412 static void genSkipc(resolvedIfx *rifx)
3422 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3423 rifx->generated = 1;
3426 /*-----------------------------------------------------------------*/
3428 /*-----------------------------------------------------------------*/
3429 static void genSkipz2(resolvedIfx *rifx)
3439 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3440 rifx->generated = 1;
3443 /*-----------------------------------------------------------------*/
3445 /*-----------------------------------------------------------------*/
3446 static void genSkipz(iCode *ifx, int condition)
3457 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3459 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3462 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3464 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3467 /*-----------------------------------------------------------------*/
3469 /*-----------------------------------------------------------------*/
3470 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3476 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3478 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3481 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3482 rifx->generated = 1;
3486 /*-----------------------------------------------------------------*/
3487 /* genChkZeroes :- greater or less than comparison */
3488 /* For each byte in a literal that is zero, inclusive or the */
3489 /* the corresponding byte in the operand with W */
3490 /* returns true if any of the bytes are zero */
3491 /*-----------------------------------------------------------------*/
3492 static int genChkZeroes(operand *op, int lit, int size)
3499 i = (lit >> (size*8)) & 0xff;
3503 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3505 emitpcode(POC_IORFW, popGet(AOP(op),size));
3514 /*-----------------------------------------------------------------*/
3515 /* genCmp :- greater or less than comparison */
3516 /*-----------------------------------------------------------------*/
3517 static void genCmp (operand *left,operand *right,
3518 operand *result, iCode *ifx, int sign)
3520 int size, offset = 0 ;
3521 unsigned long lit = 0L,i = 0;
3524 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3526 DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
3527 DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
3530 resolveIfx(&rIfx,ifx);
3532 /* if left & right are bit variables */
3533 if (AOP_TYPE(left) == AOP_CRY &&
3534 AOP_TYPE(right) == AOP_CRY ) {
3535 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3536 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3538 /* subtract right from left if at the
3539 end the carry flag is set then we know that
3540 left is greater than right */
3541 size = max(AOP_SIZE(left),AOP_SIZE(right));
3543 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3544 if((size == 1) && !sign &&
3545 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3546 symbol *lbl = newiTempLabel(NULL);
3547 pic14_emitcode("cjne","%s,%s,%05d_DS_",
3548 aopGet(AOP(left),offset,FALSE,FALSE),
3549 aopGet(AOP(right),offset,FALSE,FALSE),
3551 pic14_emitcode("","%05d_DS_:",lbl->key+100);
3554 symbol *lbl = newiTempLabel(NULL);
3555 int emitFinalCheck=1;
3556 symbol *truelbl = newiTempLabel(NULL);
3559 if(AOP_TYPE(right) == AOP_LIT) {
3561 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3563 DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
3570 genSkipCond(&rIfx,left,size-1,7);
3572 /* no need to compare to 0...*/
3573 /* NOTE: this is a de-generate compare that most certainly
3574 * creates some dead code. */
3575 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
3577 if(ifx) ifx->generated = 1;
3584 //i = (lit >> (size*8)) & 0xff;
3585 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3587 emitpcode(POC_MOVFW, popGet(AOP(left),size));
3589 i = ((0-lit) & 0xff);
3592 /* lit is 0x7f, all signed chars are less than
3593 * this except for 0x7f itself */
3594 emitpcode(POC_XORLW, popGetLit(0x7f));
3597 emitpcode(POC_ADDLW, popGetLit(0x80));
3598 emitpcode(POC_ADDLW, popGetLit(i^0x80));
3603 emitpcode(POC_ADDLW, popGetLit(i));
3608 if(ifx) ifx->generated = 1;
3612 /* chars are out of the way. now do ints and longs */
3615 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3622 genSkipCond(&rIfx,left,size,7);
3623 if(ifx) ifx->generated = 1;
3628 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3630 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3631 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
3632 emitpcode(POC_MOVLW, popGetLit(0x100-lit));
3633 emitpcode(POC_ADDFW, popGet(AOP(left),0));
3634 emitpcode(POC_MOVFW, popGet(AOP(left),1));
3637 emitpcode(POC_IORFW, popGet(AOP(left),size--));
3642 emitpLabel(truelbl->key);
3643 if(ifx) ifx->generated = 1;
3650 if( (lit & 0xff) == 0) {
3651 /* lower byte is zero */
3652 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3653 i = ((lit >> 8) & 0xff) ^0x80;
3654 emitpcode(POC_MOVFW, popGet(AOP(left),size));
3655 emitpcode(POC_ADDLW, popGetLit( 0x80));
3656 emitpcode(POC_ADDLW, popGetLit(0x100-i));
3660 if(ifx) ifx->generated = 1;
3665 /* Special cases for signed longs */
3666 if( (lit & 0xffffff) == 0) {
3667 /* lower byte is zero */
3668 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3669 i = ((lit >> 8*3) & 0xff) ^0x80;
3670 emitpcode(POC_MOVFW, popGet(AOP(left),size));
3671 emitpcode(POC_ADDLW, popGetLit( 0x80));
3672 emitpcode(POC_ADDLW, popGetLit(0x100-i));
3676 if(ifx) ifx->generated = 1;
3682 if( lit < 0x10000) {
3683 /* upper word is zero */
3684 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3686 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3687 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
3689 emitpcode(POC_MOVLW, popGetLit((lit >> (1*8)) & 0xff));
3690 emitpcode(POC_SUBFW, popGet(AOP(left),1));
3691 emitpcode(POC_MOVLW, popGetLit((lit & 0xff));
3693 emitpcode(POC_SUBFW, popGet(AOP(left),0));
3695 emitpcode(POC_IORFW, popGet(AOP(left),2));
3696 emitpcode(POC_IORFW, popGet(AOP(left),3));
3701 emitpLabel(truelbl->key);
3702 if(ifx) ifx->generated = 1;
3711 if(lit & (0x80 << (size*8))) {
3712 /* lit is negative */
3713 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3715 genSkipCond(&rIfx,left,size,7);
3717 /* lit is positive */
3718 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3719 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3720 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
3725 This works, but is only good for ints.
3726 It also requires a "known zero" register.
3727 emitpcode(POC_MOVLW, popGetLit(mlit & 0xff));
3728 emitpcode(POC_ADDFW, popGet(AOP(left),0));
3729 emitpcode(POC_RLFW, popCopyReg(&pc_kzero));
3730 emitpcode(POC_ADDLW, popGetLit( ((mlit>>8) & 0xff)));
3731 emitpcode(POC_ADDFW, popGet(AOP(left),1));
3734 emitpLabel(truelbl->key);
3735 if(ifx) ifx->generated = 1;
3739 /* There are no more special cases, so perform a general compare */
3741 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3742 emitpcode(POC_SUBFW, popGet(AOP(left),size));
3746 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3748 emitpcode(POC_SUBFW, popGet(AOP(left),size));
3753 emitpLabel(truelbl->key);
3755 if(ifx) ifx->generated = 1;
3762 /* sign is out of the way. So now do an unsigned compare */
3763 DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
3766 //genChkZeroes(left)
3768 /* General case - compare to an unsigned literal on the right.*/
3770 i = (lit >> (size*8)) & 0xff;
3771 emitpcode(POC_MOVLW, popGetLit(i));
3772 emitpcode(POC_SUBFW, popGet(AOP(left),size));
3774 i = (lit >> (size*8)) & 0xff;
3777 emitpcode(POC_MOVLW, popGetLit(i));
3779 emitpcode(POC_SUBFW, popGet(AOP(left),size));
3781 /* this byte of the lit is zero,
3782 *if it's not the last then OR in the variable */
3784 emitpcode(POC_IORFW, popGet(AOP(left),size));
3789 emitpLabel(lbl->key);
3793 emitpLabel(truelbl->key);
3795 if(ifx) ifx->generated = 1;
3801 if(AOP_TYPE(left) == AOP_LIT) {
3802 //symbol *lbl = newiTempLabel(NULL);
3804 lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
3807 DEBUGpic14_emitcode(";left lit","lit = %d,sign=%d",lit,sign);
3810 if((lit == 0) && (sign == 0)){
3813 emitpcode(POC_MOVFW, popGet(AOP(right),size));
3815 emitpcode(POC_IORFW, popGet(AOP(right),--size));
3817 //rIfx.condition ^= 1;
3819 if(ifx) ifx->generated = 1;
3826 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
3827 /* degenerate compare can never be true */
3828 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
3829 if(ifx) ifx->generated = 1;
3835 emitpcode(POC_MOVFW, popGet(AOP(right),0));
3836 emitpcode(POC_ADDLW, popGetLit(0x80));
3837 emitpcode(POC_ADDLW, popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
3838 rIfx.condition ^= 1;
3841 rIfx.condition ^= 1;
3842 genSkipCond(&rIfx,right,0,7);
3847 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
3848 emitpcode(POC_SUBFW, popGet(AOP(right),0));
3849 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3850 rIfx.condition ^= 1;
3853 emitpcode(POC_MOVFW, popGet(AOP(right),0));
3858 if(ifx) ifx->generated = 1;
3863 /* Size is greater than 1 */
3873 /* this means lit = 0xffffffff, or -1 */
3876 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
3877 rIfx.condition ^= 1;
3878 genSkipCond(&rIfx,right,size,7);
3879 if(ifx) ifx->generated = 1;
3885 emitpcode(POC_MOVFW, popGet(AOP(right),size));
3887 emitpcode(POC_IORFW, popGet(AOP(right),size));
3890 rIfx.condition ^= 1;
3891 genSkipCond(&rIfx,right,s,7);
3892 if(ifx) ifx->generated = 1;
3897 if(lit & (0x80 << (size*8))) {
3898 /* Lit is less than zero */
3899 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
3900 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
3901 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
3904 /* Lit is greater than or equal to zero */
3905 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
3906 rIfx.condition ^= 1;
3907 genSkipCond(&rIfx,right,size,7);
3908 rIfx.condition ^= 1;
3911 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
3912 emitpcode(POC_SUBFW, popGet(AOP(right),size));
3916 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
3918 emitpcode(POC_SUBFW, popGet(AOP(right),size));
3920 rIfx.condition ^= 1;
3923 emitpLabel(truelbl->key);
3925 if(ifx) ifx->generated = 1;
3929 /* Unsigned compare for sizes greater than 1 */
3932 i = (lit >> (size*8)) & 0xff;
3936 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3937 emitpcode(POC_MOVLW, popGetLit(i&0xff));
3938 emitpcode(POC_SUBFW, popGet(AOP(right),size));
3940 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3942 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3943 emitpcode(POC_MOVLW, popGetLit((i+1)&0xff));
3944 emitpcode(POC_SUBFW, popGet(AOP(right),size));
3949 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3951 emitpLabel(lbl->key);
3953 rIfx.condition ^= 1;
3958 emitpLabel(truelbl->key);
3959 if(ifx) ifx->generated = 1;
3963 /* Compare two variables */
3965 DEBUGpic14_emitcode(";sign","%d",sign);
3969 /* Sigh. thus sucks... */
3971 emitpcode(POC_MOVFW, popGet(AOP(left),size));
3972 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3973 emitpcode(POC_MOVLW, popGetLit(0x80));
3974 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
3975 emitpcode(POC_XORFW, popGet(AOP(right),size));
3976 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
3978 /* Signed char comparison */
3979 /* Special thanks to Nikolai Golovchenko for this snippet */
3980 emitpcode(POC_MOVFW, popGet(AOP(right),0));
3981 emitpcode(POC_SUBFW, popGet(AOP(left),0));
3982 emitpcode(POC_RRFW, popGet(AOP(left),0)); /* could be any register */
3983 emitpcode(POC_XORFW, popGet(AOP(left),0));
3984 emitpcode(POC_XORFW, popGet(AOP(right),0));
3985 emitpcode(POC_ADDLW, popGetLit(0x80));
3987 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3990 if(ifx) ifx->generated = 1;
3996 emitpcode(POC_MOVFW, popGet(AOP(right),size));
3997 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4001 /* The rest of the bytes of a multi-byte compare */
4005 emitpcode(POC_GOTO, popGetLabel(lbl->key));
4008 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4009 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4014 emitpLabel(lbl->key);
4016 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4018 if(ifx) ifx->generated = 1;
4025 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4026 pic14_outBitC(result);
4028 /* if the result is used in the next
4029 ifx conditional branch then generate
4030 code a little differently */
4032 genIfxJump (ifx,"c");
4034 pic14_outBitC(result);
4035 /* leave the result in acc */
4040 /*-----------------------------------------------------------------*/
4041 /* genCmpGt :- greater than comparison */
4042 /*-----------------------------------------------------------------*/
4043 static void genCmpGt (iCode *ic, iCode *ifx)
4045 operand *left, *right, *result;
4046 sym_link *letype , *retype;
4049 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4051 right= IC_RIGHT(ic);
4052 result = IC_RESULT(ic);
4054 letype = getSpec(operandType(left));
4055 retype =getSpec(operandType(right));
4056 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4057 /* assign the amsops */
4058 aopOp (left,ic,FALSE);
4059 aopOp (right,ic,FALSE);
4060 aopOp (result,ic,TRUE);
4062 genCmp(right, left, result, ifx, sign);
4064 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4065 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4066 freeAsmop(result,NULL,ic,TRUE);
4069 /*-----------------------------------------------------------------*/
4070 /* genCmpLt - less than comparisons */
4071 /*-----------------------------------------------------------------*/
4072 static void genCmpLt (iCode *ic, iCode *ifx)
4074 operand *left, *right, *result;
4075 sym_link *letype , *retype;
4078 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4080 right= IC_RIGHT(ic);
4081 result = IC_RESULT(ic);
4083 letype = getSpec(operandType(left));
4084 retype =getSpec(operandType(right));
4085 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4087 /* assign the amsops */
4088 aopOp (left,ic,FALSE);
4089 aopOp (right,ic,FALSE);
4090 aopOp (result,ic,TRUE);
4092 genCmp(left, right, result, ifx, sign);
4094 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4095 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4096 freeAsmop(result,NULL,ic,TRUE);
4099 /*-----------------------------------------------------------------*/
4100 /* genc16bit2lit - compare a 16 bit value to a literal */
4101 /*-----------------------------------------------------------------*/
4102 static void genc16bit2lit(operand *op, int lit, int offset)
4106 DEBUGpic14_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
4107 if( (lit&0xff) == 0)
4112 switch( BYTEofLONG(lit,i)) {
4114 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4117 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4120 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4123 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4124 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4129 switch( BYTEofLONG(lit,i)) {
4131 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4135 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4139 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4142 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4144 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4150 /*-----------------------------------------------------------------*/
4151 /* gencjneshort - compare and jump if not equal */
4152 /*-----------------------------------------------------------------*/
4153 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4155 int size = max(AOP_SIZE(left),AOP_SIZE(right));
4160 unsigned long lit = 0L;
4161 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4162 DEBUGpic14_AopType(__LINE__,left,right,NULL);
4164 resolveIfx(&rIfx,ifx);
4165 lbl = newiTempLabel(NULL);
4168 /* if the left side is a literal or
4169 if the right is in a pointer register and left
4171 if ((AOP_TYPE(left) == AOP_LIT) ||
4172 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4177 if(AOP_TYPE(right) == AOP_LIT)
4178 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4180 /* if the right side is a literal then anything goes */
4181 if (AOP_TYPE(right) == AOP_LIT &&
4182 AOP_TYPE(left) != AOP_DIR ) {
4185 genc16bit2lit(left, lit, 0);
4187 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4192 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4193 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4195 emitpcode(POC_MOVF,popGet(AOP(left),offset));
4199 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4207 /* if the right side is in a register or in direct space or
4208 if the left is a pointer register & right is not */
4209 else if (AOP_TYPE(right) == AOP_REG ||
4210 AOP_TYPE(right) == AOP_DIR ||
4211 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4212 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4215 genc16bit2lit(left, lit, 0);
4217 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4222 if((AOP_TYPE(left) == AOP_DIR) &&
4223 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4225 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4226 emitpcode(POC_XORFW,popGet(AOP(right),offset));
4228 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4230 switch (lit & 0xff) {
4232 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4235 emitpcode(POC_DECFSZ,popGet(AOP(left),offset));
4236 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4240 emitpcode(POC_INCFSZ,popGet(AOP(left),offset));
4241 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4245 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4246 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4251 emitpcode(POC_MOVF,popGet(AOP(left),offset));
4254 if(AOP_TYPE(result) == AOP_CRY) {
4255 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
4260 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4262 /* fix me. probably need to check result size too */
4263 emitpcode(POC_CLRF,popGet(AOP(result),0));
4268 emitpcode(POC_INCF,popGet(AOP(result),0));
4278 } else if(AOP_TYPE(right) == AOP_REG &&
4279 AOP_TYPE(left) != AOP_DIR){
4282 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4283 emitpcode(POC_XORFW,popGet(AOP(right),offset));
4284 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
4289 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4294 /* right is a pointer reg need both a & b */
4296 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4298 pic14_emitcode("mov","b,%s",l);
4299 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4300 pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
4304 emitpLabel(lbl->key);
4311 /*-----------------------------------------------------------------*/
4312 /* gencjne - compare and jump if not equal */
4313 /*-----------------------------------------------------------------*/
4314 static void gencjne(operand *left, operand *right, iCode *ifx)
4316 symbol *tlbl = newiTempLabel(NULL);
4318 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4319 gencjneshort(left, right, lbl);
4321 pic14_emitcode("mov","a,%s",one);
4322 pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
4323 pic14_emitcode("","%05d_DS_:",lbl->key+100);
4324 pic14_emitcode("clr","a");
4325 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4327 emitpLabel(lbl->key);
4328 emitpLabel(tlbl->key);
4333 /*-----------------------------------------------------------------*/
4334 /* genCmpEq - generates code for equal to */
4335 /*-----------------------------------------------------------------*/
4336 static void genCmpEq (iCode *ic, iCode *ifx)
4338 operand *left, *right, *result;
4339 unsigned long lit = 0L;
4342 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4345 DEBUGpic14_emitcode ("; ifx is non-null","");
4347 DEBUGpic14_emitcode ("; ifx is null","");
4349 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4350 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4351 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4353 size = max(AOP_SIZE(left),AOP_SIZE(right));
4355 DEBUGpic14_AopType(__LINE__,left,right,result);
4357 /* if literal, literal on the right or
4358 if the right is in a pointer register and left
4360 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
4361 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4362 operand *tmp = right ;
4368 if(ifx && !AOP_SIZE(result)){
4370 /* if they are both bit variables */
4371 if (AOP_TYPE(left) == AOP_CRY &&
4372 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4373 if(AOP_TYPE(right) == AOP_LIT){
4374 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4376 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4377 pic14_emitcode("cpl","c");
4378 } else if(lit == 1L) {
4379 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4381 pic14_emitcode("clr","c");
4383 /* AOP_TYPE(right) == AOP_CRY */
4385 symbol *lbl = newiTempLabel(NULL);
4386 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4387 pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4388 pic14_emitcode("cpl","c");
4389 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4391 /* if true label then we jump if condition
4393 tlbl = newiTempLabel(NULL);
4394 if ( IC_TRUE(ifx) ) {
4395 pic14_emitcode("jnc","%05d_DS_",tlbl->key+100);
4396 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4398 pic14_emitcode("jc","%05d_DS_",tlbl->key+100);
4399 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4401 pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4404 /* They're not both bit variables. Is the right a literal? */
4405 if(AOP_TYPE(right) == AOP_LIT) {
4406 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4411 switch(lit & 0xff) {
4413 if ( IC_TRUE(ifx) ) {
4414 emitpcode(POC_DECFW,popGet(AOP(left),offset));
4416 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4418 emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4419 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4423 if ( IC_TRUE(ifx) ) {
4424 emitpcode(POC_INCFW,popGet(AOP(left),offset));
4426 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4428 emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4429 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4433 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4435 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4440 /* end of size == 1 */
4444 genc16bit2lit(left,lit,offset);
4447 /* end of size == 2 */
4452 emitpcode(POC_MOVFW,popGet(AOP(left),0));
4453 emitpcode(POC_IORFW,popGet(AOP(left),1));
4454 emitpcode(POC_IORFW,popGet(AOP(left),2));
4455 emitpcode(POC_IORFW,popGet(AOP(left),3));
4459 /* search for patterns that can be optimized */
4461 genc16bit2lit(left,lit,0);
4464 genSkipz(ifx,IC_TRUE(ifx) == NULL);
4466 genc16bit2lit(left,lit,2);
4468 emitpcode(POC_IORFW,popGet(AOP(left),2));
4469 emitpcode(POC_IORFW,popGet(AOP(left),3));
4482 } else if(AOP_TYPE(right) == AOP_CRY ) {
4483 /* we know the left is not a bit, but that the right is */
4484 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4485 emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4486 popGet(AOP(right),offset));
4487 emitpcode(POC_XORLW,popGetLit(1));
4489 /* if the two are equal, then W will be 0 and the Z bit is set
4490 * we could test Z now, or go ahead and check the high order bytes if
4491 * the variable we're comparing is larger than a byte. */
4494 emitpcode(POC_IORFW,popGet(AOP(left),offset));
4496 if ( IC_TRUE(ifx) ) {
4498 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4499 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4502 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4503 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4507 /* They're both variables that are larger than bits */
4510 tlbl = newiTempLabel(NULL);
4513 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4514 emitpcode(POC_XORFW,popGet(AOP(right),offset));
4516 if ( IC_TRUE(ifx) ) {
4519 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
4520 pic14_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4523 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4524 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4528 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4529 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4533 if(s>1 && IC_TRUE(ifx)) {
4534 emitpLabel(tlbl->key);
4535 pic14_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);
4539 /* mark the icode as generated */
4544 /* if they are both bit variables */
4545 if (AOP_TYPE(left) == AOP_CRY &&
4546 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4547 if(AOP_TYPE(right) == AOP_LIT){
4548 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4550 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4551 pic14_emitcode("cpl","c");
4552 } else if(lit == 1L) {
4553 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4555 pic14_emitcode("clr","c");
4557 /* AOP_TYPE(right) == AOP_CRY */
4559 symbol *lbl = newiTempLabel(NULL);
4560 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4561 pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4562 pic14_emitcode("cpl","c");
4563 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4566 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4567 pic14_outBitC(result);
4571 genIfxJump (ifx,"c");
4574 /* if the result is used in an arithmetic operation
4575 then put the result in place */
4576 pic14_outBitC(result);
4579 gencjne(left,right,result,ifx);
4582 gencjne(left,right,newiTempLabel(NULL));
4584 if(IC_TRUE(ifx)->key)
4585 gencjne(left,right,IC_TRUE(ifx)->key);
4587 gencjne(left,right,IC_FALSE(ifx)->key);
4591 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4592 aopPut(AOP(result),"a",0);
4597 genIfxJump (ifx,"a");
4601 /* if the result is used in an arithmetic operation
4602 then put the result in place */
4604 if (AOP_TYPE(result) != AOP_CRY)
4605 pic14_outAcc(result);
4607 /* leave the result in acc */
4611 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4612 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4613 freeAsmop(result,NULL,ic,TRUE);
4616 /*-----------------------------------------------------------------*/
4617 /* ifxForOp - returns the icode containing the ifx for operand */
4618 /*-----------------------------------------------------------------*/
4619 static iCode *ifxForOp ( operand *op, iCode *ic )
4621 /* if true symbol then needs to be assigned */
4622 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4623 if (IS_TRUE_SYMOP(op))
4626 /* if this has register type condition and
4627 the next instruction is ifx with the same operand
4628 and live to of the operand is upto the ifx only then */
4630 ic->next->op == IFX &&
4631 IC_COND(ic->next)->key == op->key &&
4632 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4636 ic->next->op == IFX &&
4637 IC_COND(ic->next)->key == op->key) {
4638 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
4642 DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
4644 ic->next->op == IFX)
4645 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
4648 ic->next->op == IFX &&
4649 IC_COND(ic->next)->key == op->key) {
4650 DEBUGpic14_emitcode ("; "," key is okay");
4651 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
4652 OP_SYMBOL(op)->liveTo,
4659 /*-----------------------------------------------------------------*/
4660 /* genAndOp - for && operation */
4661 /*-----------------------------------------------------------------*/
4662 static void genAndOp (iCode *ic)
4664 operand *left,*right, *result;
4667 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4668 /* note here that && operations that are in an
4669 if statement are taken away by backPatchLabels
4670 only those used in arthmetic operations remain */
4671 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4672 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4673 aopOp((result=IC_RESULT(ic)),ic,FALSE);
4675 /* if both are bit variables */
4676 if (AOP_TYPE(left) == AOP_CRY &&
4677 AOP_TYPE(right) == AOP_CRY ) {
4678 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4679 pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4680 pic14_outBitC(result);
4682 tlbl = newiTempLabel(NULL);
4683 pic14_toBoolean(left);
4684 pic14_emitcode("jz","%05d_DS_",tlbl->key+100);
4685 pic14_toBoolean(right);
4686 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4687 pic14_outBitAcc(result);
4690 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4691 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4692 freeAsmop(result,NULL,ic,TRUE);
4696 /*-----------------------------------------------------------------*/
4697 /* genOrOp - for || operation */
4698 /*-----------------------------------------------------------------*/
4701 modified this code, but it doesn't appear to ever get called
4704 static void genOrOp (iCode *ic)
4706 operand *left,*right, *result;
4709 /* note here that || operations that are in an
4710 if statement are taken away by backPatchLabels
4711 only those used in arthmetic operations remain */
4712 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4713 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4714 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4715 aopOp((result=IC_RESULT(ic)),ic,FALSE);
4717 DEBUGpic14_AopType(__LINE__,left,right,result);
4719 /* if both are bit variables */
4720 if (AOP_TYPE(left) == AOP_CRY &&
4721 AOP_TYPE(right) == AOP_CRY ) {
4722 pic14_emitcode("clrc","");
4723 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
4724 AOP(left)->aopu.aop_dir,
4725 AOP(left)->aopu.aop_dir);
4726 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
4727 AOP(right)->aopu.aop_dir,
4728 AOP(right)->aopu.aop_dir);
4729 pic14_emitcode("setc","");
4732 tlbl = newiTempLabel(NULL);
4733 pic14_toBoolean(left);
4735 pic14_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
4736 pic14_toBoolean(right);
4737 pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4739 pic14_outBitAcc(result);
4742 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4743 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4744 freeAsmop(result,NULL,ic,TRUE);
4747 /*-----------------------------------------------------------------*/
4748 /* isLiteralBit - test if lit == 2^n */
4749 /*-----------------------------------------------------------------*/
4750 static int isLiteralBit(unsigned long lit)
4752 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4753 0x100L,0x200L,0x400L,0x800L,
4754 0x1000L,0x2000L,0x4000L,0x8000L,
4755 0x10000L,0x20000L,0x40000L,0x80000L,
4756 0x100000L,0x200000L,0x400000L,0x800000L,
4757 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4758 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4761 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4762 for(idx = 0; idx < 32; idx++)
4768 /*-----------------------------------------------------------------*/
4769 /* continueIfTrue - */
4770 /*-----------------------------------------------------------------*/
4771 static void continueIfTrue (iCode *ic)
4773 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4775 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4779 /*-----------------------------------------------------------------*/
4781 /*-----------------------------------------------------------------*/
4782 static void jumpIfTrue (iCode *ic)
4784 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4786 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4790 /*-----------------------------------------------------------------*/
4791 /* jmpTrueOrFalse - */
4792 /*-----------------------------------------------------------------*/
4793 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4795 // ugly but optimized by peephole
4796 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4798 symbol *nlbl = newiTempLabel(NULL);
4799 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);
4800 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4801 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4802 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
4805 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4806 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4811 /*-----------------------------------------------------------------*/
4812 /* genAnd - code for and */
4813 /*-----------------------------------------------------------------*/
4814 static void genAnd (iCode *ic, iCode *ifx)
4816 operand *left, *right, *result;
4818 unsigned long lit = 0L;
4823 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4824 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4825 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4826 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4828 resolveIfx(&rIfx,ifx);
4830 /* if left is a literal & right is not then exchange them */
4831 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4832 AOP_NEEDSACC(left)) {
4833 operand *tmp = right ;
4838 /* if result = right then exchange them */
4839 if(pic14_sameRegs(AOP(result),AOP(right))){
4840 operand *tmp = right ;
4845 /* if right is bit then exchange them */
4846 if (AOP_TYPE(right) == AOP_CRY &&
4847 AOP_TYPE(left) != AOP_CRY){
4848 operand *tmp = right ;
4852 if(AOP_TYPE(right) == AOP_LIT)
4853 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4855 size = AOP_SIZE(result);
4857 DEBUGpic14_AopType(__LINE__,left,right,result);
4860 // result = bit & yy;
4861 if (AOP_TYPE(left) == AOP_CRY){
4862 // c = bit & literal;
4863 if(AOP_TYPE(right) == AOP_LIT){
4865 if(size && pic14_sameRegs(AOP(result),AOP(left)))
4868 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4871 if(size && (AOP_TYPE(result) == AOP_CRY)){
4872 pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4875 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4879 pic14_emitcode("clr","c");
4882 if (AOP_TYPE(right) == AOP_CRY){
4884 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4885 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4888 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
4890 pic14_emitcode("rrc","a");
4891 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4897 pic14_outBitC(result);
4899 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4900 genIfxJump(ifx, "c");
4904 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4905 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4906 if((AOP_TYPE(right) == AOP_LIT) &&
4907 (AOP_TYPE(result) == AOP_CRY) &&
4908 (AOP_TYPE(left) != AOP_CRY)){
4909 int posbit = isLiteralBit(lit);
4913 //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
4916 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
4922 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
4923 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
4925 emitpcode(POC_BTFSS,newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
4926 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
4929 emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
4930 newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
4931 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4938 symbol *tlbl = newiTempLabel(NULL);
4939 int sizel = AOP_SIZE(left);
4941 pic14_emitcode("setb","c");
4943 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4944 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
4946 if((posbit = isLiteralBit(bytelit)) != 0)
4947 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
4949 if(bytelit != 0x0FFL)
4950 pic14_emitcode("anl","a,%s",
4951 aopGet(AOP(right),offset,FALSE,TRUE));
4952 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
4957 // bit = left & literal
4959 pic14_emitcode("clr","c");
4960 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4962 // if(left & literal)
4965 jmpTrueOrFalse(ifx, tlbl);
4969 pic14_outBitC(result);
4973 /* if left is same as result */
4974 if(pic14_sameRegs(AOP(result),AOP(left))){
4976 for(;size--; offset++,lit>>=8) {
4977 if(AOP_TYPE(right) == AOP_LIT){
4978 switch(lit & 0xff) {
4980 /* and'ing with 0 has clears the result */
4981 pic14_emitcode("clrf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
4982 emitpcode(POC_CLRF,popGet(AOP(result),offset));
4985 /* and'ing with 0xff is a nop when the result and left are the same */
4990 int p = my_powof2( (~lit) & 0xff );
4992 /* only one bit is set in the literal, so use a bcf instruction */
4993 pic14_emitcode("bcf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
4994 emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
4997 pic14_emitcode("movlw","0x%x", (lit & 0xff));
4998 pic14_emitcode("andwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE));
4999 if(know_W != (lit&0xff))
5000 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5002 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5007 if (AOP_TYPE(left) == AOP_ACC) {
5008 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5010 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5011 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5018 // left & result in different registers
5019 if(AOP_TYPE(result) == AOP_CRY){
5021 // if(size), result in bit
5022 // if(!size && ifx), conditional oper: if(left & right)
5023 symbol *tlbl = newiTempLabel(NULL);
5024 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5026 pic14_emitcode("setb","c");
5028 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5029 pic14_emitcode("anl","a,%s",
5030 aopGet(AOP(left),offset,FALSE,FALSE));
5031 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5036 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5037 pic14_outBitC(result);
5039 jmpTrueOrFalse(ifx, tlbl);
5041 for(;(size--);offset++) {
5043 // result = left & right
5044 if(AOP_TYPE(right) == AOP_LIT){
5045 int t = (lit >> (offset*8)) & 0x0FFL;
5048 pic14_emitcode("clrf","%s",
5049 aopGet(AOP(result),offset,FALSE,FALSE));
5050 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5053 pic14_emitcode("movf","%s,w",
5054 aopGet(AOP(left),offset,FALSE,FALSE));
5055 pic14_emitcode("movwf","%s",
5056 aopGet(AOP(result),offset,FALSE,FALSE));
5057 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5058 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5061 pic14_emitcode("movlw","0x%x",t);
5062 pic14_emitcode("andwf","%s,w",
5063 aopGet(AOP(left),offset,FALSE,FALSE));
5064 pic14_emitcode("movwf","%s",
5065 aopGet(AOP(result),offset,FALSE,FALSE));
5067 emitpcode(POC_MOVLW, popGetLit(t));
5068 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5069 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5074 if (AOP_TYPE(left) == AOP_ACC) {
5075 pic14_emitcode("andwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5076 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5078 pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5079 pic14_emitcode("andwf","%s,w",
5080 aopGet(AOP(left),offset,FALSE,FALSE));
5081 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5082 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5084 pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5085 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5091 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5092 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5093 freeAsmop(result,NULL,ic,TRUE);
5096 /*-----------------------------------------------------------------*/
5097 /* genOr - code for or */
5098 /*-----------------------------------------------------------------*/
5099 static void genOr (iCode *ic, iCode *ifx)
5101 operand *left, *right, *result;
5103 unsigned long lit = 0L;
5105 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5107 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5108 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5109 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5111 DEBUGpic14_AopType(__LINE__,left,right,result);
5113 /* if left is a literal & right is not then exchange them */
5114 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5115 AOP_NEEDSACC(left)) {
5116 operand *tmp = right ;
5121 /* if result = right then exchange them */
5122 if(pic14_sameRegs(AOP(result),AOP(right))){
5123 operand *tmp = right ;
5128 /* if right is bit then exchange them */
5129 if (AOP_TYPE(right) == AOP_CRY &&
5130 AOP_TYPE(left) != AOP_CRY){
5131 operand *tmp = right ;
5136 DEBUGpic14_AopType(__LINE__,left,right,result);
5138 if(AOP_TYPE(right) == AOP_LIT)
5139 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5141 size = AOP_SIZE(result);
5145 if (AOP_TYPE(left) == AOP_CRY){
5146 if(AOP_TYPE(right) == AOP_LIT){
5147 // c = bit & literal;
5149 // lit != 0 => result = 1
5150 if(AOP_TYPE(result) == AOP_CRY){
5152 emitpcode(POC_BSF, popGet(AOP(result),0));
5153 //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5154 // AOP(result)->aopu.aop_dir,
5155 // AOP(result)->aopu.aop_dir);
5157 continueIfTrue(ifx);
5161 // lit == 0 => result = left
5162 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5164 pic14_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5167 if (AOP_TYPE(right) == AOP_CRY){
5168 if(pic14_sameRegs(AOP(result),AOP(left))){
5170 emitpcode(POC_BCF, popGet(AOP(result),0));
5171 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5172 emitpcode(POC_BSF, popGet(AOP(result),0));
5174 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5175 AOP(result)->aopu.aop_dir,
5176 AOP(result)->aopu.aop_dir);
5177 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5178 AOP(right)->aopu.aop_dir,
5179 AOP(right)->aopu.aop_dir);
5180 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5181 AOP(result)->aopu.aop_dir,
5182 AOP(result)->aopu.aop_dir);
5184 if( AOP_TYPE(result) == AOP_ACC) {
5185 emitpcode(POC_MOVLW, popGetLit(0));
5186 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5187 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5188 emitpcode(POC_MOVLW, popGetLit(1));
5192 emitpcode(POC_BCF, popGet(AOP(result),0));
5193 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5194 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5195 emitpcode(POC_BSF, popGet(AOP(result),0));
5197 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5198 AOP(result)->aopu.aop_dir,
5199 AOP(result)->aopu.aop_dir);
5200 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5201 AOP(right)->aopu.aop_dir,
5202 AOP(right)->aopu.aop_dir);
5203 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5204 AOP(left)->aopu.aop_dir,
5205 AOP(left)->aopu.aop_dir);
5206 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5207 AOP(result)->aopu.aop_dir,
5208 AOP(result)->aopu.aop_dir);
5213 symbol *tlbl = newiTempLabel(NULL);
5214 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5217 emitpcode(POC_BCF, popGet(AOP(result),0));
5218 if( AOP_TYPE(right) == AOP_ACC) {
5219 emitpcode(POC_IORLW, popGetLit(0));
5221 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5222 emitpcode(POC_BSF, popGet(AOP(result),0));
5227 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5228 pic14_emitcode(";XXX setb","c");
5229 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5230 AOP(left)->aopu.aop_dir,tlbl->key+100);
5231 pic14_toBoolean(right);
5232 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5233 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5234 jmpTrueOrFalse(ifx, tlbl);
5238 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5245 pic14_outBitC(result);
5247 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5248 genIfxJump(ifx, "c");
5252 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5253 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5254 if((AOP_TYPE(right) == AOP_LIT) &&
5255 (AOP_TYPE(result) == AOP_CRY) &&
5256 (AOP_TYPE(left) != AOP_CRY)){
5258 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5261 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5263 continueIfTrue(ifx);
5266 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5267 // lit = 0, result = boolean(left)
5269 pic14_emitcode(";XXX setb","c");
5270 pic14_toBoolean(right);
5272 symbol *tlbl = newiTempLabel(NULL);
5273 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5275 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5277 genIfxJump (ifx,"a");
5281 pic14_outBitC(result);
5285 /* if left is same as result */
5286 if(pic14_sameRegs(AOP(result),AOP(left))){
5288 for(;size--; offset++,lit>>=8) {
5289 if(AOP_TYPE(right) == AOP_LIT){
5290 if((lit & 0xff) == 0)
5291 /* or'ing with 0 has no effect */
5294 int p = my_powof2(lit & 0xff);
5296 /* only one bit is set in the literal, so use a bsf instruction */
5298 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5300 if(know_W != (lit & 0xff))
5301 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5302 know_W = lit & 0xff;
5303 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5308 if (AOP_TYPE(left) == AOP_ACC) {
5309 emitpcode(POC_IORFW, popGet(AOP(right),offset));
5310 pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5312 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
5313 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5315 pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5316 pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5322 // left & result in different registers
5323 if(AOP_TYPE(result) == AOP_CRY){
5325 // if(size), result in bit
5326 // if(!size && ifx), conditional oper: if(left | right)
5327 symbol *tlbl = newiTempLabel(NULL);
5328 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5329 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5333 pic14_emitcode(";XXX setb","c");
5335 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5336 pic14_emitcode(";XXX orl","a,%s",
5337 aopGet(AOP(left),offset,FALSE,FALSE));
5338 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5343 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5344 pic14_outBitC(result);
5346 jmpTrueOrFalse(ifx, tlbl);
5347 } else for(;(size--);offset++){
5349 // result = left & right
5350 if(AOP_TYPE(right) == AOP_LIT){
5351 int t = (lit >> (offset*8)) & 0x0FFL;
5354 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
5355 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5357 pic14_emitcode("movf","%s,w",
5358 aopGet(AOP(left),offset,FALSE,FALSE));
5359 pic14_emitcode("movwf","%s",
5360 aopGet(AOP(result),offset,FALSE,FALSE));
5363 emitpcode(POC_MOVLW, popGetLit(t));
5364 emitpcode(POC_IORFW, popGet(AOP(left),offset));
5365 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5367 pic14_emitcode("movlw","0x%x",t);
5368 pic14_emitcode("iorwf","%s,w",
5369 aopGet(AOP(left),offset,FALSE,FALSE));
5370 pic14_emitcode("movwf","%s",
5371 aopGet(AOP(result),offset,FALSE,FALSE));
5377 // faster than result <- left, anl result,right
5378 // and better if result is SFR
5379 if (AOP_TYPE(left) == AOP_ACC) {
5380 emitpcode(POC_IORWF, popGet(AOP(right),offset));
5381 pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5383 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
5384 emitpcode(POC_IORFW, popGet(AOP(left),offset));
5386 pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5387 pic14_emitcode("iorwf","%s,w",
5388 aopGet(AOP(left),offset,FALSE,FALSE));
5390 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5391 pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5396 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5397 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5398 freeAsmop(result,NULL,ic,TRUE);
5401 /*-----------------------------------------------------------------*/
5402 /* genXor - code for xclusive or */
5403 /*-----------------------------------------------------------------*/
5404 static void genXor (iCode *ic, iCode *ifx)
5406 operand *left, *right, *result;
5408 unsigned long lit = 0L;
5410 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5412 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5413 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5414 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5416 /* if left is a literal & right is not ||
5417 if left needs acc & right does not */
5418 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5419 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5420 operand *tmp = right ;
5425 /* if result = right then exchange them */
5426 if(pic14_sameRegs(AOP(result),AOP(right))){
5427 operand *tmp = right ;
5432 /* if right is bit then exchange them */
5433 if (AOP_TYPE(right) == AOP_CRY &&
5434 AOP_TYPE(left) != AOP_CRY){
5435 operand *tmp = right ;
5439 if(AOP_TYPE(right) == AOP_LIT)
5440 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5442 size = AOP_SIZE(result);
5446 if (AOP_TYPE(left) == AOP_CRY){
5447 if(AOP_TYPE(right) == AOP_LIT){
5448 // c = bit & literal;
5450 // lit>>1 != 0 => result = 1
5451 if(AOP_TYPE(result) == AOP_CRY){
5453 pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);
5455 continueIfTrue(ifx);
5458 pic14_emitcode("setb","c");
5462 // lit == 0, result = left
5463 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5465 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5467 // lit == 1, result = not(left)
5468 if(size && pic14_sameRegs(AOP(result),AOP(left))){
5469 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5472 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5473 pic14_emitcode("cpl","c");
5480 symbol *tlbl = newiTempLabel(NULL);
5481 if (AOP_TYPE(right) == AOP_CRY){
5483 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5486 int sizer = AOP_SIZE(right);
5488 // if val>>1 != 0, result = 1
5489 pic14_emitcode("setb","c");
5491 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5493 // test the msb of the lsb
5494 pic14_emitcode("anl","a,#0xfe");
5495 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5499 pic14_emitcode("rrc","a");
5501 pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5502 pic14_emitcode("cpl","c");
5503 pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
5508 pic14_outBitC(result);
5510 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5511 genIfxJump(ifx, "c");
5515 if(pic14_sameRegs(AOP(result),AOP(left))){
5516 /* if left is same as result */
5517 for(;size--; offset++) {
5518 if(AOP_TYPE(right) == AOP_LIT){
5519 int t = (lit >> (offset*8)) & 0x0FFL;
5523 if (IS_AOP_PREG(left)) {
5524 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5525 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5526 aopPut(AOP(result),"a",offset);
5528 emitpcode(POC_MOVLW, popGetLit(t));
5529 emitpcode(POC_XORWF,popGet(AOP(left),offset));
5530 pic14_emitcode("xrl","%s,%s",
5531 aopGet(AOP(left),offset,FALSE,TRUE),
5532 aopGet(AOP(right),offset,FALSE,FALSE));
5535 if (AOP_TYPE(left) == AOP_ACC)
5536 pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
5538 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5539 emitpcode(POC_XORWF,popGet(AOP(left),offset));
5541 if (IS_AOP_PREG(left)) {
5542 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5543 aopPut(AOP(result),"a",offset);
5545 pic14_emitcode("xrl","%s,a",
5546 aopGet(AOP(left),offset,FALSE,TRUE));
5552 // left & result in different registers
5553 if(AOP_TYPE(result) == AOP_CRY){
5555 // if(size), result in bit
5556 // if(!size && ifx), conditional oper: if(left ^ right)
5557 symbol *tlbl = newiTempLabel(NULL);
5558 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5560 pic14_emitcode("setb","c");
5562 if((AOP_TYPE(right) == AOP_LIT) &&
5563 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5564 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
5566 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5567 pic14_emitcode("xrl","a,%s",
5568 aopGet(AOP(left),offset,FALSE,FALSE));
5570 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5575 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5576 pic14_outBitC(result);
5578 jmpTrueOrFalse(ifx, tlbl);
5579 } else for(;(size--);offset++){
5581 // result = left & right
5582 if(AOP_TYPE(right) == AOP_LIT){
5583 int t = (lit >> (offset*8)) & 0x0FFL;
5586 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5587 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5588 pic14_emitcode("movf","%s,w",
5589 aopGet(AOP(left),offset,FALSE,FALSE));
5590 pic14_emitcode("movwf","%s",
5591 aopGet(AOP(result),offset,FALSE,FALSE));
5594 emitpcode(POC_COMFW,popGet(AOP(left),offset));
5595 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5596 pic14_emitcode("comf","%s,w",
5597 aopGet(AOP(left),offset,FALSE,FALSE));
5598 pic14_emitcode("movwf","%s",
5599 aopGet(AOP(result),offset,FALSE,FALSE));
5602 emitpcode(POC_MOVLW, popGetLit(t));
5603 emitpcode(POC_XORFW,popGet(AOP(left),offset));
5604 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5605 pic14_emitcode("movlw","0x%x",t);
5606 pic14_emitcode("xorwf","%s,w",
5607 aopGet(AOP(left),offset,FALSE,FALSE));
5608 pic14_emitcode("movwf","%s",
5609 aopGet(AOP(result),offset,FALSE,FALSE));
5615 // faster than result <- left, anl result,right
5616 // and better if result is SFR
5617 if (AOP_TYPE(left) == AOP_ACC) {
5618 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5619 pic14_emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5621 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5622 emitpcode(POC_XORFW,popGet(AOP(left),offset));
5623 pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5624 pic14_emitcode("xorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
5626 if ( AOP_TYPE(result) != AOP_ACC){
5627 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5628 pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5634 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5635 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5636 freeAsmop(result,NULL,ic,TRUE);
5639 /*-----------------------------------------------------------------*/
5640 /* genInline - write the inline code out */
5641 /*-----------------------------------------------------------------*/
5642 static void genInline (iCode *ic)
5644 char *buffer, *bp, *bp1;
5646 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5648 _G.inLine += (!options.asmpeep);
5650 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5651 strcpy(buffer,IC_INLINE(ic));
5653 /* emit each line as a code */
5657 pic14_emitcode(bp1,"");
5664 pic14_emitcode(bp1,"");
5671 pic14_emitcode(bp1,"");
5672 /* pic14_emitcode("",buffer); */
5673 _G.inLine -= (!options.asmpeep);
5676 /*-----------------------------------------------------------------*/
5677 /* genRRC - rotate right with carry */
5678 /*-----------------------------------------------------------------*/
5679 static void genRRC (iCode *ic)
5681 operand *left , *result ;
5682 int size, offset = 0, same;
5684 /* rotate right with carry */
5686 result=IC_RESULT(ic);
5687 aopOp (left,ic,FALSE);
5688 aopOp (result,ic,FALSE);
5690 DEBUGpic14_AopType(__LINE__,left,NULL,result);
5692 same = pic14_sameRegs(AOP(result),AOP(left));
5694 size = AOP_SIZE(result);
5696 /* get the lsb and put it into the carry */
5697 emitpcode(POC_RRFW, popGet(AOP(left),size-1));
5704 emitpcode(POC_RRF, popGet(AOP(left),offset));
5706 emitpcode(POC_RRFW, popGet(AOP(left),offset));
5707 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5713 freeAsmop(left,NULL,ic,TRUE);
5714 freeAsmop(result,NULL,ic,TRUE);
5717 /*-----------------------------------------------------------------*/
5718 /* genRLC - generate code for rotate left with carry */
5719 /*-----------------------------------------------------------------*/
5720 static void genRLC (iCode *ic)
5722 operand *left , *result ;
5723 int size, offset = 0;
5726 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5727 /* rotate right with carry */
5729 result=IC_RESULT(ic);
5730 aopOp (left,ic,FALSE);
5731 aopOp (result,ic,FALSE);
5733 DEBUGpic14_AopType(__LINE__,left,NULL,result);
5735 same = pic14_sameRegs(AOP(result),AOP(left));
5737 /* move it to the result */
5738 size = AOP_SIZE(result);
5740 /* get the msb and put it into the carry */
5741 emitpcode(POC_RLFW, popGet(AOP(left),size-1));
5748 emitpcode(POC_RLF, popGet(AOP(left),offset));
5750 emitpcode(POC_RLFW, popGet(AOP(left),offset));
5751 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5758 freeAsmop(left,NULL,ic,TRUE);
5759 freeAsmop(result,NULL,ic,TRUE);
5762 /*-----------------------------------------------------------------*/
5763 /* genGetHbit - generates code get highest order bit */
5764 /*-----------------------------------------------------------------*/
5765 static void genGetHbit (iCode *ic)
5767 operand *left, *result;
5769 result=IC_RESULT(ic);
5770 aopOp (left,ic,FALSE);
5771 aopOp (result,ic,FALSE);
5773 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5774 /* get the highest order byte into a */
5775 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
5776 if(AOP_TYPE(result) == AOP_CRY){
5777 pic14_emitcode("rlc","a");
5778 pic14_outBitC(result);
5781 pic14_emitcode("rl","a");
5782 pic14_emitcode("anl","a,#0x01");
5783 pic14_outAcc(result);
5787 freeAsmop(left,NULL,ic,TRUE);
5788 freeAsmop(result,NULL,ic,TRUE);
5791 /*-----------------------------------------------------------------*/
5792 /* AccRol - rotate left accumulator by known count */
5793 /*-----------------------------------------------------------------*/
5794 static void AccRol (int shCount)
5796 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5797 shCount &= 0x0007; // shCount : 0..7
5802 pic14_emitcode("rl","a");
5805 pic14_emitcode("rl","a");
5806 pic14_emitcode("rl","a");
5809 pic14_emitcode("swap","a");
5810 pic14_emitcode("rr","a");
5813 pic14_emitcode("swap","a");
5816 pic14_emitcode("swap","a");
5817 pic14_emitcode("rl","a");
5820 pic14_emitcode("rr","a");
5821 pic14_emitcode("rr","a");
5824 pic14_emitcode("rr","a");
5829 /*-----------------------------------------------------------------*/
5830 /* AccLsh - left shift accumulator by known count */
5831 /*-----------------------------------------------------------------*/
5832 static void AccLsh (int shCount)
5834 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5837 pic14_emitcode("add","a,acc");
5840 pic14_emitcode("add","a,acc");
5841 pic14_emitcode("add","a,acc");
5843 /* rotate left accumulator */
5845 /* and kill the lower order bits */
5846 pic14_emitcode("anl","a,#0x%02x", SLMask[shCount]);
5851 /*-----------------------------------------------------------------*/
5852 /* AccRsh - right shift accumulator by known count */
5853 /*-----------------------------------------------------------------*/
5854 static void AccRsh (int shCount)
5856 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5860 pic14_emitcode("rrc","a");
5862 /* rotate right accumulator */
5863 AccRol(8 - shCount);
5864 /* and kill the higher order bits */
5865 pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
5871 /*-----------------------------------------------------------------*/
5872 /* AccSRsh - signed right shift accumulator by known count */
5873 /*-----------------------------------------------------------------*/
5874 static void AccSRsh (int shCount)
5877 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5880 pic14_emitcode("mov","c,acc.7");
5881 pic14_emitcode("rrc","a");
5882 } else if(shCount == 2){
5883 pic14_emitcode("mov","c,acc.7");
5884 pic14_emitcode("rrc","a");
5885 pic14_emitcode("mov","c,acc.7");
5886 pic14_emitcode("rrc","a");
5888 tlbl = newiTempLabel(NULL);
5889 /* rotate right accumulator */
5890 AccRol(8 - shCount);
5891 /* and kill the higher order bits */
5892 pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
5893 pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5894 pic14_emitcode("orl","a,#0x%02x",
5895 (unsigned char)~SRMask[shCount]);
5896 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5901 /*-----------------------------------------------------------------*/
5902 /* shiftR1Left2Result - shift right one byte from left to result */
5903 /*-----------------------------------------------------------------*/
5904 static void shiftR1Left2ResultSigned (operand *left, int offl,
5905 operand *result, int offr,
5910 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5912 same = (left == result) || (AOP(left) == AOP(result));
5916 emitpcode(POC_RLFW, popGet(AOP(left),offl));
5918 emitpcode(POC_RRF, popGet(AOP(result),offr));
5920 emitpcode(POC_RRFW, popGet(AOP(left),offl));
5921 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5931 /*-----------------------------------------------------------------*/
5932 /* shiftR1Left2Result - shift right one byte from left to result */
5933 /*-----------------------------------------------------------------*/
5934 static void shiftR1Left2Result (operand *left, int offl,
5935 operand *result, int offr,
5936 int shCount, int sign)
5940 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5942 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
5944 /* Copy the msb into the carry if signed. */
5946 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
5956 emitpcode(POC_RRF, popGet(AOP(result),offr));
5958 emitpcode(POC_RRFW, popGet(AOP(left),offl));
5959 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5965 emitpcode(POC_RRF, popGet(AOP(result),offr));
5967 emitpcode(POC_RRFW, popGet(AOP(left),offl));
5968 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5971 emitpcode(POC_RRF, popGet(AOP(result),offr));
5976 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
5978 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
5979 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5982 emitpcode(POC_RLFW, popGet(AOP(result),offr));
5983 emitpcode(POC_RLFW, popGet(AOP(result),offr));
5984 emitpcode(POC_ANDLW, popGetLit(0x1f));
5985 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5989 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
5990 emitpcode(POC_ANDLW, popGetLit(0x0f));
5991 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5995 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
5996 emitpcode(POC_ANDLW, popGetLit(0x0f));
5997 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5999 emitpcode(POC_RRF, popGet(AOP(result),offr));
6004 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6005 emitpcode(POC_ANDLW, popGetLit(0x80));
6006 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6007 emitpcode(POC_RLF, popGet(AOP(result),offr));
6008 emitpcode(POC_RLF, popGet(AOP(result),offr));
6013 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6014 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6015 emitpcode(POC_RLF, popGet(AOP(result),offr));
6026 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6028 /* shift right accumulator */
6033 aopPut(AOP(result),"a",offr);
6037 /*-----------------------------------------------------------------*/
6038 /* shiftL1Left2Result - shift left one byte from left to result */
6039 /*-----------------------------------------------------------------*/
6040 static void shiftL1Left2Result (operand *left, int offl,
6041 operand *result, int offr, int shCount)
6046 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6048 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6049 DEBUGpic14_emitcode ("; ***","same = %d",same);
6050 // l = aopGet(AOP(left),offl,FALSE,FALSE);
6052 /* shift left accumulator */
6053 //AccLsh(shCount); // don't comment out just yet...
6054 // aopPut(AOP(result),"a",offr);
6058 /* Shift left 1 bit position */
6059 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6061 emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6063 emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6064 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6068 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6069 emitpcode(POC_ANDLW,popGetLit(0x7e));
6070 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6071 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6074 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6075 emitpcode(POC_ANDLW,popGetLit(0x3e));
6076 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6077 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6078 emitpcode(POC_RLF, popGet(AOP(result),offr));
6081 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6082 emitpcode(POC_ANDLW, popGetLit(0xf0));
6083 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6086 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6087 emitpcode(POC_ANDLW, popGetLit(0xf0));
6088 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6089 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6092 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6093 emitpcode(POC_ANDLW, popGetLit(0x30));
6094 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6095 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6096 emitpcode(POC_RLF, popGet(AOP(result),offr));
6099 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6100 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6101 emitpcode(POC_RRF, popGet(AOP(result),offr));
6105 DEBUGpic14_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6110 /*-----------------------------------------------------------------*/
6111 /* movLeft2Result - move byte from left to result */
6112 /*-----------------------------------------------------------------*/
6113 static void movLeft2Result (operand *left, int offl,
6114 operand *result, int offr, int sign)
6117 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6118 if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6119 l = aopGet(AOP(left),offl,FALSE,FALSE);
6121 if (*l == '@' && (IS_AOP_PREG(result))) {
6122 pic14_emitcode("mov","a,%s",l);
6123 aopPut(AOP(result),"a",offr);
6126 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6127 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6129 //aopPut(AOP(result),l,offr);
6131 /* MSB sign in acc.7 ! */
6132 if(pic14_getDataSize(left) == offl+1){
6133 pic14_emitcode("mov","a,%s",l);
6134 aopPut(AOP(result),"a",offr);
6141 /*-----------------------------------------------------------------*/
6142 /* shiftL2Left2Result - shift left two bytes from left to result */
6143 /*-----------------------------------------------------------------*/
6144 static void shiftL2Left2Result (operand *left, int offl,
6145 operand *result, int offr, int shCount)
6149 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6151 if(pic14_sameRegs(AOP(result), AOP(left))) {
6159 emitpcode(POC_MOVFW,popGet(AOP(result),offr));
6160 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6161 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6165 emitpcode(POC_RLF, popGet(AOP(result),offr));
6166 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6172 emitpcode(POC_MOVLW, popGetLit(0x0f));
6173 emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
6174 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6175 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6176 emitpcode(POC_ANDFW, popGet(AOP(result),offr));
6177 emitpcode(POC_XORWF, popGet(AOP(result),offr));
6178 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6180 emitpcode(POC_RLF, popGet(AOP(result),offr));
6181 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6185 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6186 emitpcode(POC_RRF, popGet(AOP(result),offr));
6187 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6188 emitpcode(POC_RRF, popGet(AOP(result),offr));
6189 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6190 emitpcode(POC_ANDLW,popGetLit(0xc0));
6191 emitpcode(POC_XORFW,popGet(AOP(result),offr));
6192 emitpcode(POC_XORWF,popGet(AOP(result),offr));
6193 emitpcode(POC_XORFW,popGet(AOP(result),offr));
6194 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6197 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6198 emitpcode(POC_RRFW, popGet(AOP(result),offr));
6199 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6200 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6201 emitpcode(POC_RRF, popGet(AOP(result),offr));
6211 /* note, use a mov/add for the shift since the mov has a
6212 chance of getting optimized out */
6213 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6214 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6215 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6216 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6217 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6221 emitpcode(POC_RLF, popGet(AOP(result),offr));
6222 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6228 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6229 emitpcode(POC_ANDLW, popGetLit(0xF0));
6230 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6231 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6232 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6233 emitpcode(POC_ANDLW, popGetLit(0xF0));
6234 emitpcode(POC_XORWF, popGet(AOP(result),offr));
6235 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6239 emitpcode(POC_RLF, popGet(AOP(result),offr));
6240 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6244 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6245 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6246 emitpcode(POC_RRFW, popGet(AOP(result),offl));
6247 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6249 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6250 emitpcode(POC_RRF, popGet(AOP(result),offr));
6251 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6252 emitpcode(POC_ANDLW,popGetLit(0xc0));
6253 emitpcode(POC_XORFW,popGet(AOP(result),offr));
6254 emitpcode(POC_XORWF,popGet(AOP(result),offr));
6255 emitpcode(POC_XORFW,popGet(AOP(result),offr));
6256 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6259 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6260 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6261 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6262 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6263 emitpcode(POC_RRF, popGet(AOP(result),offr));
6268 /*-----------------------------------------------------------------*/
6269 /* shiftR2Left2Result - shift right two bytes from left to result */
6270 /*-----------------------------------------------------------------*/
6271 static void shiftR2Left2Result (operand *left, int offl,
6272 operand *result, int offr,
6273 int shCount, int sign)
6277 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6278 same = pic14_sameRegs(AOP(result), AOP(left));
6280 if(same && ((offl + MSB16) == offr)){
6282 /* don't crash result[offr] */
6283 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6284 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6286 movLeft2Result(left,offl, result, offr, 0);
6287 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6289 /* a:x >> shCount (x = lsb(result))*/
6292 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6294 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6304 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6305 emitpcode(POC_RRF,popGet(AOP(result),offr));
6308 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6309 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6310 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6311 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6316 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6317 emitpcode(POC_RRF,popGet(AOP(result),offr));
6324 emitpcode(POC_MOVLW, popGetLit(0xf0));
6325 emitpcode(POC_ANDWF, popGet(AOP(result),offr));
6326 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6328 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6329 emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
6330 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6331 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6333 emitpcode(POC_SWAPF, popGet(AOP(left),offl));
6334 emitpcode(POC_ANDLW, popGetLit(0x0f));
6335 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6337 emitpcode(POC_SWAPF, popGet(AOP(left),offl+MSB16));
6338 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6339 emitpcode(POC_ANDLW, popGetLit(0xf0));
6340 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6341 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6345 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6346 emitpcode(POC_RRF, popGet(AOP(result),offr));
6354 emitpcode(POC_RLF, popGet(AOP(result),offr));
6355 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6357 emitpcode(POC_RLF, popGet(AOP(result),offr));
6358 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6359 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6360 emitpcode(POC_ANDLW,popGetLit(0x03));
6361 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6362 emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
6363 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6364 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6366 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6367 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6368 emitpcode(POC_RLFW, popGet(AOP(result),offl+MSB16));
6369 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6370 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6371 emitpcode(POC_RLF, popGet(AOP(result),offr));
6372 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6373 emitpcode(POC_ANDLW,popGetLit(0x03));
6374 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6379 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6380 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6381 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6382 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
6383 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6388 /*-----------------------------------------------------------------*/
6389 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
6390 /*-----------------------------------------------------------------*/
6391 static void shiftLLeftOrResult (operand *left, int offl,
6392 operand *result, int offr, int shCount)
6394 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6395 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6396 /* shift left accumulator */
6398 /* or with result */
6399 pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6400 /* back to result */
6401 aopPut(AOP(result),"a",offr);
6404 /*-----------------------------------------------------------------*/
6405 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
6406 /*-----------------------------------------------------------------*/
6407 static void shiftRLeftOrResult (operand *left, int offl,
6408 operand *result, int offr, int shCount)
6410 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6411 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6412 /* shift right accumulator */
6414 /* or with result */
6415 pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6416 /* back to result */
6417 aopPut(AOP(result),"a",offr);
6420 /*-----------------------------------------------------------------*/
6421 /* genlshOne - left shift a one byte quantity by known count */
6422 /*-----------------------------------------------------------------*/
6423 static void genlshOne (operand *result, operand *left, int shCount)
6425 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6426 shiftL1Left2Result(left, LSB, result, LSB, shCount);
6429 /*-----------------------------------------------------------------*/
6430 /* genlshTwo - left shift two bytes by known amount != 0 */
6431 /*-----------------------------------------------------------------*/
6432 static void genlshTwo (operand *result,operand *left, int shCount)
6436 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6437 size = pic14_getDataSize(result);
6439 /* if shCount >= 8 */
6445 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6447 movLeft2Result(left, LSB, result, MSB16, 0);
6449 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
6452 /* 1 <= shCount <= 7 */
6455 shiftL1Left2Result(left, LSB, result, LSB, shCount);
6457 shiftL2Left2Result(left, LSB, result, LSB, shCount);
6461 /*-----------------------------------------------------------------*/
6462 /* shiftLLong - shift left one long from left to result */
6463 /* offl = LSB or MSB16 */
6464 /*-----------------------------------------------------------------*/
6465 static void shiftLLong (operand *left, operand *result, int offr )
6468 int size = AOP_SIZE(result);
6470 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6471 if(size >= LSB+offr){
6472 l = aopGet(AOP(left),LSB,FALSE,FALSE);
6474 pic14_emitcode("add","a,acc");
6475 if (pic14_sameRegs(AOP(left),AOP(result)) &&
6476 size >= MSB16+offr && offr != LSB )
6477 pic14_emitcode("xch","a,%s",
6478 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
6480 aopPut(AOP(result),"a",LSB+offr);
6483 if(size >= MSB16+offr){
6484 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6485 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
6488 pic14_emitcode("rlc","a");
6489 if (pic14_sameRegs(AOP(left),AOP(result)) &&
6490 size >= MSB24+offr && offr != LSB)
6491 pic14_emitcode("xch","a,%s",
6492 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
6494 aopPut(AOP(result),"a",MSB16+offr);
6497 if(size >= MSB24+offr){
6498 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
6499 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
6502 pic14_emitcode("rlc","a");
6503 if (pic14_sameRegs(AOP(left),AOP(result)) &&
6504 size >= MSB32+offr && offr != LSB )
6505 pic14_emitcode("xch","a,%s",
6506 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
6508 aopPut(AOP(result),"a",MSB24+offr);
6511 if(size > MSB32+offr){
6512 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
6513 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
6516 pic14_emitcode("rlc","a");
6517 aopPut(AOP(result),"a",MSB32+offr);
6520 aopPut(AOP(result),zero,LSB);
6523 /*-----------------------------------------------------------------*/
6524 /* genlshFour - shift four byte by a known amount != 0 */
6525 /*-----------------------------------------------------------------*/
6526 static void genlshFour (operand *result, operand *left, int shCount)
6530 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6531 size = AOP_SIZE(result);
6533 /* if shifting more that 3 bytes */
6534 if (shCount >= 24 ) {
6537 /* lowest order of left goes to the highest
6538 order of the destination */
6539 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6541 movLeft2Result(left, LSB, result, MSB32, 0);
6542 aopPut(AOP(result),zero,LSB);
6543 aopPut(AOP(result),zero,MSB16);
6544 aopPut(AOP(result),zero,MSB32);
6548 /* more than two bytes */
6549 else if ( shCount >= 16 ) {
6550 /* lower order two bytes goes to higher order two bytes */
6552 /* if some more remaining */
6554 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6556 movLeft2Result(left, MSB16, result, MSB32, 0);
6557 movLeft2Result(left, LSB, result, MSB24, 0);
6559 aopPut(AOP(result),zero,MSB16);
6560 aopPut(AOP(result),zero,LSB);
6564 /* if more than 1 byte */
6565 else if ( shCount >= 8 ) {
6566 /* lower order three bytes goes to higher order three bytes */
6570 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6572 movLeft2Result(left, LSB, result, MSB16, 0);
6574 else{ /* size = 4 */
6576 movLeft2Result(left, MSB24, result, MSB32, 0);
6577 movLeft2Result(left, MSB16, result, MSB24, 0);
6578 movLeft2Result(left, LSB, result, MSB16, 0);
6579 aopPut(AOP(result),zero,LSB);
6581 else if(shCount == 1)
6582 shiftLLong(left, result, MSB16);
6584 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
6585 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6586 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6587 aopPut(AOP(result),zero,LSB);
6592 /* 1 <= shCount <= 7 */
6593 else if(shCount <= 2){
6594 shiftLLong(left, result, LSB);
6596 shiftLLong(result, result, LSB);
6598 /* 3 <= shCount <= 7, optimize */
6600 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6601 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6602 shiftL2Left2Result(left, LSB, result, LSB, shCount);
6606 /*-----------------------------------------------------------------*/
6607 /* genLeftShiftLiteral - left shifting by known count */
6608 /*-----------------------------------------------------------------*/
6609 static void genLeftShiftLiteral (operand *left,
6614 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6617 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6618 freeAsmop(right,NULL,ic,TRUE);
6620 aopOp(left,ic,FALSE);
6621 aopOp(result,ic,FALSE);
6623 size = getSize(operandType(result));
6626 pic14_emitcode("; shift left ","result %d, left %d",size,
6630 /* I suppose that the left size >= result size */
6633 movLeft2Result(left, size, result, size, 0);
6637 else if(shCount >= (size * 8))
6639 aopPut(AOP(result),zero,size);
6643 genlshOne (result,left,shCount);
6648 genlshTwo (result,left,shCount);
6652 genlshFour (result,left,shCount);
6656 freeAsmop(left,NULL,ic,TRUE);
6657 freeAsmop(result,NULL,ic,TRUE);
6660 /*-----------------------------------------------------------------*/
6661 /* genLeftShift - generates code for left shifting */
6662 /*-----------------------------------------------------------------*/
6663 static void genLeftShift (iCode *ic)
6665 operand *left,*right, *result;
6668 symbol *tlbl , *tlbl1;
6670 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6672 right = IC_RIGHT(ic);
6674 result = IC_RESULT(ic);
6676 aopOp(right,ic,FALSE);
6678 /* if the shift count is known then do it
6679 as efficiently as possible */
6680 if (AOP_TYPE(right) == AOP_LIT) {
6681 genLeftShiftLiteral (left,right,result,ic);
6685 /* shift count is unknown then we have to form
6686 a loop get the loop count in B : Note: we take
6687 only the lower order byte since shifting
6688 more that 32 bits make no sense anyway, ( the
6689 largest size of an object can be only 32 bits ) */
6692 aopOp(left,ic,FALSE);
6693 aopOp(result,ic,FALSE);
6695 /* now move the left to the result if they are not the
6697 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
6698 AOP_SIZE(result) > 1) {
6700 size = AOP_SIZE(result);
6703 l = aopGet(AOP(left),offset,FALSE,TRUE);
6704 if (*l == '@' && (IS_AOP_PREG(result))) {
6706 pic14_emitcode("mov","a,%s",l);
6707 aopPut(AOP(result),"a",offset);
6709 aopPut(AOP(result),l,offset);
6714 size = AOP_SIZE(result);
6716 /* if it is only one byte then */
6718 if(optimized_for_speed) {
6719 emitpcode(POC_SWAPFW, popGet(AOP(left),0));
6720 emitpcode(POC_ANDLW, popGetLit(0xf0));
6721 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
6722 emitpcode(POC_MOVFW, popGet(AOP(left),0));
6723 emitpcode(POC_MOVWF, popGet(AOP(result),0));
6724 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
6725 emitpcode(POC_ADDWF, popGet(AOP(result),0));
6726 emitpcode(POC_RLFW, popGet(AOP(result),0));
6727 emitpcode(POC_ANDLW, popGetLit(0xfe));
6728 emitpcode(POC_ADDFW, popGet(AOP(result),0));
6729 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
6730 emitpcode(POC_ADDWF, popGet(AOP(result),0));
6733 tlbl = newiTempLabel(NULL);
6734 if (!pic14_sameRegs(AOP(left),AOP(result))) {
6735 emitpcode(POC_MOVFW, popGet(AOP(left),0));
6736 emitpcode(POC_MOVWF, popGet(AOP(result),0));
6739 emitpcode(POC_COMFW, popGet(AOP(right),0));
6740 emitpcode(POC_RRF, popGet(AOP(result),0));
6741 emitpLabel(tlbl->key);
6742 emitpcode(POC_RLF, popGet(AOP(result),0));
6743 emitpcode(POC_ADDLW, popGetLit(1));
6745 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
6751 tlbl = newiTempLabel(NULL);
6753 tlbl1 = newiTempLabel(NULL);
6755 reAdjustPreg(AOP(result));
6757 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6758 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6759 l = aopGet(AOP(result),offset,FALSE,FALSE);
6761 pic14_emitcode("add","a,acc");
6762 aopPut(AOP(result),"a",offset++);
6764 l = aopGet(AOP(result),offset,FALSE,FALSE);
6766 pic14_emitcode("rlc","a");
6767 aopPut(AOP(result),"a",offset++);
6769 reAdjustPreg(AOP(result));
6771 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
6772 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6774 freeAsmop (right,NULL,ic,TRUE);
6775 freeAsmop(left,NULL,ic,TRUE);
6776 freeAsmop(result,NULL,ic,TRUE);
6779 /*-----------------------------------------------------------------*/
6780 /* genrshOne - right shift a one byte quantity by known count */
6781 /*-----------------------------------------------------------------*/
6782 static void genrshOne (operand *result, operand *left,
6783 int shCount, int sign)
6785 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6786 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6789 /*-----------------------------------------------------------------*/
6790 /* genrshTwo - right shift two bytes by known amount != 0 */
6791 /*-----------------------------------------------------------------*/
6792 static void genrshTwo (operand *result,operand *left,
6793 int shCount, int sign)
6795 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6796 /* if shCount >= 8 */
6800 shiftR1Left2Result(left, MSB16, result, LSB,
6803 movLeft2Result(left, MSB16, result, LSB, sign);
6805 addSign(result, MSB16, sign);
6807 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
6811 /* 1 <= shCount <= 7 */
6813 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
6816 /*-----------------------------------------------------------------*/
6817 /* shiftRLong - shift right one long from left to result */
6818 /* offl = LSB or MSB16 */
6819 /*-----------------------------------------------------------------*/
6820 static void shiftRLong (operand *left, int offl,
6821 operand *result, int sign)
6823 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6825 pic14_emitcode("clr","c");
6826 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
6828 pic14_emitcode("mov","c,acc.7");
6829 pic14_emitcode("rrc","a");
6830 aopPut(AOP(result),"a",MSB32-offl);
6832 /* add sign of "a" */
6833 addSign(result, MSB32, sign);
6835 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
6836 pic14_emitcode("rrc","a");
6837 aopPut(AOP(result),"a",MSB24-offl);
6839 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
6840 pic14_emitcode("rrc","a");
6841 aopPut(AOP(result),"a",MSB16-offl);
6844 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
6845 pic14_emitcode("rrc","a");
6846 aopPut(AOP(result),"a",LSB);
6850 /*-----------------------------------------------------------------*/
6851 /* genrshFour - shift four byte by a known amount != 0 */
6852 /*-----------------------------------------------------------------*/
6853 static void genrshFour (operand *result, operand *left,
6854 int shCount, int sign)
6856 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6857 /* if shifting more that 3 bytes */
6858 if(shCount >= 24 ) {
6861 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6863 movLeft2Result(left, MSB32, result, LSB, sign);
6864 addSign(result, MSB16, sign);
6866 else if(shCount >= 16){
6869 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6871 movLeft2Result(left, MSB24, result, LSB, 0);
6872 movLeft2Result(left, MSB32, result, MSB16, sign);
6874 addSign(result, MSB24, sign);
6876 else if(shCount >= 8){
6879 shiftRLong(left, MSB16, result, sign);
6880 else if(shCount == 0){
6881 movLeft2Result(left, MSB16, result, LSB, 0);
6882 movLeft2Result(left, MSB24, result, MSB16, 0);
6883 movLeft2Result(left, MSB32, result, MSB24, sign);
6884 addSign(result, MSB32, sign);
6887 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6888 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6889 /* the last shift is signed */
6890 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6891 addSign(result, MSB32, sign);
6894 else{ /* 1 <= shCount <= 7 */
6896 shiftRLong(left, LSB, result, sign);
6898 shiftRLong(result, LSB, result, sign);
6901 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6902 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6903 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6908 /*-----------------------------------------------------------------*/
6909 /* genRightShiftLiteral - right shifting by known count */
6910 /*-----------------------------------------------------------------*/
6911 static void genRightShiftLiteral (operand *left,
6917 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6920 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6921 freeAsmop(right,NULL,ic,TRUE);
6923 aopOp(left,ic,FALSE);
6924 aopOp(result,ic,FALSE);
6927 pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6931 size = pic14_getDataSize(left);
6932 /* test the LEFT size !!! */
6934 /* I suppose that the left size >= result size */
6936 size = pic14_getDataSize(result);
6938 movLeft2Result(left, size, result, size, 0);
6941 else if(shCount >= (size * 8)){
6943 /* get sign in acc.7 */
6944 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
6945 addSign(result, LSB, sign);
6949 genrshOne (result,left,shCount,sign);
6953 genrshTwo (result,left,shCount,sign);
6957 genrshFour (result,left,shCount,sign);
6963 freeAsmop(left,NULL,ic,TRUE);
6964 freeAsmop(result,NULL,ic,TRUE);
6968 /*-----------------------------------------------------------------*/
6969 /* genSignedRightShift - right shift of signed number */
6970 /*-----------------------------------------------------------------*/
6971 static void genSignedRightShift (iCode *ic)
6973 operand *right, *left, *result;
6976 symbol *tlbl, *tlbl1 ;
6978 /* we do it the hard way put the shift count in b
6979 and loop thru preserving the sign */
6980 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6982 right = IC_RIGHT(ic);
6984 result = IC_RESULT(ic);
6986 aopOp(right,ic,FALSE);
6989 if ( AOP_TYPE(right) == AOP_LIT) {
6990 genRightShiftLiteral (left,right,result,ic,1);
6993 /* shift count is unknown then we have to form
6994 a loop get the loop count in B : Note: we take
6995 only the lower order byte since shifting
6996 more that 32 bits make no sense anyway, ( the
6997 largest size of an object can be only 32 bits ) */
6999 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7000 pic14_emitcode("inc","b");
7001 freeAsmop (right,NULL,ic,TRUE);
7002 aopOp(left,ic,FALSE);
7003 aopOp(result,ic,FALSE);
7005 /* now move the left to the result if they are not the
7007 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
7008 AOP_SIZE(result) > 1) {
7010 size = AOP_SIZE(result);
7013 l = aopGet(AOP(left),offset,FALSE,TRUE);
7014 if (*l == '@' && IS_AOP_PREG(result)) {
7016 pic14_emitcode("mov","a,%s",l);
7017 aopPut(AOP(result),"a",offset);
7019 aopPut(AOP(result),l,offset);
7024 /* mov the highest order bit to OVR */
7025 tlbl = newiTempLabel(NULL);
7026 tlbl1= newiTempLabel(NULL);
7028 size = AOP_SIZE(result);
7030 pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
7031 pic14_emitcode("rlc","a");
7032 pic14_emitcode("mov","ov,c");
7033 /* if it is only one byte then */
7035 l = aopGet(AOP(left),0,FALSE,FALSE);
7037 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7038 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7039 pic14_emitcode("mov","c,ov");
7040 pic14_emitcode("rrc","a");
7041 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7042 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7043 aopPut(AOP(result),"a",0);
7047 reAdjustPreg(AOP(result));
7048 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7049 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7050 pic14_emitcode("mov","c,ov");
7052 l = aopGet(AOP(result),offset,FALSE,FALSE);
7054 pic14_emitcode("rrc","a");
7055 aopPut(AOP(result),"a",offset--);
7057 reAdjustPreg(AOP(result));
7058 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7059 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7062 freeAsmop(left,NULL,ic,TRUE);
7063 freeAsmop(result,NULL,ic,TRUE);
7066 /*-----------------------------------------------------------------*/
7067 /* genRightShift - generate code for right shifting */
7068 /*-----------------------------------------------------------------*/
7069 static void genRightShift (iCode *ic)
7071 operand *right, *left, *result;
7075 symbol *tlbl, *tlbl1 ;
7077 /* if signed then we do it the hard way preserve the
7078 sign bit moving it inwards */
7079 retype = getSpec(operandType(IC_RESULT(ic)));
7080 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7082 if (!SPEC_USIGN(retype)) {
7083 genSignedRightShift (ic);
7087 /* signed & unsigned types are treated the same : i.e. the
7088 signed is NOT propagated inwards : quoting from the
7089 ANSI - standard : "for E1 >> E2, is equivalent to division
7090 by 2**E2 if unsigned or if it has a non-negative value,
7091 otherwise the result is implementation defined ", MY definition
7092 is that the sign does not get propagated */
7094 right = IC_RIGHT(ic);
7096 result = IC_RESULT(ic);
7098 aopOp(right,ic,FALSE);
7100 /* if the shift count is known then do it
7101 as efficiently as possible */
7102 if (AOP_TYPE(right) == AOP_LIT) {
7103 genRightShiftLiteral (left,right,result,ic, 0);
7107 /* shift count is unknown then we have to form
7108 a loop get the loop count in B : Note: we take
7109 only the lower order byte since shifting
7110 more that 32 bits make no sense anyway, ( the
7111 largest size of an object can be only 32 bits ) */
7113 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7114 pic14_emitcode("inc","b");
7115 aopOp(left,ic,FALSE);
7116 aopOp(result,ic,FALSE);
7118 /* now move the left to the result if they are not the
7120 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
7121 AOP_SIZE(result) > 1) {
7123 size = AOP_SIZE(result);
7126 l = aopGet(AOP(left),offset,FALSE,TRUE);
7127 if (*l == '@' && IS_AOP_PREG(result)) {
7129 pic14_emitcode("mov","a,%s",l);
7130 aopPut(AOP(result),"a",offset);
7132 aopPut(AOP(result),l,offset);
7137 tlbl = newiTempLabel(NULL);
7138 tlbl1= newiTempLabel(NULL);
7139 size = AOP_SIZE(result);
7142 /* if it is only one byte then */
7145 l = aopGet(AOP(left),0,FALSE,FALSE);
7147 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7148 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7150 pic14_emitcode("rrc","a");
7151 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7152 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7153 aopPut(AOP(result),"a",0);
7155 tlbl = newiTempLabel(NULL);
7156 if (!pic14_sameRegs(AOP(left),AOP(result))) {
7157 emitpcode(POC_MOVFW, popGet(AOP(left),0));
7158 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7161 emitpcode(POC_COMFW, popGet(AOP(right),0));
7162 emitpcode(POC_RLF, popGet(AOP(result),0));
7163 emitpLabel(tlbl->key);
7164 emitpcode(POC_RRF, popGet(AOP(result),0));
7165 emitpcode(POC_ADDLW, popGetLit(1));
7167 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7172 reAdjustPreg(AOP(result));
7173 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7174 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7177 l = aopGet(AOP(result),offset,FALSE,FALSE);
7179 pic14_emitcode("rrc","a");
7180 aopPut(AOP(result),"a",offset--);
7182 reAdjustPreg(AOP(result));
7184 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7185 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7188 freeAsmop(left,NULL,ic,TRUE);
7189 freeAsmop (right,NULL,ic,TRUE);
7190 freeAsmop(result,NULL,ic,TRUE);
7193 /*-----------------------------------------------------------------*/
7194 /* genUnpackBits - generates code for unpacking bits */
7195 /*-----------------------------------------------------------------*/
7196 static void genUnpackBits (operand *result, char *rname, int ptype)
7203 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7204 etype = getSpec(operandType(result));
7206 /* read the first byte */
7211 pic14_emitcode("mov","a,@%s",rname);
7215 pic14_emitcode("movx","a,@%s",rname);
7219 pic14_emitcode("movx","a,@dptr");
7223 pic14_emitcode("clr","a");
7224 pic14_emitcode("movc","a","@a+dptr");
7228 pic14_emitcode("lcall","__gptrget");
7232 /* if we have bitdisplacement then it fits */
7233 /* into this byte completely or if length is */
7234 /* less than a byte */
7235 if ((shCnt = SPEC_BSTR(etype)) ||
7236 (SPEC_BLEN(etype) <= 8)) {
7238 /* shift right acc */
7241 pic14_emitcode("anl","a,#0x%02x",
7242 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
7243 aopPut(AOP(result),"a",offset);
7247 /* bit field did not fit in a byte */
7248 rlen = SPEC_BLEN(etype) - 8;
7249 aopPut(AOP(result),"a",offset++);
7256 pic14_emitcode("inc","%s",rname);
7257 pic14_emitcode("mov","a,@%s",rname);
7261 pic14_emitcode("inc","%s",rname);
7262 pic14_emitcode("movx","a,@%s",rname);
7266 pic14_emitcode("inc","dptr");
7267 pic14_emitcode("movx","a,@dptr");
7271 pic14_emitcode("clr","a");
7272 pic14_emitcode("inc","dptr");
7273 pic14_emitcode("movc","a","@a+dptr");
7277 pic14_emitcode("inc","dptr");
7278 pic14_emitcode("lcall","__gptrget");
7283 /* if we are done */
7287 aopPut(AOP(result),"a",offset++);
7292 pic14_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
7293 aopPut(AOP(result),"a",offset);
7300 /*-----------------------------------------------------------------*/
7301 /* genDataPointerGet - generates code when ptr offset is known */
7302 /*-----------------------------------------------------------------*/
7303 static void genDataPointerGet (operand *left,
7307 int size , offset = 0;
7310 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7313 /* optimization - most of the time, left and result are the same
7314 * address, but different types. for the pic code, we could omit
7318 aopOp(result,ic,TRUE);
7320 emitpcode(POC_MOVFW, popGet(AOP(left),0));
7322 size = AOP_SIZE(result);
7325 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7329 freeAsmop(left,NULL,ic,TRUE);
7330 freeAsmop(result,NULL,ic,TRUE);
7333 /*-----------------------------------------------------------------*/
7334 /* genNearPointerGet - pic14_emitcode for near pointer fetch */
7335 /*-----------------------------------------------------------------*/
7336 static void genNearPointerGet (operand *left,
7343 sym_link *rtype, *retype;
7344 sym_link *ltype = operandType(left);
7347 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7349 rtype = operandType(result);
7350 retype= getSpec(rtype);
7352 aopOp(left,ic,FALSE);
7354 /* if left is rematerialisable and
7355 result is not bit variable type and
7356 the left is pointer to data space i.e
7357 lower 128 bytes of space */
7358 if (AOP_TYPE(left) == AOP_IMMD &&
7359 !IS_BITVAR(retype) &&
7360 DCL_TYPE(ltype) == POINTER) {
7361 genDataPointerGet (left,result,ic);
7365 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7367 /* if the value is already in a pointer register
7368 then don't need anything more */
7369 if (!AOP_INPREG(AOP(left))) {
7370 /* otherwise get a free pointer register */
7371 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7373 preg = getFreePtr(ic,&aop,FALSE);
7374 pic14_emitcode("mov","%s,%s",
7376 aopGet(AOP(left),0,FALSE,TRUE));
7377 rname = preg->name ;
7379 rname = aopGet(AOP(left),0,FALSE,FALSE);
7381 freeAsmop(left,NULL,ic,TRUE);
7382 aopOp (result,ic,FALSE);
7384 /* if bitfield then unpack the bits */
7385 if (IS_BITVAR(retype))
7386 genUnpackBits (result,rname,POINTER);
7388 /* we have can just get the values */
7389 int size = AOP_SIZE(result);
7392 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7394 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
7396 pic14_emitcode("mov","a,@%s",rname);
7397 aopPut(AOP(result),"a",offset);
7399 sprintf(buffer,"@%s",rname);
7400 aopPut(AOP(result),buffer,offset);
7404 pic14_emitcode("inc","%s",rname);
7408 /* now some housekeeping stuff */
7410 /* we had to allocate for this iCode */
7411 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7412 freeAsmop(NULL,aop,ic,TRUE);
7414 /* we did not allocate which means left
7415 already in a pointer register, then
7416 if size > 0 && this could be used again
7417 we have to point it back to where it
7419 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7420 if (AOP_SIZE(result) > 1 &&
7421 !OP_SYMBOL(left)->remat &&
7422 ( OP_SYMBOL(left)->liveTo > ic->seq ||
7424 int size = AOP_SIZE(result) - 1;
7426 pic14_emitcode("dec","%s",rname);
7431 freeAsmop(result,NULL,ic,TRUE);
7435 /*-----------------------------------------------------------------*/
7436 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch */
7437 /*-----------------------------------------------------------------*/
7438 static void genPagedPointerGet (operand *left,
7445 sym_link *rtype, *retype;
7447 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7449 rtype = operandType(result);
7450 retype= getSpec(rtype);
7452 aopOp(left,ic,FALSE);
7454 /* if the value is already in a pointer register
7455 then don't need anything more */
7456 if (!AOP_INPREG(AOP(left))) {
7457 /* otherwise get a free pointer register */
7459 preg = getFreePtr(ic,&aop,FALSE);
7460 pic14_emitcode("mov","%s,%s",
7462 aopGet(AOP(left),0,FALSE,TRUE));
7463 rname = preg->name ;
7465 rname = aopGet(AOP(left),0,FALSE,FALSE);
7467 freeAsmop(left,NULL,ic,TRUE);
7468 aopOp (result,ic,FALSE);
7470 /* if bitfield then unpack the bits */
7471 if (IS_BITVAR(retype))
7472 genUnpackBits (result,rname,PPOINTER);
7474 /* we have can just get the values */
7475 int size = AOP_SIZE(result);
7480 pic14_emitcode("movx","a,@%s",rname);
7481 aopPut(AOP(result),"a",offset);
7486 pic14_emitcode("inc","%s",rname);
7490 /* now some housekeeping stuff */
7492 /* we had to allocate for this iCode */
7493 freeAsmop(NULL,aop,ic,TRUE);
7495 /* we did not allocate which means left
7496 already in a pointer register, then
7497 if size > 0 && this could be used again
7498 we have to point it back to where it
7500 if (AOP_SIZE(result) > 1 &&
7501 !OP_SYMBOL(left)->remat &&
7502 ( OP_SYMBOL(left)->liveTo > ic->seq ||
7504 int size = AOP_SIZE(result) - 1;
7506 pic14_emitcode("dec","%s",rname);
7511 freeAsmop(result,NULL,ic,TRUE);
7516 /*-----------------------------------------------------------------*/
7517 /* genFarPointerGet - gget value from far space */
7518 /*-----------------------------------------------------------------*/
7519 static void genFarPointerGet (operand *left,
7520 operand *result, iCode *ic)
7523 sym_link *retype = getSpec(operandType(result));
7525 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7527 aopOp(left,ic,FALSE);
7529 /* if the operand is already in dptr
7530 then we do nothing else we move the value to dptr */
7531 if (AOP_TYPE(left) != AOP_STR) {
7532 /* if this is remateriazable */
7533 if (AOP_TYPE(left) == AOP_IMMD)
7534 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7535 else { /* we need to get it byte by byte */
7536 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7537 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7538 if (options.model == MODEL_FLAT24)
7540 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7544 /* so dptr know contains the address */
7545 freeAsmop(left,NULL,ic,TRUE);
7546 aopOp(result,ic,FALSE);
7548 /* if bit then unpack */
7549 if (IS_BITVAR(retype))
7550 genUnpackBits(result,"dptr",FPOINTER);
7552 size = AOP_SIZE(result);
7556 pic14_emitcode("movx","a,@dptr");
7557 aopPut(AOP(result),"a",offset++);
7559 pic14_emitcode("inc","dptr");
7563 freeAsmop(result,NULL,ic,TRUE);
7566 /*-----------------------------------------------------------------*/
7567 /* pic14_emitcodePointerGet - gget value from code space */
7568 /*-----------------------------------------------------------------*/
7569 static void pic14_emitcodePointerGet (operand *left,
7570 operand *result, iCode *ic)
7573 sym_link *retype = getSpec(operandType(result));
7575 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7577 aopOp(left,ic,FALSE);
7579 /* if the operand is already in dptr
7580 then we do nothing else we move the value to dptr */
7581 if (AOP_TYPE(left) != AOP_STR) {
7582 /* if this is remateriazable */
7583 if (AOP_TYPE(left) == AOP_IMMD)
7584 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7585 else { /* we need to get it byte by byte */
7586 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7587 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7588 if (options.model == MODEL_FLAT24)
7590 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7594 /* so dptr know contains the address */
7595 freeAsmop(left,NULL,ic,TRUE);
7596 aopOp(result,ic,FALSE);
7598 /* if bit then unpack */
7599 if (IS_BITVAR(retype))
7600 genUnpackBits(result,"dptr",CPOINTER);
7602 size = AOP_SIZE(result);
7606 pic14_emitcode("clr","a");
7607 pic14_emitcode("movc","a,@a+dptr");
7608 aopPut(AOP(result),"a",offset++);
7610 pic14_emitcode("inc","dptr");
7614 freeAsmop(result,NULL,ic,TRUE);
7617 /*-----------------------------------------------------------------*/
7618 /* genGenPointerGet - gget value from generic pointer space */
7619 /*-----------------------------------------------------------------*/
7620 static void genGenPointerGet (operand *left,
7621 operand *result, iCode *ic)
7624 sym_link *retype = getSpec(operandType(result));
7626 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7627 aopOp(left,ic,FALSE);
7628 aopOp(result,ic,FALSE);
7631 DEBUGpic14_AopType(__LINE__,left,NULL,result);
7633 /* if the operand is already in dptr
7634 then we do nothing else we move the value to dptr */
7635 if (AOP_TYPE(left) != AOP_STR) {
7636 /* if this is remateriazable */
7637 if (AOP_TYPE(left) == AOP_IMMD) {
7638 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7639 pic14_emitcode("mov","b,#%d",pointerCode(retype));
7641 else { /* we need to get it byte by byte */
7643 emitpcode(POC_MOVFW,popGet(AOP(left),0));
7644 emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
7646 size = AOP_SIZE(result);
7650 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
7651 emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
7653 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
7658 /* so dptr know contains the address */
7660 /* if bit then unpack */
7661 if (IS_BITVAR(retype))
7662 genUnpackBits(result,"dptr",GPOINTER);
7665 freeAsmop(left,NULL,ic,TRUE);
7666 freeAsmop(result,NULL,ic,TRUE);
7670 /*-----------------------------------------------------------------*/
7671 /* genPointerGet - generate code for pointer get */
7672 /*-----------------------------------------------------------------*/
7673 static void genPointerGet (iCode *ic)
7675 operand *left, *result ;
7676 sym_link *type, *etype;
7679 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7682 result = IC_RESULT(ic) ;
7684 /* depending on the type of pointer we need to
7685 move it to the correct pointer register */
7686 type = operandType(left);
7687 etype = getSpec(type);
7688 /* if left is of type of pointer then it is simple */
7689 if (IS_PTR(type) && !IS_FUNC(type->next))
7690 p_type = DCL_TYPE(type);
7692 /* we have to go by the storage class */
7693 p_type = PTR_TYPE(SPEC_OCLS(etype));
7695 /* if (SPEC_OCLS(etype)->codesp ) { */
7696 /* p_type = CPOINTER ; */
7699 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7700 /* p_type = FPOINTER ; */
7702 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7703 /* p_type = PPOINTER; */
7705 /* if (SPEC_OCLS(etype) == idata ) */
7706 /* p_type = IPOINTER; */
7708 /* p_type = POINTER ; */
7711 /* now that we have the pointer type we assign
7712 the pointer values */
7717 genNearPointerGet (left,result,ic);
7721 genPagedPointerGet(left,result,ic);
7725 genFarPointerGet (left,result,ic);
7729 pic14_emitcodePointerGet (left,result,ic);
7733 genGenPointerGet (left,result,ic);
7739 /*-----------------------------------------------------------------*/
7740 /* genPackBits - generates code for packed bit storage */
7741 /*-----------------------------------------------------------------*/
7742 static void genPackBits (sym_link *etype ,
7744 char *rname, int p_type)
7752 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7753 blen = SPEC_BLEN(etype);
7754 bstr = SPEC_BSTR(etype);
7756 l = aopGet(AOP(right),offset++,FALSE,FALSE);
7759 /* if the bit lenth is less than or */
7760 /* it exactly fits a byte then */
7761 if (SPEC_BLEN(etype) <= 8 ) {
7762 shCount = SPEC_BSTR(etype) ;
7764 /* shift left acc */
7767 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
7772 pic14_emitcode ("mov","b,a");
7773 pic14_emitcode("mov","a,@%s",rname);
7777 pic14_emitcode ("mov","b,a");
7778 pic14_emitcode("movx","a,@dptr");
7782 pic14_emitcode ("push","b");
7783 pic14_emitcode ("push","acc");
7784 pic14_emitcode ("lcall","__gptrget");
7785 pic14_emitcode ("pop","b");
7789 pic14_emitcode ("anl","a,#0x%02x",(unsigned char)
7790 ((unsigned char)(0xFF << (blen+bstr)) |
7791 (unsigned char)(0xFF >> (8-bstr)) ) );
7792 pic14_emitcode ("orl","a,b");
7793 if (p_type == GPOINTER)
7794 pic14_emitcode("pop","b");
7800 pic14_emitcode("mov","@%s,a",rname);
7804 pic14_emitcode("movx","@dptr,a");
7808 DEBUGpic14_emitcode(";lcall","__gptrput");
7813 if ( SPEC_BLEN(etype) <= 8 )
7816 pic14_emitcode("inc","%s",rname);
7817 rLen = SPEC_BLEN(etype) ;
7819 /* now generate for lengths greater than one byte */
7822 l = aopGet(AOP(right),offset++,FALSE,TRUE);
7832 pic14_emitcode("mov","@%s,a",rname);
7834 pic14_emitcode("mov","@%s,%s",rname,l);
7839 pic14_emitcode("movx","@dptr,a");
7844 DEBUGpic14_emitcode(";lcall","__gptrput");
7847 pic14_emitcode ("inc","%s",rname);
7852 /* last last was not complete */
7854 /* save the byte & read byte */
7857 pic14_emitcode ("mov","b,a");
7858 pic14_emitcode("mov","a,@%s",rname);
7862 pic14_emitcode ("mov","b,a");
7863 pic14_emitcode("movx","a,@dptr");
7867 pic14_emitcode ("push","b");
7868 pic14_emitcode ("push","acc");
7869 pic14_emitcode ("lcall","__gptrget");
7870 pic14_emitcode ("pop","b");
7874 pic14_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
7875 pic14_emitcode ("orl","a,b");
7878 if (p_type == GPOINTER)
7879 pic14_emitcode("pop","b");
7884 pic14_emitcode("mov","@%s,a",rname);
7888 pic14_emitcode("movx","@dptr,a");
7892 DEBUGpic14_emitcode(";lcall","__gptrput");
7896 /*-----------------------------------------------------------------*/
7897 /* genDataPointerSet - remat pointer to data space */
7898 /*-----------------------------------------------------------------*/
7899 static void genDataPointerSet(operand *right,
7903 int size, offset = 0 ;
7904 char *l, buffer[256];
7906 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7907 aopOp(right,ic,FALSE);
7909 l = aopGet(AOP(result),0,FALSE,TRUE);
7910 size = AOP_SIZE(right);
7911 // tsd, was l+1 - the underline `_' prefix was being stripped
7914 sprintf(buffer,"(%s + %d)",l,offset);
7916 sprintf(buffer,"%s",l);
7918 if (AOP_TYPE(right) == AOP_LIT) {
7919 unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
7920 lit = lit >> (8*offset);
7922 pic14_emitcode("movlw","%d",lit);
7923 pic14_emitcode("movwf","%s",buffer);
7925 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
7926 emitpcode(POC_MOVWF, popRegFromString(buffer));
7929 pic14_emitcode("clrf","%s",buffer);
7930 emitpcode(POC_CLRF, popRegFromString(buffer));
7933 pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
7934 pic14_emitcode("movwf","%s",buffer);
7936 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
7937 emitpcode(POC_MOVWF, popRegFromString(buffer));
7944 freeAsmop(right,NULL,ic,TRUE);
7945 freeAsmop(result,NULL,ic,TRUE);
7948 /*-----------------------------------------------------------------*/
7949 /* genNearPointerSet - pic14_emitcode for near pointer put */
7950 /*-----------------------------------------------------------------*/
7951 static void genNearPointerSet (operand *right,
7958 sym_link *ptype = operandType(result);
7961 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7962 retype= getSpec(operandType(right));
7964 aopOp(result,ic,FALSE);
7966 /* if the result is rematerializable &
7967 in data space & not a bit variable */
7968 if (AOP_TYPE(result) == AOP_IMMD &&
7969 DCL_TYPE(ptype) == POINTER &&
7970 !IS_BITVAR(retype)) {
7971 genDataPointerSet (right,result,ic);
7975 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7977 /* if the value is already in a pointer register
7978 then don't need anything more */
7979 if (!AOP_INPREG(AOP(result))) {
7980 /* otherwise get a free pointer register */
7981 //aop = newAsmop(0);
7982 //preg = getFreePtr(ic,&aop,FALSE);
7983 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7984 //pic14_emitcode("mov","%s,%s",
7986 // aopGet(AOP(result),0,FALSE,TRUE));
7987 //rname = preg->name ;
7988 pic14_emitcode("movwf","fsr");
7990 // rname = aopGet(AOP(result),0,FALSE,FALSE);
7992 freeAsmop(result,NULL,ic,TRUE);
7993 aopOp (right,ic,FALSE);
7994 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7996 /* if bitfield then unpack the bits */
7997 if (IS_BITVAR(retype)) {
7998 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7999 "The programmer is obviously confused");
8000 //genPackBits (retype,right,rname,POINTER);
8004 /* we have can just get the values */
8005 int size = AOP_SIZE(right);
8008 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8010 l = aopGet(AOP(right),offset,FALSE,TRUE);
8013 //pic14_emitcode("mov","@%s,a",rname);
8014 pic14_emitcode("movf","indf,w ;1");
8017 if (AOP_TYPE(right) == AOP_LIT) {
8018 unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8020 pic14_emitcode("movlw","%s",l);
8021 pic14_emitcode("movwf","indf ;2");
8023 pic14_emitcode("clrf","indf");
8025 pic14_emitcode("movf","%s,w",l);
8026 pic14_emitcode("movwf","indf ;2");
8028 //pic14_emitcode("mov","@%s,%s",rname,l);
8031 pic14_emitcode("incf","fsr,f ;3");
8032 //pic14_emitcode("inc","%s",rname);
8037 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8038 /* now some housekeeping stuff */
8040 /* we had to allocate for this iCode */
8041 freeAsmop(NULL,aop,ic,TRUE);
8043 /* we did not allocate which means left
8044 already in a pointer register, then
8045 if size > 0 && this could be used again
8046 we have to point it back to where it
8048 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8049 if (AOP_SIZE(right) > 1 &&
8050 !OP_SYMBOL(result)->remat &&
8051 ( OP_SYMBOL(result)->liveTo > ic->seq ||
8053 int size = AOP_SIZE(right) - 1;
8055 pic14_emitcode("decf","fsr,f");
8056 //pic14_emitcode("dec","%s",rname);
8060 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8062 freeAsmop(right,NULL,ic,TRUE);
8067 /*-----------------------------------------------------------------*/
8068 /* genPagedPointerSet - pic14_emitcode for Paged pointer put */
8069 /*-----------------------------------------------------------------*/
8070 static void genPagedPointerSet (operand *right,
8079 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8081 retype= getSpec(operandType(right));
8083 aopOp(result,ic,FALSE);
8085 /* if the value is already in a pointer register
8086 then don't need anything more */
8087 if (!AOP_INPREG(AOP(result))) {
8088 /* otherwise get a free pointer register */
8090 preg = getFreePtr(ic,&aop,FALSE);
8091 pic14_emitcode("mov","%s,%s",
8093 aopGet(AOP(result),0,FALSE,TRUE));
8094 rname = preg->name ;
8096 rname = aopGet(AOP(result),0,FALSE,FALSE);
8098 freeAsmop(result,NULL,ic,TRUE);
8099 aopOp (right,ic,FALSE);
8101 /* if bitfield then unpack the bits */
8102 if (IS_BITVAR(retype))
8103 genPackBits (retype,right,rname,PPOINTER);
8105 /* we have can just get the values */
8106 int size = AOP_SIZE(right);
8110 l = aopGet(AOP(right),offset,FALSE,TRUE);
8113 pic14_emitcode("movx","@%s,a",rname);
8116 pic14_emitcode("inc","%s",rname);
8122 /* now some housekeeping stuff */
8124 /* we had to allocate for this iCode */
8125 freeAsmop(NULL,aop,ic,TRUE);
8127 /* we did not allocate which means left
8128 already in a pointer register, then
8129 if size > 0 && this could be used again
8130 we have to point it back to where it
8132 if (AOP_SIZE(right) > 1 &&
8133 !OP_SYMBOL(result)->remat &&
8134 ( OP_SYMBOL(result)->liveTo > ic->seq ||
8136 int size = AOP_SIZE(right) - 1;
8138 pic14_emitcode("dec","%s",rname);
8143 freeAsmop(right,NULL,ic,TRUE);
8148 /*-----------------------------------------------------------------*/
8149 /* genFarPointerSet - set value from far space */
8150 /*-----------------------------------------------------------------*/
8151 static void genFarPointerSet (operand *right,
8152 operand *result, iCode *ic)
8155 sym_link *retype = getSpec(operandType(right));
8157 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8158 aopOp(result,ic,FALSE);
8160 /* if the operand is already in dptr
8161 then we do nothing else we move the value to dptr */
8162 if (AOP_TYPE(result) != AOP_STR) {
8163 /* if this is remateriazable */
8164 if (AOP_TYPE(result) == AOP_IMMD)
8165 pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8166 else { /* we need to get it byte by byte */
8167 pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
8168 pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
8169 if (options.model == MODEL_FLAT24)
8171 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
8175 /* so dptr know contains the address */
8176 freeAsmop(result,NULL,ic,TRUE);
8177 aopOp(right,ic,FALSE);
8179 /* if bit then unpack */
8180 if (IS_BITVAR(retype))
8181 genPackBits(retype,right,"dptr",FPOINTER);
8183 size = AOP_SIZE(right);
8187 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8189 pic14_emitcode("movx","@dptr,a");
8191 pic14_emitcode("inc","dptr");
8195 freeAsmop(right,NULL,ic,TRUE);
8198 /*-----------------------------------------------------------------*/
8199 /* genGenPointerSet - set value from generic pointer space */
8200 /*-----------------------------------------------------------------*/
8201 static void genGenPointerSet (operand *right,
8202 operand *result, iCode *ic)
8205 sym_link *retype = getSpec(operandType(right));
8207 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8209 aopOp(result,ic,FALSE);
8210 aopOp(right,ic,FALSE);
8211 size = AOP_SIZE(right);
8213 DEBUGpic14_AopType(__LINE__,NULL,right,result);
8215 /* if the operand is already in dptr
8216 then we do nothing else we move the value to dptr */
8217 if (AOP_TYPE(result) != AOP_STR) {
8218 /* if this is remateriazable */
8219 if (AOP_TYPE(result) == AOP_IMMD) {
8220 pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8221 pic14_emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
8223 else { /* we need to get it byte by byte */
8224 //char *l = aopGet(AOP(result),0,FALSE,FALSE);
8225 size = AOP_SIZE(right);
8228 /* hack hack! see if this the FSR. If so don't load W */
8229 if(AOP_TYPE(right) != AOP_ACC) {
8231 emitpcode(POC_MOVFW,popGet(AOP(result),0));
8232 emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8235 //emitpcode(POC_DECF,popCopyReg(&pc_fsr));
8237 // emitpcode(POC_MOVLW,popGetLit(0xfd));
8238 // emitpcode(POC_ADDWF,popCopyReg(&pc_fsr));
8242 emitpcode(POC_MOVFW,popGet(AOP(right),offset++));
8243 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8246 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8253 if(aopIdx(AOP(result),0) != 4) {
8255 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8259 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8264 /* so dptr know contains the address */
8267 /* if bit then unpack */
8268 if (IS_BITVAR(retype))
8269 genPackBits(retype,right,"dptr",GPOINTER);
8271 size = AOP_SIZE(right);
8275 //char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8277 pic14_emitcode("incf","fsr,f");
8278 pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset++,FALSE,FALSE));
8279 pic14_emitcode("movwf","indf");
8281 //DEBUGpic14_emitcode(";lcall","__gptrput");
8283 // pic14_emitcode("inc","dptr");
8288 freeAsmop(right,NULL,ic,TRUE);
8289 freeAsmop(result,NULL,ic,TRUE);
8292 /*-----------------------------------------------------------------*/
8293 /* genPointerSet - stores the value into a pointer location */
8294 /*-----------------------------------------------------------------*/
8295 static void genPointerSet (iCode *ic)
8297 operand *right, *result ;
8298 sym_link *type, *etype;
8301 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8303 right = IC_RIGHT(ic);
8304 result = IC_RESULT(ic) ;
8306 /* depending on the type of pointer we need to
8307 move it to the correct pointer register */
8308 type = operandType(result);
8309 etype = getSpec(type);
8310 /* if left is of type of pointer then it is simple */
8311 if (IS_PTR(type) && !IS_FUNC(type->next)) {
8312 p_type = DCL_TYPE(type);
8315 /* we have to go by the storage class */
8316 p_type = PTR_TYPE(SPEC_OCLS(etype));
8318 /* if (SPEC_OCLS(etype)->codesp ) { */
8319 /* p_type = CPOINTER ; */
8322 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8323 /* p_type = FPOINTER ; */
8325 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8326 /* p_type = PPOINTER ; */
8328 /* if (SPEC_OCLS(etype) == idata ) */
8329 /* p_type = IPOINTER ; */
8331 /* p_type = POINTER ; */
8334 /* now that we have the pointer type we assign
8335 the pointer values */
8340 genNearPointerSet (right,result,ic);
8344 genPagedPointerSet (right,result,ic);
8348 genFarPointerSet (right,result,ic);
8352 genGenPointerSet (right,result,ic);
8358 /*-----------------------------------------------------------------*/
8359 /* genIfx - generate code for Ifx statement */
8360 /*-----------------------------------------------------------------*/
8361 static void genIfx (iCode *ic, iCode *popIc)
8363 operand *cond = IC_COND(ic);
8366 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8368 aopOp(cond,ic,FALSE);
8370 /* get the value into acc */
8371 if (AOP_TYPE(cond) != AOP_CRY)
8372 pic14_toBoolean(cond);
8375 /* the result is now in the accumulator */
8376 freeAsmop(cond,NULL,ic,TRUE);
8378 /* if there was something to be popped then do it */
8382 /* if the condition is a bit variable */
8383 if (isbit && IS_ITEMP(cond) &&
8385 genIfxJump(ic,SPIL_LOC(cond)->rname);
8386 DEBUGpic14_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
8389 if (isbit && !IS_ITEMP(cond))
8390 genIfxJump(ic,OP_SYMBOL(cond)->rname);
8398 /*-----------------------------------------------------------------*/
8399 /* genAddrOf - generates code for address of */
8400 /*-----------------------------------------------------------------*/
8401 static void genAddrOf (iCode *ic)
8403 //symbol *sym = OP_SYMBOL(IC_LEFT(ic));
8404 operand *right, *result, *left;
8405 //int size, offset ;
8407 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8410 //aopOp(IC_RESULT(ic),ic,FALSE);
8412 aopOp((left=IC_LEFT(ic)),ic,FALSE);
8413 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
8414 aopOp((result=IC_RESULT(ic)),ic,TRUE);
8416 DEBUGpic14_AopType(__LINE__,left,right,result);
8418 emitpcode(POC_MOVLW, popGet(AOP(left),0));
8419 emitpcode(POC_MOVWF, popGet(AOP(result),0));
8422 /* object not on stack then we need the name */
8423 size = AOP_SIZE(IC_RESULT(ic));
8427 char s[SDCC_NAME_MAX];
8429 sprintf(s,"#(%s >> %d)",
8433 sprintf(s,"#%s",sym->rname);
8434 aopPut(AOP(IC_RESULT(ic)),s,offset++);
8439 // freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8440 freeAsmop(left,NULL,ic,FALSE);
8441 freeAsmop(result,NULL,ic,TRUE);
8446 /*-----------------------------------------------------------------*/
8447 /* genFarFarAssign - assignment when both are in far space */
8448 /*-----------------------------------------------------------------*/
8449 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
8451 int size = AOP_SIZE(right);
8454 /* first push the right side on to the stack */
8456 l = aopGet(AOP(right),offset++,FALSE,FALSE);
8458 pic14_emitcode ("push","acc");
8461 freeAsmop(right,NULL,ic,FALSE);
8462 /* now assign DPTR to result */
8463 aopOp(result,ic,FALSE);
8464 size = AOP_SIZE(result);
8466 pic14_emitcode ("pop","acc");
8467 aopPut(AOP(result),"a",--offset);
8469 freeAsmop(result,NULL,ic,FALSE);
8474 /*-----------------------------------------------------------------*/
8475 /* genAssign - generate code for assignment */
8476 /*-----------------------------------------------------------------*/
8477 static void genAssign (iCode *ic)
8479 operand *result, *right;
8480 int size, offset,know_W;
8481 unsigned long lit = 0L;
8483 result = IC_RESULT(ic);
8484 right = IC_RIGHT(ic) ;
8486 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8488 /* if they are the same */
8489 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
8492 aopOp(right,ic,FALSE);
8493 aopOp(result,ic,TRUE);
8495 DEBUGpic14_AopType(__LINE__,NULL,right,result);
8497 /* if they are the same registers */
8498 if (pic14_sameRegs(AOP(right),AOP(result)))
8501 /* if the result is a bit */
8502 if (AOP_TYPE(result) == AOP_CRY) {
8504 /* if the right size is a literal then
8505 we know what the value is */
8506 if (AOP_TYPE(right) == AOP_LIT) {
8508 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
8509 popGet(AOP(result),0));
8511 if (((int) operandLitValue(right)))
8512 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
8513 AOP(result)->aopu.aop_dir,
8514 AOP(result)->aopu.aop_dir);
8516 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
8517 AOP(result)->aopu.aop_dir,
8518 AOP(result)->aopu.aop_dir);
8522 /* the right is also a bit variable */
8523 if (AOP_TYPE(right) == AOP_CRY) {
8524 emitpcode(POC_BCF, popGet(AOP(result),0));
8525 emitpcode(POC_BTFSC, popGet(AOP(right),0));
8526 emitpcode(POC_BSF, popGet(AOP(result),0));
8528 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
8529 AOP(result)->aopu.aop_dir,
8530 AOP(result)->aopu.aop_dir);
8531 pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
8532 AOP(right)->aopu.aop_dir,
8533 AOP(right)->aopu.aop_dir);
8534 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
8535 AOP(result)->aopu.aop_dir,
8536 AOP(result)->aopu.aop_dir);
8541 emitpcode(POC_BCF, popGet(AOP(result),0));
8542 pic14_toBoolean(right);
8544 emitpcode(POC_BSF, popGet(AOP(result),0));
8545 //aopPut(AOP(result),"a",0);
8549 /* bit variables done */
8551 size = AOP_SIZE(result);
8553 if(AOP_TYPE(right) == AOP_LIT)
8554 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
8556 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
8557 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8558 if(aopIdx(AOP(result),0) == 4) {
8559 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8560 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8561 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8564 DEBUGpic14_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
8569 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8570 if(AOP_TYPE(right) == AOP_LIT) {
8572 if(know_W != (lit&0xff))
8573 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
8575 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8577 emitpcode(POC_CLRF, popGet(AOP(result),offset));
8581 } else if (AOP_TYPE(right) == AOP_CRY) {
8582 emitpcode(POC_CLRF, popGet(AOP(result),offset));
8584 emitpcode(POC_BTFSS, popGet(AOP(right),0));
8585 emitpcode(POC_INCF, popGet(AOP(result),0));
8588 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8589 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8590 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8598 freeAsmop (right,NULL,ic,FALSE);
8599 freeAsmop (result,NULL,ic,TRUE);
8602 /*-----------------------------------------------------------------*/
8603 /* genJumpTab - genrates code for jump table */
8604 /*-----------------------------------------------------------------*/
8605 static void genJumpTab (iCode *ic)
8610 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8612 aopOp(IC_JTCOND(ic),ic,FALSE);
8613 /* get the condition into accumulator */
8614 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
8616 /* multiply by three */
8617 pic14_emitcode("add","a,acc");
8618 pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
8620 jtab = newiTempLabel(NULL);
8621 pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
8622 pic14_emitcode("jmp","@a+dptr");
8623 pic14_emitcode("","%05d_DS_:",jtab->key+100);
8625 emitpcode(POC_MOVLW, popGetLabel(jtab->key));
8626 emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
8628 emitpcode(POC_INCF, popCopyReg(&pc_pclath));
8629 emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
8630 emitpLabel(jtab->key);
8632 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
8634 /* now generate the jump labels */
8635 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
8636 jtab = setNextItem(IC_JTLABELS(ic))) {
8637 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
8638 emitpcode(POC_GOTO,popGetLabel(jtab->key));
8644 /*-----------------------------------------------------------------*/
8645 /* genMixedOperation - gen code for operators between mixed types */
8646 /*-----------------------------------------------------------------*/
8648 TSD - Written for the PIC port - but this unfortunately is buggy.
8649 This routine is good in that it is able to efficiently promote
8650 types to different (larger) sizes. Unfortunately, the temporary
8651 variables that are optimized out by this routine are sometimes
8652 used in other places. So until I know how to really parse the
8653 iCode tree, I'm going to not be using this routine :(.
8655 static int genMixedOperation (iCode *ic)
8658 operand *result = IC_RESULT(ic);
8659 sym_link *ctype = operandType(IC_LEFT(ic));
8660 operand *right = IC_RIGHT(ic);
8666 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
8668 pic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
8674 nextright = IC_RIGHT(nextic);
8675 nextleft = IC_LEFT(nextic);
8676 nextresult = IC_RESULT(nextic);
8678 aopOp(right,ic,FALSE);
8679 aopOp(result,ic,FALSE);
8680 aopOp(nextright, nextic, FALSE);
8681 aopOp(nextleft, nextic, FALSE);
8682 aopOp(nextresult, nextic, FALSE);
8684 if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
8690 pic14_emitcode(";remove right +","");
8692 } else if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
8698 pic14_emitcode(";remove left +","");
8702 big = AOP_SIZE(nextleft);
8703 small = AOP_SIZE(nextright);
8705 switch(nextic->op) {
8708 pic14_emitcode(";optimize a +","");
8709 /* if unsigned or not an integral type */
8710 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
8711 pic14_emitcode(";add a bit to something","");
8714 pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
8716 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
8717 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
8718 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
8720 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
8728 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8729 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8730 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8733 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8735 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
8736 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
8737 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
8738 pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8739 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
8742 pic14_emitcode("rlf","known_zero,w");
8749 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8750 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8751 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8753 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8763 freeAsmop(right,NULL,ic,TRUE);
8764 freeAsmop(result,NULL,ic,TRUE);
8765 freeAsmop(nextright,NULL,ic,TRUE);
8766 freeAsmop(nextleft,NULL,ic,TRUE);
8768 nextic->generated = 1;
8775 /*-----------------------------------------------------------------*/
8776 /* genCast - gen code for casting */
8777 /*-----------------------------------------------------------------*/
8778 static void genCast (iCode *ic)
8780 operand *result = IC_RESULT(ic);
8781 sym_link *ctype = operandType(IC_LEFT(ic));
8782 operand *right = IC_RIGHT(ic);
8785 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
8786 /* if they are equivalent then do nothing */
8787 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
8790 aopOp(right,ic,FALSE) ;
8791 aopOp(result,ic,FALSE);
8793 DEBUGpic14_AopType(__LINE__,NULL,right,result);
8795 /* if the result is a bit */
8796 if (AOP_TYPE(result) == AOP_CRY) {
8797 /* if the right size is a literal then
8798 we know what the value is */
8799 if (AOP_TYPE(right) == AOP_LIT) {
8801 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
8802 popGet(AOP(result),0));
8804 if (((int) operandLitValue(right)))
8805 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
8806 AOP(result)->aopu.aop_dir,
8807 AOP(result)->aopu.aop_dir);
8809 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
8810 AOP(result)->aopu.aop_dir,
8811 AOP(result)->aopu.aop_dir);
8816 /* the right is also a bit variable */
8817 if (AOP_TYPE(right) == AOP_CRY) {
8820 emitpcode(POC_BTFSC, popGet(AOP(right),0));
8822 pic14_emitcode("clrc","");
8823 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
8824 AOP(right)->aopu.aop_dir,
8825 AOP(right)->aopu.aop_dir);
8826 aopPut(AOP(result),"c",0);
8831 if (AOP_TYPE(right) == AOP_REG) {
8832 emitpcode(POC_BCF, popGet(AOP(result),0));
8833 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
8834 emitpcode(POC_BSF, popGet(AOP(result),0));
8836 pic14_toBoolean(right);
8837 aopPut(AOP(result),"a",0);
8841 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
8843 size = AOP_SIZE(result);
8845 emitpcode(POC_CLRF, popGet(AOP(result),0));
8846 emitpcode(POC_BTFSC, popGet(AOP(right),0));
8847 emitpcode(POC_INCF, popGet(AOP(result),0));
8850 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
8855 /* if they are the same size : or less */
8856 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8858 /* if they are in the same place */
8859 if (pic14_sameRegs(AOP(right),AOP(result)))
8862 /* if they in different places then copy */
8863 size = AOP_SIZE(result);
8867 aopGet(AOP(right),offset,FALSE,FALSE),
8875 /* if the result is of type pointer */
8876 if (IS_PTR(ctype)) {
8879 sym_link *type = operandType(right);
8880 sym_link *etype = getSpec(type);
8882 /* pointer to generic pointer */
8883 if (IS_GENPTR(ctype)) {
8887 p_type = DCL_TYPE(type);
8889 /* we have to go by the storage class */
8890 p_type = PTR_TYPE(SPEC_OCLS(etype));
8892 /* if (SPEC_OCLS(etype)->codesp ) */
8893 /* p_type = CPOINTER ; */
8895 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8896 /* p_type = FPOINTER ; */
8898 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8899 /* p_type = PPOINTER; */
8901 /* if (SPEC_OCLS(etype) == idata ) */
8902 /* p_type = IPOINTER ; */
8904 /* p_type = POINTER ; */
8907 /* the first two bytes are known */
8908 size = GPTRSIZE - 1;
8912 aopGet(AOP(right),offset,FALSE,FALSE),
8916 /* the last byte depending on type */
8933 /* this should never happen */
8934 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8935 "got unknown pointer type");
8938 aopPut(AOP(result),l, GPTRSIZE - 1);
8942 /* just copy the pointers */
8943 size = AOP_SIZE(result);
8947 aopGet(AOP(right),offset,FALSE,FALSE),
8956 /* so we now know that the size of destination is greater
8957 than the size of the source.
8958 Now, if the next iCode is an operator then we might be
8959 able to optimize the operation without performing a cast.
8961 if(genMixedOperation(ic))
8965 /* we move to result for the size of source */
8966 size = AOP_SIZE(right);
8969 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8970 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8974 /* now depending on the sign of the destination */
8975 size = AOP_SIZE(result) - AOP_SIZE(right);
8976 /* if unsigned or not an integral type */
8977 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
8979 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
8981 /* we need to extend the sign :{ */
8984 /* Save one instruction of casting char to int */
8985 emitpcode(POC_CLRF, popGet(AOP(result),offset));
8986 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
8987 emitpcode(POC_DECF, popGet(AOP(result),offset));
8989 emitpcodeNULLop(POC_CLRW);
8992 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
8994 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),offset,FALSE,FALSE),7,0));
8996 emitpcode(POC_MOVLW, popGetLit(0xff));
8999 emitpcode(POC_MOVWF, popGet(AOP(result),offset++));
9004 freeAsmop(right,NULL,ic,TRUE);
9005 freeAsmop(result,NULL,ic,TRUE);
9009 /*-----------------------------------------------------------------*/
9010 /* genDjnz - generate decrement & jump if not zero instrucion */
9011 /*-----------------------------------------------------------------*/
9012 static int genDjnz (iCode *ic, iCode *ifx)
9015 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9020 /* if the if condition has a false label
9021 then we cannot save */
9025 /* if the minus is not of the form
9027 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
9028 !IS_OP_LITERAL(IC_RIGHT(ic)))
9031 if (operandLitValue(IC_RIGHT(ic)) != 1)
9034 /* if the size of this greater than one then no
9036 if (getSize(operandType(IC_RESULT(ic))) > 1)
9039 /* otherwise we can save BIG */
9040 lbl = newiTempLabel(NULL);
9041 lbl1= newiTempLabel(NULL);
9043 aopOp(IC_RESULT(ic),ic,FALSE);
9045 if (IS_AOP_PREG(IC_RESULT(ic))) {
9046 pic14_emitcode("dec","%s",
9047 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9048 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9049 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
9053 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
9054 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
9056 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9057 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
9060 /* pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
9061 /* pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
9062 /* pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
9063 /* pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
9066 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9071 /*-----------------------------------------------------------------*/
9072 /* genReceive - generate code for a receive iCode */
9073 /*-----------------------------------------------------------------*/
9074 static void genReceive (iCode *ic)
9076 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9078 if (isOperandInFarSpace(IC_RESULT(ic)) &&
9079 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
9080 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
9082 int size = getSize(operandType(IC_RESULT(ic)));
9083 int offset = fReturnSizePic - size;
9085 pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
9086 fReturn[fReturnSizePic - offset - 1] : "acc"));
9089 aopOp(IC_RESULT(ic),ic,FALSE);
9090 size = AOP_SIZE(IC_RESULT(ic));
9093 pic14_emitcode ("pop","acc");
9094 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
9099 aopOp(IC_RESULT(ic),ic,FALSE);
9101 assignResultValue(IC_RESULT(ic));
9104 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9107 /*-----------------------------------------------------------------*/
9108 /* genpic14Code - generate code for pic14 based controllers */
9109 /*-----------------------------------------------------------------*/
9111 * At this point, ralloc.c has gone through the iCode and attempted
9112 * to optimize in a way suitable for a PIC. Now we've got to generate
9113 * PIC instructions that correspond to the iCode.
9115 * Once the instructions are generated, we'll pass through both the
9116 * peep hole optimizer and the pCode optimizer.
9117 *-----------------------------------------------------------------*/
9119 void genpic14Code (iCode *lic)
9124 lineHead = lineCurr = NULL;
9126 pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
9129 /* if debug information required */
9130 /* if (options.debug && currFunc) { */
9132 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
9134 if (IS_STATIC(currFunc->etype)) {
9135 pic14_emitcode("",";F%s$%s$0$0 %d",moduleName,currFunc->name,__LINE__);
9136 //addpCode2pBlock(pb,newpCodeLabel(moduleName,currFunc->name));
9138 pic14_emitcode("",";G$%s$0$0 %d",currFunc->name,__LINE__);
9139 //addpCode2pBlock(pb,newpCodeLabel(NULL,currFunc->name));
9145 for (ic = lic ; ic ; ic = ic->next ) {
9147 DEBUGpic14_emitcode(";ic","");
9148 if ( cln != ic->lineno ) {
9149 if ( options.debug ) {
9151 pic14_emitcode("",";C$%s$%d$%d$%d ==.",
9152 FileBaseName(ic->filename),ic->lineno,
9153 ic->level,ic->block);
9156 pic14_emitcode("#CSRC","%s %d",FileBaseName(ic->filename),ic->lineno);
9159 /* if the result is marked as
9160 spilt and rematerializable or code for
9161 this has already been generated then
9163 if (resultRemat(ic) || ic->generated )
9166 /* depending on the operation */
9185 /* IPOP happens only when trying to restore a
9186 spilt live range, if there is an ifx statement
9187 following this pop then the if statement might
9188 be using some of the registers being popped which
9189 would destory the contents of the register so
9190 we need to check for this condition and handle it */
9192 ic->next->op == IFX &&
9193 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
9194 genIfx (ic->next,ic);
9212 genEndFunction (ic);
9232 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
9249 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
9253 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
9260 /* note these two are xlated by algebraic equivalence
9261 during parsing SDCC.y */
9262 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9263 "got '>=' or '<=' shouldn't have come here");
9267 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
9279 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
9283 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
9287 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
9314 case GET_VALUE_AT_ADDRESS:
9319 if (POINTER_SET(ic))
9346 addSet(&_G.sendSet,ic);
9355 /* now we are ready to call the
9356 peep hole optimizer */
9357 if (!options.nopeep) {
9358 printf("peep hole optimizing\n");
9359 peepHole (&lineHead);
9361 /* now do the actual printing */
9362 printLine (lineHead,codeOutFile);
9364 printf("printing pBlock\n\n");
9365 printpBlock(stdout,pb);