1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for pic
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 PIC port - Scott Dattalo scott@dattalo.com (2000)
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"
40 #include "SDCCpeeph.h"
45 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
46 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
47 void genMult8X8_8 (operand *, operand *,operand *);
48 extern void printpBlock(FILE *of, pBlock *pb);
50 static int labelOffset=0;
51 extern int debug_verbose;
52 static int optimized_for_speed = 0;
54 /* max_key keeps track of the largest label number used in
55 a function. This is then used to adjust the label offset
56 for the next function.
59 static int GpsuedoStkPtr=0;
61 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
62 unsigned int pic14aopLiteral (value *val, int offset);
63 const char *AopType(short type);
65 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0x00ff)
67 /* this is the down and dirty file with all kinds of
68 kludgy & hacky stuff. This is what it is all about
69 CODE GENERATION for a specific MCU . some of the
70 routines may be reusable, will have to see */
72 static char *zero = "#0x00";
73 static char *one = "#0x01";
74 static char *spname = "sp";
76 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
77 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
78 static char **fReturn = fReturnpic14;
80 static char *accUse[] = {"a","b"};
82 //static short rbank = -1;
94 /* Resolved ifx structure. This structure stores information
95 about an iCode ifx that makes it easier to generate code.
97 typedef struct resolvedIfx {
98 symbol *lbl; /* pointer to a label */
99 int condition; /* true or false ifx */
100 int generated; /* set true when the code associated with the ifx
104 extern int pic14_ptrRegReq ;
105 extern int pic14_nRegs;
106 extern FILE *codeOutFile;
107 static void saverbank (int, iCode *,bool);
109 static lineNode *lineHead = NULL;
110 static lineNode *lineCurr = NULL;
112 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
113 0xE0, 0xC0, 0x80, 0x00};
114 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
115 0x07, 0x03, 0x01, 0x00};
119 /*-----------------------------------------------------------------*/
120 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
121 /* exponent of 2 is returned, otherwise -1 is */
123 /* note that this is similar to the function `powof2' in SDCCsymt */
127 /*-----------------------------------------------------------------*/
128 static int my_powof2 (unsigned long num)
131 if( (num & (num-1)) == 0) {
144 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
147 DEBUGpic14_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
149 ((result) ? AopType(AOP_TYPE(result)) : "-"),
150 ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
151 ((left) ? AopType(AOP_TYPE(left)) : "-"),
152 ((left) ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
153 ((right) ? AopType(AOP_TYPE(right)) : "-"),
154 ((right) ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
155 ((result) ? AOP_SIZE(result) : 0));
159 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
162 DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
164 ((result) ? AopType(AOP_TYPE(result)) : "-"),
165 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
166 ((left) ? AopType(AOP_TYPE(left)) : "-"),
167 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
168 ((right) ? AopType(AOP_TYPE(right)) : "-"),
169 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
173 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
176 char lb[INITIAL_INLINEASM];
179 if(!debug_verbose && !options.debug)
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));
207 static void Safe_vsnprintf (char *buf, size_t size, const char *fmt, va_list ap)
209 #if defined (HAVE_VSNPRINTF)
210 vsnprintf (buf, size, fmt, ap);
211 #elif defined (HAVE_VSPRINTF)
212 vsprintf (buf, size, fmt, ap);
213 if (strlen (buf) >= size)
215 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
217 #elif defined (HAVE_SNPRINTF)
218 snprintf (buf, size, "vs(n)printf required");
219 #elif defined (HAVE_SRINTF)
220 sprintf (buf, "vs(n)printf required");
221 if (strlen (buf) >= size)
223 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
226 assert ( !"neither vsnprintf nor vsprintf is present -- unable to proceed" );
230 void emitpComment (const char *fmt, ...)
237 Safe_vsnprintf (buffer, 4096, fmt, va);
238 //fprintf (stderr, "%s\n" ,buffer);
239 addpCode2pBlock (pb, newpCodeCharP (buffer));
244 void emitpLabel(int key)
246 addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
249 void emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
252 addpCode2pBlock(pb,newpCode(poc,pcop));
254 DEBUGpic14_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
257 void emitpcodeNULLop(PIC_OPCODE poc)
260 addpCode2pBlock(pb,newpCode(poc,NULL));
265 /*-----------------------------------------------------------------*/
266 /* pic14_emitcode - writes the code into a file : for now it is simple */
267 /*-----------------------------------------------------------------*/
268 void pic14_emitcode (char *inst,char *fmt, ...)
271 char lb[INITIAL_INLINEASM];
278 sprintf(lb,"%s\t",inst);
280 sprintf(lb,"%s",inst);
281 vsprintf(lb+(strlen(lb)),fmt,ap);
285 while (isspace(*lbp)) lbp++;
288 lineCurr = (lineCurr ?
289 connectLine(lineCurr,newLineNode(lb)) :
290 (lineHead = newLineNode(lb)));
291 lineCurr->isInline = _G.inLine;
292 lineCurr->isDebug = _G.debugLine;
295 addpCode2pBlock(pb,newpCodeCharP(lb));
300 /*-----------------------------------------------------------------*/
301 /* pic14_emitDebuggerSymbol - associate the current code location */
302 /* with a debugger symbol */
303 /*-----------------------------------------------------------------*/
305 pic14_emitDebuggerSymbol (char * debugSym)
308 pic14_emitcode ("", ";%s ==.", debugSym);
313 /*-----------------------------------------------------------------*/
314 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
315 /*-----------------------------------------------------------------*/
316 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
318 bool r0iu = FALSE , r1iu = FALSE;
319 bool r0ou = FALSE , r1ou = FALSE;
321 /* the logic: if r0 & r1 used in the instruction
322 then we are in trouble otherwise */
324 /* first check if r0 & r1 are used by this
325 instruction, in which case we are in trouble */
326 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
327 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
332 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
333 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
335 /* if no usage of r0 then return it */
336 if (!r0iu && !r0ou) {
337 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
338 (*aopp)->type = AOP_R0;
340 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
343 /* if no usage of r1 then return it */
344 if (!r1iu && !r1ou) {
345 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
346 (*aopp)->type = AOP_R1;
348 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
351 /* now we know they both have usage */
352 /* if r0 not used in this instruction */
354 /* push it if not already pushed */
356 //pic14_emitcode ("push","%s",
357 // pic14_regWithIdx(R0_IDX)->dname);
361 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
362 (*aopp)->type = AOP_R0;
364 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
367 /* if r1 not used then */
370 /* push it if not already pushed */
372 //pic14_emitcode ("push","%s",
373 // pic14_regWithIdx(R1_IDX)->dname);
377 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
378 (*aopp)->type = AOP_R1;
379 return pic14_regWithIdx(R1_IDX);
383 /* I said end of world but not quite end of world yet */
384 /* if this is a result then we can push it on the stack*/
386 (*aopp)->type = AOP_STK;
390 /* other wise this is true end of the world */
391 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
392 "getFreePtr should never reach here");
396 /*-----------------------------------------------------------------*/
397 /* newAsmop - creates a new asmOp */
398 /*-----------------------------------------------------------------*/
399 asmop *newAsmop (short type)
403 aop = Safe_calloc(1,sizeof(asmop));
408 static void genSetDPTR(int n)
412 pic14_emitcode(";", "Select standard DPTR");
413 pic14_emitcode("mov", "dps, #0x00");
417 pic14_emitcode(";", "Select alternate DPTR");
418 pic14_emitcode("mov", "dps, #0x01");
422 /*-----------------------------------------------------------------*/
423 /* resolveIfx - converts an iCode ifx into a form more useful for */
424 /* generating code */
425 /*-----------------------------------------------------------------*/
426 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
431 // DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
433 resIfx->condition = 1; /* assume that the ifx is true */
434 resIfx->generated = 0; /* indicate that the ifx has not been used */
437 resIfx->lbl = newiTempLabel(NULL); /* oops, there is no ifx. so create a label */
439 DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
440 __FUNCTION__,__LINE__,resIfx->lbl->key);
444 resIfx->lbl = IC_TRUE(ifx);
446 resIfx->lbl = IC_FALSE(ifx);
447 resIfx->condition = 0;
451 DEBUGpic14_emitcode("; ***","ifx true is non-null");
453 DEBUGpic14_emitcode("; ***","ifx false is non-null");
457 // DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
460 /*-----------------------------------------------------------------*/
461 /* pointerCode - returns the code for a pointer type */
462 /*-----------------------------------------------------------------*/
463 static int pointerCode (sym_link *etype)
466 return PTR_TYPE(SPEC_OCLS(etype));
470 /*-----------------------------------------------------------------*/
471 /* aopForSym - for a true symbol */
472 /*-----------------------------------------------------------------*/
473 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
476 memmap *space= SPEC_OCLS(sym->etype);
478 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
479 /* if already has one */
483 /* assign depending on the storage class */
484 /* if it is on the stack or indirectly addressable */
485 /* space we need to assign either r0 or r1 to it */
486 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
487 sym->aop = aop = newAsmop(0);
488 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
489 aop->size = getSize(sym->type);
491 /* now assign the address of the variable to
492 the pointer register */
493 if (aop->type != AOP_STK) {
497 pic14_emitcode("push","acc");
499 pic14_emitcode("mov","a,_bp");
500 pic14_emitcode("add","a,#0x%02x",
502 ((char)(sym->stack - _G.nRegsSaved )) :
503 ((char)sym->stack)) & 0xff);
504 pic14_emitcode("mov","%s,a",
505 aop->aopu.aop_ptr->name);
508 pic14_emitcode("pop","acc");
510 pic14_emitcode("mov","%s,#%s",
511 aop->aopu.aop_ptr->name,
513 aop->paged = space->paged;
515 aop->aopu.aop_stk = sym->stack;
519 if (sym->onStack && options.stack10bit)
521 /* It's on the 10 bit stack, which is located in
525 //DEBUGpic14_emitcode(";","%d",__LINE__);
528 pic14_emitcode("push","acc");
530 pic14_emitcode("mov","a,_bp");
531 pic14_emitcode("add","a,#0x%02x",
533 ((char)(sym->stack - _G.nRegsSaved )) :
534 ((char)sym->stack)) & 0xff);
537 pic14_emitcode ("mov","dpx1,#0x40");
538 pic14_emitcode ("mov","dph1,#0x00");
539 pic14_emitcode ("mov","dpl1, a");
543 pic14_emitcode("pop","acc");
545 sym->aop = aop = newAsmop(AOP_DPTR2);
546 aop->size = getSize(sym->type);
550 //DEBUGpic14_emitcode(";","%d",__LINE__);
551 /* if in bit space */
552 if (IN_BITSPACE(space)) {
553 sym->aop = aop = newAsmop (AOP_CRY);
554 aop->aopu.aop_dir = sym->rname ;
555 aop->size = getSize(sym->type);
556 //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
559 /* if it is in direct space */
560 if (IN_DIRSPACE(space)) {
561 sym->aop = aop = newAsmop (AOP_DIR);
562 aop->aopu.aop_dir = sym->rname ;
563 aop->size = getSize(sym->type);
564 DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
568 /* special case for a function */
569 if (IS_FUNC(sym->type)) {
571 sym->aop = aop = newAsmop(AOP_PCODE);
572 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
573 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
574 PCOI(aop->aopu.pcop)->_function = 1;
575 PCOI(aop->aopu.pcop)->index = 0;
576 aop->size = FPTRSIZE;
578 sym->aop = aop = newAsmop(AOP_IMMD);
579 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
580 strcpy(aop->aopu.aop_immd,sym->rname);
581 aop->size = FPTRSIZE;
583 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
588 /* only remaining is far space */
589 /* in which case DPTR gets the address */
590 sym->aop = aop = newAsmop(AOP_PCODE);
592 aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
593 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
594 PCOI(aop->aopu.pcop)->index = 0;
596 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
597 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
599 allocDirReg (IC_LEFT(ic));
601 aop->size = FPTRSIZE;
603 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
604 sym->aop = aop = newAsmop(AOP_DPTR);
605 pic14_emitcode ("mov","dptr,#%s", sym->rname);
606 aop->size = getSize(sym->type);
608 DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
611 /* if it is in code space */
612 if (IN_CODESPACE(space))
618 /*-----------------------------------------------------------------*/
619 /* aopForRemat - rematerialzes an object */
620 /*-----------------------------------------------------------------*/
621 static asmop *aopForRemat (operand *op) // x symbol *sym)
623 symbol *sym = OP_SYMBOL(op);
625 asmop *aop = newAsmop(AOP_PCODE);
629 ic = sym->rematiCode;
631 DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
632 if(IS_OP_POINTER(op)) {
633 DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
637 val += (int) operandLitValue(IC_RIGHT(ic));
638 } else if (ic->op == '-') {
639 val -= (int) operandLitValue(IC_RIGHT(ic));
643 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
646 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
647 aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
648 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
649 PCOI(aop->aopu.pcop)->index = val;
651 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
652 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
653 val, IS_PTR_CONST(operandType(op)));
655 // DEBUGpic14_emitcode(";","aop type %s",AopType(AOP_TYPE(IC_LEFT(ic))));
657 allocDirReg (IC_LEFT(ic));
662 int aopIdx (asmop *aop, int offset)
667 if(aop->type != AOP_REG)
670 return aop->aopu.aop_reg[offset]->rIdx;
673 /*-----------------------------------------------------------------*/
674 /* regsInCommon - two operands have some registers in common */
675 /*-----------------------------------------------------------------*/
676 static bool regsInCommon (operand *op1, operand *op2)
681 /* if they have registers in common */
682 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
685 sym1 = OP_SYMBOL(op1);
686 sym2 = OP_SYMBOL(op2);
688 if (sym1->nRegs == 0 || sym2->nRegs == 0)
691 for (i = 0 ; i < sym1->nRegs ; i++) {
696 for (j = 0 ; j < sym2->nRegs ;j++ ) {
700 if (sym2->regs[j] == sym1->regs[i])
708 /*-----------------------------------------------------------------*/
709 /* operandsEqu - equivalent */
710 /*-----------------------------------------------------------------*/
711 static bool operandsEqu ( operand *op1, operand *op2)
715 /* if they not symbols */
716 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
719 sym1 = OP_SYMBOL(op1);
720 sym2 = OP_SYMBOL(op2);
722 /* if both are itemps & one is spilt
723 and the other is not then false */
724 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
725 sym1->isspilt != sym2->isspilt )
728 /* if they are the same */
732 if (sym1->rname[0] && sym2->rname[0]
733 && strcmp (sym1->rname, sym2->rname) == 0)
737 /* if left is a tmp & right is not */
741 (sym1->usl.spillLoc == sym2))
748 (sym2->usl.spillLoc == sym1))
754 /*-----------------------------------------------------------------*/
755 /* pic14_sameRegs - two asmops have the same registers */
756 /*-----------------------------------------------------------------*/
757 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
764 if (aop1->type != AOP_REG ||
765 aop2->type != AOP_REG )
768 if (aop1->size != aop2->size )
771 for (i = 0 ; i < aop1->size ; i++ )
772 if (aop1->aopu.aop_reg[i] !=
773 aop2->aopu.aop_reg[i] )
779 /*-----------------------------------------------------------------*/
780 /* aopOp - allocates an asmop for an operand : */
781 /*-----------------------------------------------------------------*/
782 void aopOp (operand *op, iCode *ic, bool result)
791 /* if this a literal */
792 if (IS_OP_LITERAL(op)) {
793 op->aop = aop = newAsmop(AOP_LIT);
794 aop->aopu.aop_lit = op->operand.valOperand;
795 aop->size = getSize(operandType(op));
800 sym_link *type = operandType(op);
801 if(IS_PTR_CONST(type))
802 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
805 /* if already has a asmop then continue */
809 /* if the underlying symbol has a aop */
810 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
811 DEBUGpic14_emitcode(";","%d",__LINE__);
812 op->aop = OP_SYMBOL(op)->aop;
816 /* if this is a true symbol */
817 if (IS_TRUE_SYMOP(op)) {
818 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
819 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
823 /* this is a temporary : this has
829 e) can be a return use only */
834 /* if the type is a conditional */
835 if (sym->regType == REG_CND) {
836 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
841 /* if it is spilt then two situations
843 b) has a spill location */
844 if (sym->isspilt || sym->nRegs == 0) {
846 DEBUGpic14_emitcode(";","%d",__LINE__);
847 /* rematerialize it NOW */
850 sym->aop = op->aop = aop = aopForRemat (op);
851 aop->size = getSize(sym->type);
852 //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
858 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
859 aop->size = getSize(sym->type);
860 for ( i = 0 ; i < 2 ; i++ )
861 aop->aopu.aop_str[i] = accUse[i];
862 DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
867 if(sym->isptr) { // && sym->uptr
868 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
869 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
871 //PCOI(aop->aopu.pcop)->_const = 0;
872 //PCOI(aop->aopu.pcop)->index = 0;
874 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
875 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
877 //allocDirReg (IC_LEFT(ic));
879 aop->size = getSize(sym->type);
880 DEBUGpic14_emitcode(";","%d",__LINE__);
887 aop = op->aop = sym->aop = newAsmop(AOP_STR);
888 aop->size = getSize(sym->type);
889 for ( i = 0 ; i < fReturnSizePic ; i++ )
890 aop->aopu.aop_str[i] = fReturn[i];
892 DEBUGpic14_emitcode(";","%d",__LINE__);
897 /* else spill location */
898 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
899 /* force a new aop if sizes differ */
900 sym->usl.spillLoc->aop = NULL;
902 DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
903 __FUNCTION__,__LINE__,
904 sym->usl.spillLoc->rname,
905 sym->rname, sym->usl.spillLoc->offset);
907 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
908 //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
909 aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname,
911 sym->usl.spillLoc->offset);
912 aop->size = getSize(sym->type);
918 sym_link *type = operandType(op);
919 if(IS_PTR_CONST(type))
920 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
923 /* must be in a register */
924 DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
925 sym->aop = op->aop = aop = newAsmop(AOP_REG);
926 aop->size = sym->nRegs;
927 for ( i = 0 ; i < sym->nRegs ;i++)
928 aop->aopu.aop_reg[i] = sym->regs[i];
931 /*-----------------------------------------------------------------*/
932 /* freeAsmop - free up the asmop given to an operand */
933 /*----------------------------------------------------------------*/
934 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
951 /* depending on the asmop type only three cases need work AOP_RO
952 , AOP_R1 && AOP_STK */
958 pic14_emitcode ("pop","ar0");
962 bitVectUnSetBit(ic->rUsed,R0_IDX);
968 pic14_emitcode ("pop","ar1");
972 bitVectUnSetBit(ic->rUsed,R1_IDX);
978 int stk = aop->aopu.aop_stk + aop->size;
979 bitVectUnSetBit(ic->rUsed,R0_IDX);
980 bitVectUnSetBit(ic->rUsed,R1_IDX);
982 getFreePtr(ic,&aop,FALSE);
984 if (options.stack10bit)
986 /* I'm not sure what to do here yet... */
989 "*** Warning: probably generating bad code for "
990 "10 bit stack mode.\n");
994 pic14_emitcode ("mov","a,_bp");
995 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
996 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
998 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1002 pic14_emitcode("pop","acc");
1003 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1005 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1008 freeAsmop(op,NULL,ic,TRUE);
1010 pic14_emitcode("pop","ar0");
1015 pic14_emitcode("pop","ar1");
1023 /* all other cases just dealloc */
1027 OP_SYMBOL(op)->aop = NULL;
1028 /* if the symbol has a spill */
1030 SPIL_LOC(op)->aop = NULL;
1035 /*-----------------------------------------------------------------*/
1036 /* aopGet - for fetching value of the aop */
1037 /*-----------------------------------------------------------------*/
1038 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1043 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1044 /* offset is greater than
1046 if (offset > (aop->size - 1) &&
1047 aop->type != AOP_LIT)
1050 /* depending on type */
1051 switch (aop->type) {
1055 DEBUGpic14_emitcode(";","%d",__LINE__);
1056 /* if we need to increment it */
1057 while (offset > aop->coff) {
1058 pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);
1062 while (offset < aop->coff) {
1063 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1067 aop->coff = offset ;
1069 pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1070 return (dname ? "acc" : "a");
1072 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1073 rs = Safe_calloc(1,strlen(s)+1);
1079 DEBUGpic14_emitcode(";","%d",__LINE__);
1080 if (aop->type == AOP_DPTR2)
1085 while (offset > aop->coff) {
1086 pic14_emitcode ("inc","dptr");
1090 while (offset < aop->coff) {
1091 pic14_emitcode("lcall","__decdptr");
1097 pic14_emitcode("clr","a");
1098 pic14_emitcode("movc","a,@a+dptr");
1101 pic14_emitcode("movx","a,@dptr");
1104 if (aop->type == AOP_DPTR2)
1109 return (dname ? "acc" : "a");
1114 sprintf (s,"%s",aop->aopu.aop_immd);
1117 sprintf(s,"(%s >> %d)",
1122 aop->aopu.aop_immd);
1123 DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1124 rs = Safe_calloc(1,strlen(s)+1);
1130 sprintf(s,"(%s + %d)",
1133 DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1135 sprintf(s,"%s",aop->aopu.aop_dir);
1136 rs = Safe_calloc(1,strlen(s)+1);
1142 // return aop->aopu.aop_reg[offset]->dname;
1144 return aop->aopu.aop_reg[offset]->name;
1147 //pic14_emitcode(";","%d",__LINE__);
1148 return aop->aopu.aop_dir;
1151 DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1152 return "AOP_accumulator_bug";
1155 sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1156 rs = Safe_calloc(1,strlen(s)+1);
1161 aop->coff = offset ;
1162 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1165 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1167 return aop->aopu.aop_str[offset];
1171 pCodeOp *pcop = aop->aopu.pcop;
1172 DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1175 DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
1176 sprintf(s,"(%s+%d)", pcop->name,offset);
1178 DEBUGpic14_emitcode(";","%s",pcop->name);
1179 sprintf(s,"%s", pcop->name);
1182 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1185 rs = Safe_calloc(1,strlen(s)+1);
1191 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1192 "aopget got unsupported aop->type");
1197 /*-----------------------------------------------------------------*/
1198 /* popGetTempReg - create a new temporary pCodeOp */
1199 /*-----------------------------------------------------------------*/
1200 pCodeOp *popGetTempReg(void)
1205 pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1206 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1207 PCOR(pcop)->r->wasUsed=1;
1208 PCOR(pcop)->r->isFree=0;
1214 /*-----------------------------------------------------------------*/
1215 /* popReleaseTempReg - create a new temporary pCodeOp */
1216 /*-----------------------------------------------------------------*/
1217 void popReleaseTempReg(pCodeOp *pcop)
1220 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1221 PCOR(pcop)->r->isFree = 1;
1224 /*-----------------------------------------------------------------*/
1225 /* popGetLabel - create a new pCodeOp of type PO_LABEL */
1226 /*-----------------------------------------------------------------*/
1227 pCodeOp *popGetLabel(unsigned int key)
1230 DEBUGpic14_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1232 if(key>(unsigned int)max_key)
1235 return newpCodeOpLabel(NULL,key+100+labelOffset);
1238 /*-------------------------------------------------------------------*/
1239 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1240 /*-------------------------------------------------------------------*/
1241 pCodeOp *popGetHighLabel(unsigned int key)
1244 pcop = popGetLabel(key);
1245 PCOLAB(pcop)->offset = 1;
1249 /*-----------------------------------------------------------------*/
1250 /* popGetLit - asm operator to pcode operator conversion */
1251 /*-----------------------------------------------------------------*/
1252 pCodeOp *popGetLit(unsigned int lit)
1255 return newpCodeOpLit(lit);
1258 /*-----------------------------------------------------------------*/
1259 /* popGetImmd - asm operator to pcode immediate conversion */
1260 /*-----------------------------------------------------------------*/
1261 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1264 return newpCodeOpImmd(name, offset,index, 0, is_func);
1268 /*-----------------------------------------------------------------*/
1269 /* popGetWithString - asm operator to pcode operator conversion */
1270 /*-----------------------------------------------------------------*/
1271 pCodeOp *popGetWithString(char *str, int isExtern)
1277 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1281 pcop = newpCodeOp(str,PO_STR);
1282 PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1287 /*-----------------------------------------------------------------*/
1288 /* popRegFromString - */
1289 /*-----------------------------------------------------------------*/
1290 pCodeOp *popRegFromString(char *str, int size, int offset)
1293 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1294 pcop->type = PO_DIR;
1296 DEBUGpic14_emitcode(";","%d",__LINE__);
1301 pcop->name = Safe_calloc(1,strlen(str)+1);
1302 strcpy(pcop->name,str);
1304 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1306 PCOR(pcop)->r = dirregWithName(pcop->name);
1307 if(PCOR(pcop)->r == NULL) {
1308 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1309 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1310 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1312 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1314 PCOR(pcop)->instance = offset;
1319 /*-----------------------------------------------------------------*/
1320 /*-----------------------------------------------------------------*/
1321 pCodeOp *popRegFromIdx(int rIdx)
1325 DEBUGpic14_emitcode ("; ***","%s,%d , rIdx=0x%x",
1326 __FUNCTION__,__LINE__,rIdx);
1328 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1330 PCOR(pcop)->rIdx = rIdx;
1331 PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1332 PCOR(pcop)->r->isFree = 0;
1333 PCOR(pcop)->r->wasUsed = 1;
1335 pcop->type = PCOR(pcop)->r->pc_type;
1341 /*-----------------------------------------------------------------*/
1342 /* popGet - asm operator to pcode operator conversion */
1343 /*-----------------------------------------------------------------*/
1344 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1346 //char *s = buffer ;
1351 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1352 /* offset is greater than
1355 if (!(offset >= 0 && ((offset < aop->size) || (aop->size == 0))))
1357 fprintf (stderr, "%s:%u: offset=%d, aop-type:%s, size:%d\n", __FILE__, __LINE__, offset, AopType (aop->type), aop->size);
1359 assert (offset >= 0 && ((offset < aop->size) || (aop->size == 0)));
1361 /* XXX: still needed for BIT operands (AOP_CRY) */
1362 if (offset > (aop->size - 1) &&
1363 aop->type != AOP_LIT)
1364 return NULL; //zero;
1366 /* depending on type */
1367 switch (aop->type) {
1374 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1378 DEBUGpic14_emitcode(";","%d",__LINE__);
1379 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1382 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1384 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1385 pcop->type = PO_DIR;
1387 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1388 strcpy(pcop->name,aop->aopu.aop_dir);
1389 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1390 if(PCOR(pcop)->r == NULL) {
1391 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1392 PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1393 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1395 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1397 PCOR(pcop)->instance = offset;
1404 int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1406 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1407 PCOR(pcop)->rIdx = rIdx;
1408 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1409 PCOR(pcop)->r->wasUsed=1;
1410 PCOR(pcop)->r->isFree=0;
1412 PCOR(pcop)->instance = offset;
1413 pcop->type = PCOR(pcop)->r->pc_type;
1414 //rs = aop->aopu.aop_reg[offset]->name;
1415 DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1420 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1421 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1422 //if(PCOR(pcop)->r == NULL)
1423 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1427 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1430 DEBUGpic14_emitcode(";","%d %s",__LINE__,aop->aopu.aop_str[offset]);
1431 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1433 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1434 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1435 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1436 pcop->type = PCOR(pcop)->r->pc_type;
1437 pcop->name = PCOR(pcop)->r->name;
1444 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1446 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1447 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1448 switch (aop->aopu.pcop->type)
1451 pcop = pCodeOpCopy (aop->aopu.pcop);
1452 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1453 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1454 PCOI(pcop)->index += offset;
1455 //PCOI(pcop)->offset = 0;
1458 pcop = pCodeOpCopy (aop->aopu.pcop);
1459 PCOR(pcop)->instance = offset;
1462 assert ( !"unhandled pCode type" );
1468 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1469 "popGet got unsupported aop->type");
1473 /*-----------------------------------------------------------------*/
1474 /* popGetAddr - access the low/high word of a symbol (immediate) */
1475 /* (for non-PO_IMMEDIATEs this is the same as poGet) */
1476 /*-----------------------------------------------------------------*/
1477 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1479 if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1481 pCodeOp *pcop = aop->aopu.pcop;
1482 pcop = pCodeOpCopy (pcop);
1483 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1484 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1485 PCOI(pcop)->offset += offset;
1486 PCOI(pcop)->index += index;
1489 return popGet (aop, offset + index);
1493 /*-----------------------------------------------------------------*/
1494 /* aopPut - puts a string for a aop */
1495 /*-----------------------------------------------------------------*/
1496 void aopPut (asmop *aop, char *s, int offset)
1501 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1503 if (aop->size && offset > ( aop->size - 1)) {
1504 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1505 "aopPut got offset > aop->size");
1509 /* will assign value to value */
1510 /* depending on where it is ofcourse */
1511 switch (aop->type) {
1514 sprintf(d,"(%s + %d)",
1515 aop->aopu.aop_dir,offset);
1516 fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1519 sprintf(d,"%s",aop->aopu.aop_dir);
1522 DEBUGpic14_emitcode(";","%d",__LINE__);
1524 pic14_emitcode("movf","%s,w",s);
1525 pic14_emitcode("movwf","%s",d);
1528 pic14_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
1529 if(offset >= aop->size) {
1530 emitpcode(POC_CLRF,popGet(aop,offset));
1533 emitpcode(POC_MOVLW,popGetImmd(s,offset,0,0));
1536 emitpcode(POC_MOVWF,popGet(aop,offset));
1543 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1544 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1547 strcmp(s,"r0") == 0 ||
1548 strcmp(s,"r1") == 0 ||
1549 strcmp(s,"r2") == 0 ||
1550 strcmp(s,"r3") == 0 ||
1551 strcmp(s,"r4") == 0 ||
1552 strcmp(s,"r5") == 0 ||
1553 strcmp(s,"r6") == 0 ||
1554 strcmp(s,"r7") == 0 )
1555 pic14_emitcode("mov","%s,%s ; %d",
1556 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1560 if(strcmp(s,"W")==0 )
1561 pic14_emitcode("movf","%s,w ; %d",s,__LINE__);
1563 pic14_emitcode("movwf","%s",
1564 aop->aopu.aop_reg[offset]->name);
1566 if(strcmp(s,zero)==0) {
1567 emitpcode(POC_CLRF,popGet(aop,offset));
1569 } else if(strcmp(s,"W")==0) {
1570 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1571 pcop->type = PO_GPR_REGISTER;
1573 PCOR(pcop)->rIdx = -1;
1574 PCOR(pcop)->r = NULL;
1576 DEBUGpic14_emitcode(";","%d",__LINE__);
1577 pcop->name = Safe_strdup(s);
1578 emitpcode(POC_MOVFW,pcop);
1579 emitpcode(POC_MOVWF,popGet(aop,offset));
1580 } else if(strcmp(s,one)==0) {
1581 emitpcode(POC_CLRF,popGet(aop,offset));
1582 emitpcode(POC_INCF,popGet(aop,offset));
1584 emitpcode(POC_MOVWF,popGet(aop,offset));
1592 if (aop->type == AOP_DPTR2)
1598 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1599 "aopPut writting to code space");
1603 while (offset > aop->coff) {
1605 pic14_emitcode ("inc","dptr");
1608 while (offset < aop->coff) {
1610 pic14_emitcode("lcall","__decdptr");
1615 /* if not in accumulater */
1618 pic14_emitcode ("movx","@dptr,a");
1620 if (aop->type == AOP_DPTR2)
1628 while (offset > aop->coff) {
1630 pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1632 while (offset < aop->coff) {
1634 pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1640 pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1645 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1647 if (strcmp(s,"r0") == 0 ||
1648 strcmp(s,"r1") == 0 ||
1649 strcmp(s,"r2") == 0 ||
1650 strcmp(s,"r3") == 0 ||
1651 strcmp(s,"r4") == 0 ||
1652 strcmp(s,"r5") == 0 ||
1653 strcmp(s,"r6") == 0 ||
1654 strcmp(s,"r7") == 0 ) {
1656 sprintf(buffer,"a%s",s);
1657 pic14_emitcode("mov","@%s,%s",
1658 aop->aopu.aop_ptr->name,buffer);
1660 pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1665 if (strcmp(s,"a") == 0)
1666 pic14_emitcode("push","acc");
1668 pic14_emitcode("push","%s",s);
1673 /* if bit variable */
1674 if (!aop->aopu.aop_dir) {
1675 pic14_emitcode("clr","a");
1676 pic14_emitcode("rlc","a");
1679 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1682 pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1685 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1687 lbl = newiTempLabel(NULL);
1689 if (strcmp(s,"a")) {
1692 pic14_emitcode("clr","c");
1693 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1694 pic14_emitcode("cpl","c");
1695 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1696 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1703 if (strcmp(aop->aopu.aop_str[offset],s))
1704 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1709 if (!offset && (strcmp(s,"acc") == 0))
1712 if (strcmp(aop->aopu.aop_str[offset],s))
1713 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1717 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1718 "aopPut got unsupported aop->type");
1724 /*-----------------------------------------------------------------*/
1725 /* mov2w - generate either a MOVLW or MOVFW based operand type */
1726 /*-----------------------------------------------------------------*/
1727 void mov2w (asmop *aop, int offset)
1733 DEBUGpic14_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
1735 if ( aop_isLitLike (aop) )
1736 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1738 emitpcode(POC_MOVFW,popGet(aop,offset));
1742 /*-----------------------------------------------------------------*/
1743 /* reAdjustPreg - points a register back to where it should */
1744 /*-----------------------------------------------------------------*/
1745 static void reAdjustPreg (asmop *aop)
1749 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1751 if ((size = aop->size) <= 1)
1754 switch (aop->type) {
1758 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1762 if (aop->type == AOP_DPTR2)
1768 pic14_emitcode("lcall","__decdptr");
1771 if (aop->type == AOP_DPTR2)
1783 /*-----------------------------------------------------------------*/
1784 /* opIsGptr: returns non-zero if the passed operand is */
1785 /* a generic pointer type. */
1786 /*-----------------------------------------------------------------*/
1787 static int opIsGptr(operand *op)
1789 sym_link *type = operandType(op);
1791 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1792 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1800 /*-----------------------------------------------------------------*/
1801 /* pic14_getDataSize - get the operand data size */
1802 /*-----------------------------------------------------------------*/
1803 int pic14_getDataSize(operand *op)
1805 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1808 return AOP_SIZE(op);
1810 // tsd- in the pic port, the genptr size is 1, so this code here
1811 // fails. ( in the 8051 port, the size was 4).
1814 size = AOP_SIZE(op);
1815 if (size == GPTRSIZE)
1817 sym_link *type = operandType(op);
1818 if (IS_GENPTR(type))
1820 /* generic pointer; arithmetic operations
1821 * should ignore the high byte (pointer type).
1824 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1831 /*-----------------------------------------------------------------*/
1832 /* pic14_outAcc - output Acc */
1833 /*-----------------------------------------------------------------*/
1834 void pic14_outAcc(operand *result)
1837 DEBUGpic14_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
1838 DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1841 size = pic14_getDataSize(result);
1843 emitpcode(POC_MOVWF,popGet(AOP(result),0));
1846 /* unsigned or positive */
1848 emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1853 /*-----------------------------------------------------------------*/
1854 /* pic14_outBitC - output a bit C */
1855 /*-----------------------------------------------------------------*/
1856 void pic14_outBitC(operand *result)
1859 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1860 /* if the result is bit */
1861 if (AOP_TYPE(result) == AOP_CRY)
1862 aopPut(AOP(result),"c",0);
1864 pic14_emitcode("clr","a ; %d", __LINE__);
1865 pic14_emitcode("rlc","a");
1866 pic14_outAcc(result);
1870 /*-----------------------------------------------------------------*/
1871 /* pic14_toBoolean - emit code for orl a,operator(sizeop) */
1872 /*-----------------------------------------------------------------*/
1873 void pic14_toBoolean(operand *oper)
1875 int size = AOP_SIZE(oper) - 1;
1878 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1880 if ( AOP_TYPE(oper) != AOP_ACC) {
1881 emitpcode(POC_MOVFW,popGet(AOP(oper),0));
1884 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
1889 /*-----------------------------------------------------------------*/
1890 /* genNot - generate code for ! operation */
1891 /*-----------------------------------------------------------------*/
1892 static void genNot (iCode *ic)
1899 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1900 /* assign asmOps to operand & result */
1901 aopOp (IC_LEFT(ic),ic,FALSE);
1902 aopOp (IC_RESULT(ic),ic,TRUE);
1904 DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1905 /* if in bit space then a special case */
1906 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1907 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1908 emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
1909 emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
1911 emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
1912 emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
1913 emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
1918 size = AOP_SIZE(IC_LEFT(ic));
1920 emitpcode(POC_COMFW,popGet(AOP(IC_LEFT(ic)),0));
1921 emitpcode(POC_ANDLW,popGetLit(1));
1922 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
1925 pic14_toBoolean(IC_LEFT(ic));
1927 tlbl = newiTempLabel(NULL);
1928 pic14_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1929 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
1930 pic14_outBitC(IC_RESULT(ic));
1933 /* release the aops */
1934 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1935 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1939 /*-----------------------------------------------------------------*/
1940 /* genCpl - generate code for complement */
1941 /*-----------------------------------------------------------------*/
1942 static void genCpl (iCode *ic)
1944 operand *left, *result;
1949 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1950 aopOp((left = IC_LEFT(ic)),ic,FALSE);
1951 aopOp((result=IC_RESULT(ic)),ic,TRUE);
1953 /* if both are in bit space then
1955 if (AOP_TYPE(result) == AOP_CRY &&
1956 AOP_TYPE(left) == AOP_CRY ) {
1958 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir);
1959 pic14_emitcode("cpl","c");
1960 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir);
1964 size = AOP_SIZE(result);
1967 if(AOP_TYPE(left) == AOP_ACC)
1968 emitpcode(POC_XORLW, popGetLit(0xff));
1970 emitpcode(POC_COMFW,popGet(AOP(left),offset));
1972 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
1978 /* release the aops */
1979 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1980 freeAsmop(result,NULL,ic,TRUE);
1983 /*-----------------------------------------------------------------*/
1984 /* genUminusFloat - unary minus for floating points */
1985 /*-----------------------------------------------------------------*/
1986 static void genUminusFloat(operand *op,operand *result)
1988 int size ,offset =0 ;
1993 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1994 /* for this we just need to flip the
1995 first it then copy the rest in place */
1996 size = AOP_SIZE(op) - 1;
1997 l = aopGet(AOP(op),3,FALSE,FALSE);
2001 pic14_emitcode("cpl","acc.7");
2002 aopPut(AOP(result),"a",3);
2006 aopGet(AOP(op),offset,FALSE,FALSE),
2012 /*-----------------------------------------------------------------*/
2013 /* genUminus - unary minus code generation */
2014 /*-----------------------------------------------------------------*/
2015 static void genUminus (iCode *ic)
2018 sym_link *optype, *rtype;
2022 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2024 aopOp(IC_LEFT(ic),ic,FALSE);
2025 aopOp(IC_RESULT(ic),ic,TRUE);
2027 /* if both in bit space then special
2029 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2030 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2032 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0));
2033 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2034 emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0));
2039 optype = operandType(IC_LEFT(ic));
2040 rtype = operandType(IC_RESULT(ic));
2042 /* if float then do float stuff */
2043 if (IS_FLOAT(optype)) {
2044 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2048 /* otherwise subtract from zero by taking the 2's complement */
2049 size = AOP_SIZE(IC_LEFT(ic));
2051 for(i=0; i<size; i++) {
2052 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2053 emitpcode(POC_COMF, popGet(AOP(IC_LEFT(ic)),i));
2055 emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2056 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2060 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0));
2061 for(i=1; i<size; i++) {
2063 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),i));
2067 /* release the aops */
2068 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2069 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2072 /*-----------------------------------------------------------------*/
2073 /* saveRegisters - will look for a call and save the registers */
2074 /*-----------------------------------------------------------------*/
2075 static void saveRegisters(iCode *lic)
2084 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2086 for (ic = lic ; ic ; ic = ic->next)
2087 if (ic->op == CALL || ic->op == PCALL)
2091 fprintf(stderr,"found parameter push with no function call\n");
2095 /* if the registers have been saved already then
2097 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2100 /* find the registers in use at this time
2101 and push them away to safety */
2102 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2106 if (options.useXstack) {
2107 if (bitVectBitValue(rsave,R0_IDX))
2108 pic14_emitcode("mov","b,r0");
2109 pic14_emitcode("mov","r0,%s",spname);
2110 for (i = 0 ; i < pic14_nRegs ; i++) {
2111 if (bitVectBitValue(rsave,i)) {
2113 pic14_emitcode("mov","a,b");
2115 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2116 pic14_emitcode("movx","@r0,a");
2117 pic14_emitcode("inc","r0");
2120 pic14_emitcode("mov","%s,r0",spname);
2121 if (bitVectBitValue(rsave,R0_IDX))
2122 pic14_emitcode("mov","r0,b");
2124 //for (i = 0 ; i < pic14_nRegs ; i++) {
2125 // if (bitVectBitValue(rsave,i))
2126 // pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2129 dtype = operandType(IC_LEFT(ic));
2130 if (currFunc && dtype &&
2131 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2132 IFFUNC_ISISR(currFunc->type) &&
2135 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2138 /*-----------------------------------------------------------------*/
2139 /* unsaveRegisters - pop the pushed registers */
2140 /*-----------------------------------------------------------------*/
2141 static void unsaveRegisters (iCode *ic)
2148 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2149 /* find the registers in use at this time
2150 and push them away to safety */
2151 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2154 if (options.useXstack) {
2155 pic14_emitcode("mov","r0,%s",spname);
2156 for (i = pic14_nRegs ; i >= 0 ; i--) {
2157 if (bitVectBitValue(rsave,i)) {
2158 pic14_emitcode("dec","r0");
2159 pic14_emitcode("movx","a,@r0");
2161 pic14_emitcode("mov","b,a");
2163 pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2167 pic14_emitcode("mov","%s,r0",spname);
2168 if (bitVectBitValue(rsave,R0_IDX))
2169 pic14_emitcode("mov","r0,b");
2171 //for (i = pic14_nRegs ; i >= 0 ; i--) {
2172 // if (bitVectBitValue(rsave,i))
2173 // pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2179 /*-----------------------------------------------------------------*/
2181 /*-----------------------------------------------------------------*/
2182 static void pushSide(operand * oper, int size)
2186 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2188 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2189 if (AOP_TYPE(oper) != AOP_REG &&
2190 AOP_TYPE(oper) != AOP_DIR &&
2192 pic14_emitcode("mov","a,%s",l);
2193 pic14_emitcode("push","acc");
2195 pic14_emitcode("push","%s",l);
2200 /*-----------------------------------------------------------------*/
2201 /* assignResultValue - */
2202 /*-----------------------------------------------------------------*/
2203 static void assignResultValue(operand * oper)
2205 int size = AOP_SIZE(oper);
2209 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2211 DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2214 if (GpsuedoStkPtr++)
2215 emitpcode(POC_MOVFW,popRegFromIdx(Gstack_base_addr+2-GpsuedoStkPtr));
2216 emitpcode(POC_MOVWF, popGet(AOP(oper),size));
2221 /*-----------------------------------------------------------------*/
2222 /* genIpush - genrate code for pushing this gets a little complex */
2223 /*-----------------------------------------------------------------*/
2224 static void genIpush (iCode *ic)
2228 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2230 int size, offset = 0 ;
2234 /* if this is not a parm push : ie. it is spill push
2235 and spill push is always done on the local stack */
2236 if (!ic->parmPush) {
2238 /* and the item is spilt then do nothing */
2239 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2242 aopOp(IC_LEFT(ic),ic,FALSE);
2243 size = AOP_SIZE(IC_LEFT(ic));
2244 /* push it on the stack */
2246 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2251 pic14_emitcode("push","%s",l);
2256 /* this is a paramter push: in this case we call
2257 the routine to find the call and save those
2258 registers that need to be saved */
2261 /* then do the push */
2262 aopOp(IC_LEFT(ic),ic,FALSE);
2265 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2266 size = AOP_SIZE(IC_LEFT(ic));
2269 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2270 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
2271 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2273 pic14_emitcode("mov","a,%s",l);
2274 pic14_emitcode("push","acc");
2276 pic14_emitcode("push","%s",l);
2279 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2283 /*-----------------------------------------------------------------*/
2284 /* genIpop - recover the registers: can happen only for spilling */
2285 /*-----------------------------------------------------------------*/
2286 static void genIpop (iCode *ic)
2290 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2295 /* if the temp was not pushed then */
2296 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2299 aopOp(IC_LEFT(ic),ic,FALSE);
2300 size = AOP_SIZE(IC_LEFT(ic));
2303 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2306 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2310 /*-----------------------------------------------------------------*/
2311 /* unsaverbank - restores the resgister bank from stack */
2312 /*-----------------------------------------------------------------*/
2313 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2317 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2323 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2325 if (options.useXstack) {
2327 r = getFreePtr(ic,&aop,FALSE);
2330 pic14_emitcode("mov","%s,_spx",r->name);
2331 pic14_emitcode("movx","a,@%s",r->name);
2332 pic14_emitcode("mov","psw,a");
2333 pic14_emitcode("dec","%s",r->name);
2336 pic14_emitcode ("pop","psw");
2339 for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2340 if (options.useXstack) {
2341 pic14_emitcode("movx","a,@%s",r->name);
2342 //pic14_emitcode("mov","(%s+%d),a",
2343 // regspic14[i].base,8*bank+regspic14[i].offset);
2344 pic14_emitcode("dec","%s",r->name);
2347 pic14_emitcode("pop",""); //"(%s+%d)",
2348 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2351 if (options.useXstack) {
2353 pic14_emitcode("mov","_spx,%s",r->name);
2354 freeAsmop(NULL,aop,ic,TRUE);
2360 /*-----------------------------------------------------------------*/
2361 /* saverbank - saves an entire register bank on the stack */
2362 /*-----------------------------------------------------------------*/
2363 static void saverbank (int bank, iCode *ic, bool pushPsw)
2367 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2373 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2374 if (options.useXstack) {
2377 r = getFreePtr(ic,&aop,FALSE);
2378 pic14_emitcode("mov","%s,_spx",r->name);
2382 for (i = 0 ; i < pic14_nRegs ;i++) {
2383 if (options.useXstack) {
2384 pic14_emitcode("inc","%s",r->name);
2385 //pic14_emitcode("mov","a,(%s+%d)",
2386 // regspic14[i].base,8*bank+regspic14[i].offset);
2387 pic14_emitcode("movx","@%s,a",r->name);
2389 pic14_emitcode("push","");// "(%s+%d)",
2390 //regspic14[i].base,8*bank+regspic14[i].offset);
2394 if (options.useXstack) {
2395 pic14_emitcode("mov","a,psw");
2396 pic14_emitcode("movx","@%s,a",r->name);
2397 pic14_emitcode("inc","%s",r->name);
2398 pic14_emitcode("mov","_spx,%s",r->name);
2399 freeAsmop (NULL,aop,ic,TRUE);
2402 pic14_emitcode("push","psw");
2404 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2410 /*-----------------------------------------------------------------*/
2411 /* genCall - generates a call statement */
2412 /*-----------------------------------------------------------------*/
2413 static void genCall (iCode *ic)
2417 unsigned char *name;
2422 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2424 /* if caller saves & we have not saved then */
2428 /* if we are calling a function that is not using
2429 the same register bank then we need to save the
2430 destination registers on the stack */
2431 dtype = operandType(IC_LEFT(ic));
2432 if (currFunc && dtype &&
2433 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2434 IFFUNC_ISISR(currFunc->type) &&
2437 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2439 /* if send set is not empty the assign */
2442 /* For the Pic port, there is no data stack.
2443 * So parameters passed to functions are stored
2444 * in registers. (The pCode optimizer will get
2445 * rid of most of these :).
2447 int psuedoStkPtr=-1;
2448 int firstTimeThruLoop = 1;
2450 _G.sendSet = reverseSet(_G.sendSet);
2452 /* First figure how many parameters are getting passed */
2453 for (sic = setFirstItem(_G.sendSet) ; sic ;
2454 sic = setNextItem(_G.sendSet)) {
2456 aopOp(IC_LEFT(sic),sic,FALSE);
2457 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2458 freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2461 for (sic = setFirstItem(_G.sendSet) ; sic ;
2462 sic = setNextItem(_G.sendSet)) {
2463 int size, offset = 0;
2465 aopOp(IC_LEFT(sic),sic,FALSE);
2466 size = AOP_SIZE(IC_LEFT(sic));
2469 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2470 AopType(AOP_TYPE(IC_LEFT(sic))));
2472 if(!firstTimeThruLoop) {
2473 /* If this is not the first time we've been through the loop
2474 * then we need to save the parameter in a temporary
2475 * register. The last byte of the last parameter is
2477 emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2480 firstTimeThruLoop=0;
2482 mov2w (AOP(IC_LEFT(sic)), offset);
2485 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2490 sym = OP_SYMBOL(IC_LEFT(ic));
2491 name = sym->rname[0] ? sym->rname : sym->name;
2492 isExtern = IS_EXTERN(sym->etype);
2494 emitpcode(POC_PAGESEL,popGetWithString(name,1)); /* Extern functions maybe on another page - must call pagesel */
2496 emitpcode(POC_CALL,popGetWithString(name,isExtern));
2498 emitpcode(POC_PAGESEL,popGetWithString("$",0)); /* May have returned from another page - must call pagesel to restore PCLATH before next goto or call instruction */
2501 /* if we need assign a result value */
2502 if ((IS_ITEMP(IC_RESULT(ic)) &&
2503 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2504 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2505 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2508 aopOp(IC_RESULT(ic),ic,FALSE);
2511 assignResultValue(IC_RESULT(ic));
2513 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2514 AopType(AOP_TYPE(IC_RESULT(ic))));
2516 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2519 /* adjust the stack for parameters if
2521 if (ic->parmBytes) {
2523 if (ic->parmBytes > 3) {
2524 pic14_emitcode("mov","a,%s",spname);
2525 pic14_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2526 pic14_emitcode("mov","%s,a",spname);
2528 for ( i = 0 ; i < ic->parmBytes ;i++)
2529 pic14_emitcode("dec","%s",spname);
2533 /* if register bank was saved then pop them */
2535 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2537 /* if we hade saved some registers then unsave them */
2538 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2539 unsaveRegisters (ic);
2544 /*-----------------------------------------------------------------*/
2545 /* genPcall - generates a call by pointer statement */
2546 /*-----------------------------------------------------------------*/
2547 static void genPcall (iCode *ic)
2550 symbol *albl = newiTempLabel(NULL);
2551 symbol *blbl = newiTempLabel(NULL);
2558 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2559 /* if caller saves & we have not saved then */
2563 /* if we are calling a function that is not using
2564 the same register bank then we need to save the
2565 destination registers on the stack */
2566 dtype = operandType(IC_LEFT(ic));
2567 if (currFunc && dtype &&
2568 IFFUNC_ISISR(currFunc->type) &&
2569 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2570 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2573 aopOp(left,ic,FALSE);
2574 DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2576 pushSide(IC_LEFT(ic), FPTRSIZE);
2578 /* if send set is not empty, assign parameters */
2581 DEBUGpic14_emitcode ("; ***","%s %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2582 /* no way to pass args - W always gets used to make the call */
2584 /* first idea - factor out a common helper function and call it.
2585 But don't know how to get it generated only once in its own block
2587 if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2590 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2591 DEBUGpic14_emitcode ("; ***","%s %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2592 buffer = Safe_calloc(1,strlen(rname)+16);
2593 sprintf(buffer, "%s_goto_helper", rname);
2594 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2598 emitpcode(POC_CALL,popGetLabel(albl->key));
2599 pcop = popGetLabel(blbl->key);
2600 emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
2601 emitpcode(POC_GOTO,pcop);
2602 emitpLabel(albl->key);
2604 poc = ( aop_isLitLike (AOP(left)) ? POC_MOVLW : POC_MOVFW );
2606 emitpcode(poc,popGetAddr(AOP(left),1,0));
2607 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2608 emitpcode(poc,popGetAddr(AOP(left),0,0));
2609 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2611 emitpLabel(blbl->key);
2613 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2615 /* if we need to assign a result value */
2616 if ((IS_ITEMP(IC_RESULT(ic)) &&
2617 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2618 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2619 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2622 aopOp(IC_RESULT(ic),ic,FALSE);
2625 assignResultValue(IC_RESULT(ic));
2627 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2630 /* if register bank was saved then unsave them */
2631 if (currFunc && dtype &&
2632 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2633 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2635 /* if we hade saved some registers then
2638 unsaveRegisters (ic);
2642 /*-----------------------------------------------------------------*/
2643 /* resultRemat - result is rematerializable */
2644 /*-----------------------------------------------------------------*/
2645 static int resultRemat (iCode *ic)
2647 // DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2650 if (SKIP_IC(ic) || ic->op == IFX)
2653 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2654 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2655 if (sym->remat && !POINTER_SET(ic))
2662 #if defined(__BORLANDC__) || defined(_MSC_VER)
2663 #define STRCASECMP stricmp
2665 #define STRCASECMP strcasecmp
2669 /*-----------------------------------------------------------------*/
2670 /* inExcludeList - return 1 if the string is in exclude Reg list */
2671 /*-----------------------------------------------------------------*/
2672 static bool inExcludeList(char *s)
2674 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2677 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2678 if (options.excludeRegs[i] &&
2679 STRCASECMP(options.excludeRegs[i],"none") == 0)
2682 for ( i = 0 ; options.excludeRegs[i]; i++) {
2683 if (options.excludeRegs[i] &&
2684 STRCASECMP(s,options.excludeRegs[i]) == 0)
2691 /*-----------------------------------------------------------------*/
2692 /* genFunction - generated code for function entry */
2693 /*-----------------------------------------------------------------*/
2694 static void genFunction (iCode *ic)
2701 DEBUGpic14_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2703 labelOffset += (max_key+4);
2707 /* create the function header */
2708 pic14_emitcode(";","-----------------------------------------");
2709 pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2710 pic14_emitcode(";","-----------------------------------------");
2712 pic14_emitcode("","%s:",sym->rname);
2713 addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2715 ftype = operandType(IC_LEFT(ic));
2717 /* if critical function then turn interrupts off */
2718 if (IFFUNC_ISCRITICAL(ftype))
2719 pic14_emitcode("clr","ea");
2721 /* here we need to generate the equates for the
2722 register bank if required */
2724 if (FUNC_REGBANK(ftype) != rbank) {
2727 rbank = FUNC_REGBANK(ftype);
2728 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2729 if (strcmp(regspic14[i].base,"0") == 0)
2730 pic14_emitcode("","%s = 0x%02x",
2732 8*rbank+regspic14[i].offset);
2734 pic14_emitcode ("","%s = %s + 0x%02x",
2737 8*rbank+regspic14[i].offset);
2742 /* if this is an interrupt service routine */
2743 if (IFFUNC_ISISR(sym->type)) {
2744 /* already done in pic14createInterruptVect() - delete me
2745 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2746 emitpcodeNULLop(POC_NOP);
2747 emitpcodeNULLop(POC_NOP);
2748 emitpcodeNULLop(POC_NOP);
2750 emitpcode(POC_MOVWF, popCopyReg(&pc_wsave));
2751 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2752 emitpcode(POC_CLRF, popCopyReg(&pc_status));
2753 emitpcode(POC_MOVWF, popCopyReg(&pc_ssave));
2754 emitpcode(POC_MOVFW, popCopyReg(&pc_pclath));
2755 emitpcode(POC_MOVWF, popCopyReg(&pc_psave));
2756 emitpcode(POC_CLRF, popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2758 pBlockConvert2ISR(pb);
2760 if (!inExcludeList("acc"))
2761 pic14_emitcode ("push","acc");
2762 if (!inExcludeList("b"))
2763 pic14_emitcode ("push","b");
2764 if (!inExcludeList("dpl"))
2765 pic14_emitcode ("push","dpl");
2766 if (!inExcludeList("dph"))
2767 pic14_emitcode ("push","dph");
2768 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2770 pic14_emitcode ("push", "dpx");
2771 /* Make sure we're using standard DPTR */
2772 pic14_emitcode ("push", "dps");
2773 pic14_emitcode ("mov", "dps, #0x00");
2774 if (options.stack10bit)
2776 /* This ISR could conceivably use DPTR2. Better save it. */
2777 pic14_emitcode ("push", "dpl1");
2778 pic14_emitcode ("push", "dph1");
2779 pic14_emitcode ("push", "dpx1");
2782 /* if this isr has no bank i.e. is going to
2783 run with bank 0 , then we need to save more
2785 if (!FUNC_REGBANK(sym->type)) {
2787 /* if this function does not call any other
2788 function then we can be economical and
2789 save only those registers that are used */
2790 if (! IFFUNC_HASFCALL(sym->type)) {
2793 /* if any registers used */
2794 if (sym->regsUsed) {
2795 /* save the registers used */
2796 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2797 if (bitVectBitValue(sym->regsUsed,i) ||
2798 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2799 pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);
2804 /* this function has a function call cannot
2805 determines register usage so we will have the
2807 saverbank(0,ic,FALSE);
2812 /* if callee-save to be used for this function
2813 then save the registers being used in this function */
2814 if (IFFUNC_CALLEESAVES(sym->type)) {
2817 /* if any registers used */
2818 if (sym->regsUsed) {
2819 /* save the registers used */
2820 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2821 if (bitVectBitValue(sym->regsUsed,i) ||
2822 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2823 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2831 /* set the register bank to the desired value */
2832 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2833 pic14_emitcode("push","psw");
2834 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);
2837 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2839 if (options.useXstack) {
2840 pic14_emitcode("mov","r0,%s",spname);
2841 pic14_emitcode("mov","a,_bp");
2842 pic14_emitcode("movx","@r0,a");
2843 pic14_emitcode("inc","%s",spname);
2847 /* set up the stack */
2848 pic14_emitcode ("push","_bp"); /* save the callers stack */
2850 pic14_emitcode ("mov","_bp,%s",spname);
2853 /* adjust the stack for the function */
2858 werror(W_STACK_OVERFLOW,sym->name);
2860 if (i > 3 && sym->recvSize < 4) {
2862 pic14_emitcode ("mov","a,sp");
2863 pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2864 pic14_emitcode ("mov","sp,a");
2869 pic14_emitcode("inc","sp");
2874 pic14_emitcode ("mov","a,_spx");
2875 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2876 pic14_emitcode ("mov","_spx,a");
2881 /*-----------------------------------------------------------------*/
2882 /* genEndFunction - generates epilogue for functions */
2883 /*-----------------------------------------------------------------*/
2884 static void genEndFunction (iCode *ic)
2886 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2890 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2892 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2894 pic14_emitcode ("mov","%s,_bp",spname);
2897 /* if use external stack but some variables were
2898 added to the local stack then decrement the
2900 if (options.useXstack && sym->stack) {
2901 pic14_emitcode("mov","a,sp");
2902 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2903 pic14_emitcode("mov","sp,a");
2907 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2908 if (options.useXstack) {
2909 pic14_emitcode("mov","r0,%s",spname);
2910 pic14_emitcode("movx","a,@r0");
2911 pic14_emitcode("mov","_bp,a");
2912 pic14_emitcode("dec","%s",spname);
2916 pic14_emitcode ("pop","_bp");
2920 /* restore the register bank */
2921 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2922 pic14_emitcode ("pop","psw");
2924 if (IFFUNC_ISISR(sym->type)) {
2926 /* now we need to restore the registers */
2927 /* if this isr has no bank i.e. is going to
2928 run with bank 0 , then we need to save more
2930 if (!FUNC_REGBANK(sym->type)) {
2932 /* if this function does not call any other
2933 function then we can be economical and
2934 save only those registers that are used */
2935 if (! IFFUNC_HASFCALL(sym->type)) {
2938 /* if any registers used */
2939 if (sym->regsUsed) {
2940 /* save the registers used */
2941 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2942 if (bitVectBitValue(sym->regsUsed,i) ||
2943 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2944 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2949 /* this function has a function call cannot
2950 determines register usage so we will have the
2952 unsaverbank(0,ic,FALSE);
2956 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2958 if (options.stack10bit)
2960 pic14_emitcode ("pop", "dpx1");
2961 pic14_emitcode ("pop", "dph1");
2962 pic14_emitcode ("pop", "dpl1");
2964 pic14_emitcode ("pop", "dps");
2965 pic14_emitcode ("pop", "dpx");
2967 if (!inExcludeList("dph"))
2968 pic14_emitcode ("pop","dph");
2969 if (!inExcludeList("dpl"))
2970 pic14_emitcode ("pop","dpl");
2971 if (!inExcludeList("b"))
2972 pic14_emitcode ("pop","b");
2973 if (!inExcludeList("acc"))
2974 pic14_emitcode ("pop","acc");
2976 if (IFFUNC_ISCRITICAL(sym->type))
2977 pic14_emitcode("setb","ea");
2980 /* if debug then send end of function */
2981 /* if (options.debug && currFunc) { */
2983 debugFile->writeEndFunction (currFunc, ic, 1);
2986 pic14_emitcode ("reti","");
2987 emitpcode(POC_MOVFW, popCopyReg(&pc_psave));
2988 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
2989 emitpcode(POC_CLRF, popCopyReg(&pc_status));
2990 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
2991 emitpcode(POC_MOVWF, popCopyReg(&pc_status));
2992 emitpcode(POC_SWAPF, popCopyReg(&pc_wsave));
2993 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
2994 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
2995 emitpcodeNULLop(POC_RETFIE);
2998 if (IFFUNC_ISCRITICAL(sym->type))
2999 pic14_emitcode("setb","ea");
3001 if (IFFUNC_CALLEESAVES(sym->type)) {
3004 /* if any registers used */
3005 if (sym->regsUsed) {
3006 /* save the registers used */
3007 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3008 if (bitVectBitValue(sym->regsUsed,i) ||
3009 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3010 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3016 /* if debug then send end of function */
3018 debugFile->writeEndFunction (currFunc, ic, 1);
3021 pic14_emitcode ("return","");
3022 emitpcodeNULLop(POC_RETURN);
3024 /* Mark the end of a function */
3025 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3030 /*-----------------------------------------------------------------*/
3031 /* genRet - generate code for return statement */
3032 /*-----------------------------------------------------------------*/
3033 static void genRet (iCode *ic)
3035 int size,offset = 0 , pushed = 0;
3039 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3040 /* if we have no return value then
3041 just generate the "ret" */
3045 /* we have something to return then
3046 move the return value into place */
3047 aopOp(IC_LEFT(ic),ic,FALSE);
3048 size = AOP_SIZE(IC_LEFT(ic));
3052 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3054 l = aopGet(AOP(IC_LEFT(ic)),offset++,
3056 pic14_emitcode("push","%s",l);
3059 l = aopGet(AOP(IC_LEFT(ic)),offset,
3061 if (strcmp(fReturn[offset],l)) {
3062 if ((((AOP(IC_LEFT(ic))->type) == AOP_PCODE) &&
3063 AOP(IC_LEFT(ic))->aopu.pcop->type == PO_IMMEDIATE) ||
3064 ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
3065 ( (AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3066 emitpcode(POC_MOVLW, popGetAddr(AOP(IC_LEFT(ic)),offset,0));
3068 emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset));
3071 emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr+1-size));
3081 if (strcmp(fReturn[pushed],"a"))
3082 pic14_emitcode("pop",fReturn[pushed]);
3084 pic14_emitcode("pop","acc");
3087 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3090 /* generate a jump to the return label
3091 if the next is not the return statement */
3092 if (!(ic->next && ic->next->op == LABEL &&
3093 IC_LABEL(ic->next) == returnLabel)) {
3095 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3096 pic14_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3101 /*-----------------------------------------------------------------*/
3102 /* genLabel - generates a label */
3103 /*-----------------------------------------------------------------*/
3104 static void genLabel (iCode *ic)
3108 /* special case never generate */
3109 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3110 if (IC_LABEL(ic) == entryLabel)
3113 emitpLabel(IC_LABEL(ic)->key);
3114 pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3117 /*-----------------------------------------------------------------*/
3118 /* genGoto - generates a goto */
3119 /*-----------------------------------------------------------------*/
3121 static void genGoto (iCode *ic)
3125 emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3126 pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3130 /*-----------------------------------------------------------------*/
3131 /* genMultbits :- multiplication of bits */
3132 /*-----------------------------------------------------------------*/
3133 static void genMultbits (operand *left,
3138 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3140 if(!pic14_sameRegs(AOP(result),AOP(right)))
3141 emitpcode(POC_BSF, popGet(AOP(result),0));
3143 emitpcode(POC_BTFSC,popGet(AOP(right),0));
3144 emitpcode(POC_BTFSS,popGet(AOP(left),0));
3145 emitpcode(POC_BCF, popGet(AOP(result),0));
3150 /*-----------------------------------------------------------------*/
3151 /* genMultOneByte : 8 bit multiplication & division */
3152 /*-----------------------------------------------------------------*/
3153 static void genMultOneByte (operand *left,
3157 sym_link *opetype = operandType(result);
3164 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3165 DEBUGpic14_AopType(__LINE__,left,right,result);
3166 DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3168 /* (if two literals, the value is computed before) */
3169 /* if one literal, literal on the right */
3170 if (AOP_TYPE(left) == AOP_LIT){
3176 size = AOP_SIZE(result);
3179 if (AOP_TYPE(right) == AOP_LIT){
3180 pic14_emitcode("multiply ","lit val:%s by variable %s and store in %s",
3181 aopGet(AOP(right),0,FALSE,FALSE),
3182 aopGet(AOP(left),0,FALSE,FALSE),
3183 aopGet(AOP(result),0,FALSE,FALSE));
3184 pic14_emitcode("call","genMultLit");
3186 pic14_emitcode("multiply ","variable :%s by variable %s and store in %s",
3187 aopGet(AOP(right),0,FALSE,FALSE),
3188 aopGet(AOP(left),0,FALSE,FALSE),
3189 aopGet(AOP(result),0,FALSE,FALSE));
3190 pic14_emitcode("call","genMult8X8_8");
3193 genMult8X8_8 (left, right,result);
3196 /* signed or unsigned */
3197 //pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3198 //l = aopGet(AOP(left),0,FALSE,FALSE);
3200 //pic14_emitcode("mul","ab");
3201 /* if result size = 1, mul signed = mul unsigned */
3202 //aopPut(AOP(result),"a",0);
3204 } else { // (size > 1)
3206 pic14_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s",
3207 aopGet(AOP(right),0,FALSE,FALSE),
3208 aopGet(AOP(left),0,FALSE,FALSE),
3209 aopGet(AOP(result),0,FALSE,FALSE));
3211 if (SPEC_USIGN(opetype)){
3212 pic14_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3213 genUMult8X8_16 (left, right, result, NULL);
3216 /* for filling the MSBs */
3217 emitpcode(POC_CLRF, popGet(AOP(result),2));
3218 emitpcode(POC_CLRF, popGet(AOP(result),3));
3222 pic14_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3224 pic14_emitcode("mov","a,b");
3226 /* adjust the MSB if left or right neg */
3228 /* if one literal */
3229 if (AOP_TYPE(right) == AOP_LIT){
3230 pic14_emitcode("multiply ","right is a lit");
3231 /* AND literal negative */
3232 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3233 /* adjust MSB (c==0 after mul) */
3234 pic14_emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3238 genSMult8X8_16 (left, right, result, NULL);
3242 pic14_emitcode("multiply ","size is greater than 2, so propogate sign");
3244 pic14_emitcode("rlc","a");
3245 pic14_emitcode("subb","a,acc");
3253 pic14_emitcode("multiply ","size is way greater than 2, so propogate sign");
3254 //aopPut(AOP(result),"a",offset++);
3258 /*-----------------------------------------------------------------*/
3259 /* genMult - generates code for multiplication */
3260 /*-----------------------------------------------------------------*/
3261 static void genMult (iCode *ic)
3263 operand *left = IC_LEFT(ic);
3264 operand *right = IC_RIGHT(ic);
3265 operand *result= IC_RESULT(ic);
3269 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3270 /* assign the amsops */
3271 aopOp (left,ic,FALSE);
3272 aopOp (right,ic,FALSE);
3273 aopOp (result,ic,TRUE);
3275 DEBUGpic14_AopType(__LINE__,left,right,result);
3277 /* special cases first */
3279 if (AOP_TYPE(left) == AOP_CRY &&
3280 AOP_TYPE(right)== AOP_CRY) {
3281 genMultbits(left,right,result);
3285 /* if both are of size == 1 */
3286 if (AOP_SIZE(left) == 1 &&
3287 AOP_SIZE(right) == 1 ) {
3288 genMultOneByte(left,right,result);
3292 pic14_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3294 /* should have been converted to function call */
3298 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3299 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3300 freeAsmop(result,NULL,ic,TRUE);
3303 /*-----------------------------------------------------------------*/
3304 /* genDivbits :- division of bits */
3305 /*-----------------------------------------------------------------*/
3306 static void genDivbits (operand *left,
3315 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3316 /* the result must be bit */
3317 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3318 l = aopGet(AOP(left),0,FALSE,FALSE);
3322 pic14_emitcode("div","ab");
3323 pic14_emitcode("rrc","a");
3324 aopPut(AOP(result),"c",0);
3327 /*-----------------------------------------------------------------*/
3328 /* genDivOneByte : 8 bit division */
3329 /*-----------------------------------------------------------------*/
3330 static void genDivOneByte (operand *left,
3334 sym_link *opetype = operandType(result);
3340 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3341 size = AOP_SIZE(result) - 1;
3343 /* signed or unsigned */
3344 if (SPEC_USIGN(opetype)) {
3345 /* unsigned is easy */
3346 pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3347 l = aopGet(AOP(left),0,FALSE,FALSE);
3349 pic14_emitcode("div","ab");
3350 aopPut(AOP(result),"a",0);
3352 aopPut(AOP(result),zero,offset++);
3356 /* signed is a little bit more difficult */
3358 /* save the signs of the operands */
3359 l = aopGet(AOP(left),0,FALSE,FALSE);
3361 pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3362 pic14_emitcode("push","acc"); /* save it on the stack */
3364 /* now sign adjust for both left & right */
3365 l = aopGet(AOP(right),0,FALSE,FALSE);
3367 lbl = newiTempLabel(NULL);
3368 pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3369 pic14_emitcode("cpl","a");
3370 pic14_emitcode("inc","a");
3371 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3372 pic14_emitcode("mov","b,a");
3374 /* sign adjust left side */
3375 l = aopGet(AOP(left),0,FALSE,FALSE);
3378 lbl = newiTempLabel(NULL);
3379 pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3380 pic14_emitcode("cpl","a");
3381 pic14_emitcode("inc","a");
3382 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3384 /* now the division */
3385 pic14_emitcode("div","ab");
3386 /* we are interested in the lower order
3388 pic14_emitcode("mov","b,a");
3389 lbl = newiTempLabel(NULL);
3390 pic14_emitcode("pop","acc");
3391 /* if there was an over flow we don't
3392 adjust the sign of the result */
3393 pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3394 pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3396 pic14_emitcode("clr","a");
3397 pic14_emitcode("subb","a,b");
3398 pic14_emitcode("mov","b,a");
3399 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3401 /* now we are done */
3402 aopPut(AOP(result),"b",0);
3404 pic14_emitcode("mov","c,b.7");
3405 pic14_emitcode("subb","a,acc");
3408 aopPut(AOP(result),"a",offset++);
3412 /*-----------------------------------------------------------------*/
3413 /* genDiv - generates code for division */
3414 /*-----------------------------------------------------------------*/
3415 static void genDiv (iCode *ic)
3417 operand *left = IC_LEFT(ic);
3418 operand *right = IC_RIGHT(ic);
3419 operand *result= IC_RESULT(ic);
3422 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3423 /* assign the amsops */
3424 aopOp (left,ic,FALSE);
3425 aopOp (right,ic,FALSE);
3426 aopOp (result,ic,TRUE);
3428 /* special cases first */
3430 if (AOP_TYPE(left) == AOP_CRY &&
3431 AOP_TYPE(right)== AOP_CRY) {
3432 genDivbits(left,right,result);
3436 /* if both are of size == 1 */
3437 if (AOP_SIZE(left) == 1 &&
3438 AOP_SIZE(right) == 1 ) {
3439 genDivOneByte(left,right,result);
3443 /* should have been converted to function call */
3446 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3447 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3448 freeAsmop(result,NULL,ic,TRUE);
3451 /*-----------------------------------------------------------------*/
3452 /* genModbits :- modulus of bits */
3453 /*-----------------------------------------------------------------*/
3454 static void genModbits (operand *left,
3462 /* the result must be bit */
3463 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3464 l = aopGet(AOP(left),0,FALSE,FALSE);
3468 pic14_emitcode("div","ab");
3469 pic14_emitcode("mov","a,b");
3470 pic14_emitcode("rrc","a");
3471 aopPut(AOP(result),"c",0);
3474 /*-----------------------------------------------------------------*/
3475 /* genModOneByte : 8 bit modulus */
3476 /*-----------------------------------------------------------------*/
3477 static void genModOneByte (operand *left,
3481 sym_link *opetype = operandType(result);
3486 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3487 /* signed or unsigned */
3488 if (SPEC_USIGN(opetype)) {
3489 /* unsigned is easy */
3490 pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3491 l = aopGet(AOP(left),0,FALSE,FALSE);
3493 pic14_emitcode("div","ab");
3494 aopPut(AOP(result),"b",0);
3498 /* signed is a little bit more difficult */
3500 /* save the signs of the operands */
3501 l = aopGet(AOP(left),0,FALSE,FALSE);
3504 pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3505 pic14_emitcode("push","acc"); /* save it on the stack */
3507 /* now sign adjust for both left & right */
3508 l = aopGet(AOP(right),0,FALSE,FALSE);
3511 lbl = newiTempLabel(NULL);
3512 pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3513 pic14_emitcode("cpl","a");
3514 pic14_emitcode("inc","a");
3515 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3516 pic14_emitcode("mov","b,a");
3518 /* sign adjust left side */
3519 l = aopGet(AOP(left),0,FALSE,FALSE);
3522 lbl = newiTempLabel(NULL);
3523 pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3524 pic14_emitcode("cpl","a");
3525 pic14_emitcode("inc","a");
3526 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3528 /* now the multiplication */
3529 pic14_emitcode("div","ab");
3530 /* we are interested in the lower order
3532 lbl = newiTempLabel(NULL);
3533 pic14_emitcode("pop","acc");
3534 /* if there was an over flow we don't
3535 adjust the sign of the result */
3536 pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3537 pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3539 pic14_emitcode("clr","a");
3540 pic14_emitcode("subb","a,b");
3541 pic14_emitcode("mov","b,a");
3542 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3544 /* now we are done */
3545 aopPut(AOP(result),"b",0);
3549 /*-----------------------------------------------------------------*/
3550 /* genMod - generates code for division */
3551 /*-----------------------------------------------------------------*/
3552 static void genMod (iCode *ic)
3554 operand *left = IC_LEFT(ic);
3555 operand *right = IC_RIGHT(ic);
3556 operand *result= IC_RESULT(ic);
3559 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3560 /* assign the amsops */
3561 aopOp (left,ic,FALSE);
3562 aopOp (right,ic,FALSE);
3563 aopOp (result,ic,TRUE);
3565 /* special cases first */
3567 if (AOP_TYPE(left) == AOP_CRY &&
3568 AOP_TYPE(right)== AOP_CRY) {
3569 genModbits(left,right,result);
3573 /* if both are of size == 1 */
3574 if (AOP_SIZE(left) == 1 &&
3575 AOP_SIZE(right) == 1 ) {
3576 genModOneByte(left,right,result);
3580 /* should have been converted to function call */
3584 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3585 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3586 freeAsmop(result,NULL,ic,TRUE);
3589 /*-----------------------------------------------------------------*/
3590 /* genIfxJump :- will create a jump depending on the ifx */
3591 /*-----------------------------------------------------------------*/
3593 note: May need to add parameter to indicate when a variable is in bit space.
3595 static void genIfxJump (iCode *ic, char *jval)
3599 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3600 /* if true label then we jump if condition
3602 if ( IC_TRUE(ic) ) {
3604 if(strcmp(jval,"a") == 0)
3606 else if (strcmp(jval,"c") == 0)
3609 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3610 emitpcode(POC_BTFSC, newpCodeOpBit(jval,-1,1));
3613 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3614 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3618 /* false label is present */
3619 if(strcmp(jval,"a") == 0)
3621 else if (strcmp(jval,"c") == 0)
3624 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3625 emitpcode(POC_BTFSS, newpCodeOpBit(jval,-1,1));
3628 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3629 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3634 /* mark the icode as generated */
3638 /*-----------------------------------------------------------------*/
3640 /*-----------------------------------------------------------------*/
3641 static void genSkip(iCode *ifx,int status_bit)
3647 if ( IC_TRUE(ifx) ) {
3648 switch(status_bit) {
3663 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3664 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3668 switch(status_bit) {
3682 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3683 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3689 /*-----------------------------------------------------------------*/
3691 /*-----------------------------------------------------------------*/
3692 static void genSkipc(resolvedIfx *rifx)
3703 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3704 rifx->generated = 1;
3707 /*-----------------------------------------------------------------*/
3709 /*-----------------------------------------------------------------*/
3710 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3716 if( (rifx->condition ^ invert_condition) & 1)
3721 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3722 rifx->generated = 1;
3725 /*-----------------------------------------------------------------*/
3727 /*-----------------------------------------------------------------*/
3728 static void genSkipz(iCode *ifx, int condition)
3740 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3742 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3745 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3747 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3750 /*-----------------------------------------------------------------*/
3752 /*-----------------------------------------------------------------*/
3753 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3760 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3762 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3765 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3766 rifx->generated = 1;
3770 /*-----------------------------------------------------------------*/
3771 /* genChkZeroes :- greater or less than comparison */
3772 /* For each byte in a literal that is zero, inclusive or the */
3773 /* the corresponding byte in the operand with W */
3774 /* returns true if any of the bytes are zero */
3775 /*-----------------------------------------------------------------*/
3776 static int genChkZeroes(operand *op, int lit, int size)
3783 i = (lit >> (size*8)) & 0xff;
3787 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3789 emitpcode(POC_IORFW, popGet(AOP(op),size));
3798 /*-----------------------------------------------------------------*/
3799 /* genCmp :- greater or less than comparison */
3800 /*-----------------------------------------------------------------*/
3801 static void genCmp (operand *left,operand *right,
3802 operand *result, iCode *ifx, int sign)
3804 int size; //, offset = 0 ;
3805 unsigned long lit = 0L,i = 0;
3806 resolvedIfx rFalseIfx;
3807 // resolvedIfx rTrueIfx;
3811 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3814 DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
3815 DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
3819 resolveIfx(&rFalseIfx,ifx);
3820 truelbl = newiTempLabel(NULL);
3821 size = max(AOP_SIZE(left),AOP_SIZE(right));
3823 DEBUGpic14_AopType(__LINE__,left,right,result);
3827 /* if literal is on the right then swap with left */
3828 if ((AOP_TYPE(right) == AOP_LIT)) {
3829 operand *tmp = right ;
3830 unsigned long mask = (0x100 << (8*(size-1))) - 1;
3831 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3834 lit = (lit - 1) & mask;
3837 rFalseIfx.condition ^= 1;
3840 } else if ((AOP_TYPE(left) == AOP_LIT)) {
3841 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3845 //if(IC_TRUE(ifx) == NULL)
3846 /* if left & right are bit variables */
3847 if (AOP_TYPE(left) == AOP_CRY &&
3848 AOP_TYPE(right) == AOP_CRY ) {
3849 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3850 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3852 /* subtract right from left if at the
3853 end the carry flag is set then we know that
3854 left is greater than right */
3856 symbol *lbl = newiTempLabel(NULL);
3859 if(AOP_TYPE(right) == AOP_LIT) {
3861 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3863 DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
3870 genSkipCond(&rFalseIfx,left,size-1,7);
3872 /* no need to compare to 0...*/
3873 /* NOTE: this is a de-generate compare that most certainly
3874 * creates some dead code. */
3875 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3877 if(ifx) ifx->generated = 1;
3884 //i = (lit >> (size*8)) & 0xff;
3885 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3887 emitpcode(POC_MOVFW, popGet(AOP(left),size));
3889 i = ((0-lit) & 0xff);
3892 /* lit is 0x7f, all signed chars are less than
3893 * this except for 0x7f itself */
3894 emitpcode(POC_XORLW, popGetLit(0x7f));
3895 genSkipz2(&rFalseIfx,0);
3897 emitpcode(POC_ADDLW, popGetLit(0x80));
3898 emitpcode(POC_ADDLW, popGetLit(i^0x80));
3899 genSkipc(&rFalseIfx);
3904 genSkipz2(&rFalseIfx,1);
3906 emitpcode(POC_ADDLW, popGetLit(i));
3907 genSkipc(&rFalseIfx);
3911 if(ifx) ifx->generated = 1;
3915 /* chars are out of the way. now do ints and longs */
3918 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3925 genSkipCond(&rFalseIfx,left,size,7);
3926 if(ifx) ifx->generated = 1;
3931 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3933 //rFalseIfx.condition ^= 1;
3934 //genSkipCond(&rFalseIfx,left,size,7);
3935 //rFalseIfx.condition ^= 1;
3937 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3938 if(rFalseIfx.condition)
3939 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
3941 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
3943 emitpcode(POC_MOVLW, popGetLit(0x100-lit));
3944 emitpcode(POC_ADDFW, popGet(AOP(left),0));
3945 emitpcode(POC_MOVFW, popGet(AOP(left),1));
3948 emitpcode(POC_IORFW, popGet(AOP(left),size--));
3950 if(rFalseIfx.condition) {
3952 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
3958 genSkipc(&rFalseIfx);
3959 emitpLabel(truelbl->key);
3960 if(ifx) ifx->generated = 1;
3967 if( (lit & 0xff) == 0) {
3968 /* lower byte is zero */
3969 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3970 i = ((lit >> 8) & 0xff) ^0x80;
3971 emitpcode(POC_MOVFW, popGet(AOP(left),size));
3972 emitpcode(POC_ADDLW, popGetLit( 0x80));
3973 emitpcode(POC_ADDLW, popGetLit(0x100-i));
3974 genSkipc(&rFalseIfx);
3977 if(ifx) ifx->generated = 1;
3982 /* Special cases for signed longs */
3983 if( (lit & 0xffffff) == 0) {
3984 /* lower byte is zero */
3985 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3986 i = ((lit >> 8*3) & 0xff) ^0x80;
3987 emitpcode(POC_MOVFW, popGet(AOP(left),size));
3988 emitpcode(POC_ADDLW, popGetLit( 0x80));
3989 emitpcode(POC_ADDLW, popGetLit(0x100-i));
3990 genSkipc(&rFalseIfx);
3993 if(ifx) ifx->generated = 1;
4001 if(lit & (0x80 << (size*8))) {
4002 /* lit is negative */
4003 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4005 //genSkipCond(&rFalseIfx,left,size,7);
4007 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4009 if(rFalseIfx.condition)
4010 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4012 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4016 /* lit is positive */
4017 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4018 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4019 if(rFalseIfx.condition)
4020 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4022 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4026 /* There are no more special cases, so perform a general compare */
4028 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4029 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4033 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4035 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4037 //rFalseIfx.condition ^= 1;
4038 genSkipc(&rFalseIfx);
4040 emitpLabel(truelbl->key);
4042 if(ifx) ifx->generated = 1;
4049 /* sign is out of the way. So now do an unsigned compare */
4050 DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4053 /* General case - compare to an unsigned literal on the right.*/
4055 i = (lit >> (size*8)) & 0xff;
4056 emitpcode(POC_MOVLW, popGetLit(i));
4057 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4059 i = (lit >> (size*8)) & 0xff;
4062 emitpcode(POC_MOVLW, popGetLit(i));
4064 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4066 /* this byte of the lit is zero,
4067 *if it's not the last then OR in the variable */
4069 emitpcode(POC_IORFW, popGet(AOP(left),size));
4074 emitpLabel(lbl->key);
4075 //if(emitFinalCheck)
4076 genSkipc(&rFalseIfx);
4078 emitpLabel(truelbl->key);
4080 if(ifx) ifx->generated = 1;
4087 if(AOP_TYPE(left) == AOP_LIT) {
4088 //symbol *lbl = newiTempLabel(NULL);
4090 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4093 DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4096 if((lit == 0) && (sign == 0)){
4099 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4101 emitpcode(POC_IORFW, popGet(AOP(right),--size));
4103 genSkipz2(&rFalseIfx,0);
4104 if(ifx) ifx->generated = 1;
4111 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4112 /* degenerate compare can never be true */
4113 if(rFalseIfx.condition == 0)
4114 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4116 if(ifx) ifx->generated = 1;
4121 /* signed comparisons to a literal byte */
4123 int lp1 = (lit+1) & 0xff;
4125 DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4128 rFalseIfx.condition ^= 1;
4129 genSkipCond(&rFalseIfx,right,0,7);
4132 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4133 emitpcode(POC_XORLW, popGetLit(0x7f));
4134 genSkipz2(&rFalseIfx,1);
4137 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4138 emitpcode(POC_ADDLW, popGetLit(0x80));
4139 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4140 rFalseIfx.condition ^= 1;
4141 genSkipc(&rFalseIfx);
4144 if(ifx) ifx->generated = 1;
4146 /* unsigned comparisons to a literal byte */
4148 switch(lit & 0xff ) {
4150 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4151 genSkipz2(&rFalseIfx,0);
4152 if(ifx) ifx->generated = 1;
4155 genSkipCond(&rFalseIfx,right,0,7);
4156 if(ifx) ifx->generated = 1;
4160 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4161 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4162 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4163 rFalseIfx.condition ^= 1;
4164 if (AOP_TYPE(result) == AOP_CRY) {
4165 genSkipc(&rFalseIfx);
4166 if(ifx) ifx->generated = 1;
4168 DEBUGpic14_emitcode ("; ***","%s %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4169 emitpcode(POC_CLRF, popGet(AOP(result),0));
4170 emitpcode(POC_RLF, popGet(AOP(result),0));
4171 emitpcode(POC_MOVLW, popGetLit(0x01));
4172 emitpcode(POC_XORWF, popGet(AOP(result),0));
4183 /* Size is greater than 1 */
4191 /* this means lit = 0xffffffff, or -1 */
4194 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4195 rFalseIfx.condition ^= 1;
4196 genSkipCond(&rFalseIfx,right,size,7);
4197 if(ifx) ifx->generated = 1;
4204 if(rFalseIfx.condition) {
4205 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4206 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4209 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4211 emitpcode(POC_IORFW, popGet(AOP(right),size));
4215 if(rFalseIfx.condition) {
4216 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4217 emitpLabel(truelbl->key);
4219 rFalseIfx.condition ^= 1;
4220 genSkipCond(&rFalseIfx,right,s,7);
4223 if(ifx) ifx->generated = 1;
4227 if((size == 1) && (0 == (lp1&0xff))) {
4228 /* lower byte of signed word is zero */
4229 DEBUGpic14_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
4230 i = ((lp1 >> 8) & 0xff) ^0x80;
4231 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4232 emitpcode(POC_ADDLW, popGetLit( 0x80));
4233 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4234 rFalseIfx.condition ^= 1;
4235 genSkipc(&rFalseIfx);
4238 if(ifx) ifx->generated = 1;
4242 if(lit & (0x80 << (size*8))) {
4243 /* Lit is less than zero */
4244 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
4245 //rFalseIfx.condition ^= 1;
4246 //genSkipCond(&rFalseIfx,left,size,7);
4247 //rFalseIfx.condition ^= 1;
4248 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4249 //emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4251 if(rFalseIfx.condition)
4252 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4254 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4258 /* Lit is greater than or equal to zero */
4259 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
4260 //rFalseIfx.condition ^= 1;
4261 //genSkipCond(&rFalseIfx,right,size,7);
4262 //rFalseIfx.condition ^= 1;
4264 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4265 //emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4267 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4268 if(rFalseIfx.condition)
4269 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4271 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4276 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4277 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4281 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4283 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4285 rFalseIfx.condition ^= 1;
4286 //rFalseIfx.condition = 1;
4287 genSkipc(&rFalseIfx);
4289 emitpLabel(truelbl->key);
4291 if(ifx) ifx->generated = 1;
4296 /* compare word or long to an unsigned literal on the right.*/
4301 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4304 break; /* handled above */
4307 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4309 emitpcode(POC_IORFW, popGet(AOP(right),size));
4310 genSkipz2(&rFalseIfx,0);
4314 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4316 emitpcode(POC_IORFW, popGet(AOP(right),size));
4319 if(rFalseIfx.condition)
4320 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4322 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4325 emitpcode(POC_MOVLW, popGetLit(lit+1));
4326 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4328 rFalseIfx.condition ^= 1;
4329 genSkipc(&rFalseIfx);
4332 emitpLabel(truelbl->key);
4334 if(ifx) ifx->generated = 1;
4340 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4341 i = (lit >> (size*8)) & 0xff;
4343 emitpcode(POC_MOVLW, popGetLit(i));
4344 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4347 i = (lit >> (size*8)) & 0xff;
4350 emitpcode(POC_MOVLW, popGetLit(i));
4352 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4354 /* this byte of the lit is zero,
4355 *if it's not the last then OR in the variable */
4357 emitpcode(POC_IORFW, popGet(AOP(right),size));
4362 emitpLabel(lbl->key);
4364 rFalseIfx.condition ^= 1;
4365 genSkipc(&rFalseIfx);
4369 emitpLabel(truelbl->key);
4370 if(ifx) ifx->generated = 1;
4374 /* Compare two variables */
4376 DEBUGpic14_emitcode(";sign","%d",sign);
4380 /* Sigh. thus sucks... */
4382 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4383 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4384 emitpcode(POC_MOVLW, popGetLit(0x80));
4385 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4386 emitpcode(POC_XORFW, popGet(AOP(right),size));
4387 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4389 /* Signed char comparison */
4390 /* Special thanks to Nikolai Golovchenko for this snippet */
4391 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4392 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4393 emitpcode(POC_RRFW, popGet(AOP(left),0)); /* could be any register */
4394 emitpcode(POC_XORFW, popGet(AOP(left),0));
4395 emitpcode(POC_XORFW, popGet(AOP(right),0));
4396 emitpcode(POC_ADDLW, popGetLit(0x80));
4398 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4399 genSkipc(&rFalseIfx);
4401 if(ifx) ifx->generated = 1;
4407 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4408 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4412 /* The rest of the bytes of a multi-byte compare */
4416 emitpcode(POC_GOTO, popGetLabel(lbl->key));
4419 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4420 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4425 emitpLabel(lbl->key);
4427 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4428 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
4429 (AOP_TYPE(result) == AOP_REG)) {
4430 emitpcode(POC_CLRF, popGet(AOP(result),0));
4431 emitpcode(POC_RLF, popGet(AOP(result),0));
4433 genSkipc(&rFalseIfx);
4435 //genSkipc(&rFalseIfx);
4436 if(ifx) ifx->generated = 1;
4443 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4444 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4445 pic14_outBitC(result);
4447 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4448 /* if the result is used in the next
4449 ifx conditional branch then generate
4450 code a little differently */
4452 genIfxJump (ifx,"c");
4454 pic14_outBitC(result);
4455 /* leave the result in acc */
4460 /*-----------------------------------------------------------------*/
4461 /* genCmpGt :- greater than comparison */
4462 /*-----------------------------------------------------------------*/
4463 static void genCmpGt (iCode *ic, iCode *ifx)
4465 operand *left, *right, *result;
4466 sym_link *letype , *retype;
4470 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4472 right= IC_RIGHT(ic);
4473 result = IC_RESULT(ic);
4475 letype = getSpec(operandType(left));
4476 retype =getSpec(operandType(right));
4477 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4478 /* assign the amsops */
4479 aopOp (left,ic,FALSE);
4480 aopOp (right,ic,FALSE);
4481 aopOp (result,ic,TRUE);
4483 genCmp(right, left, result, ifx, sign);
4485 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4486 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4487 freeAsmop(result,NULL,ic,TRUE);
4490 /*-----------------------------------------------------------------*/
4491 /* genCmpLt - less than comparisons */
4492 /*-----------------------------------------------------------------*/
4493 static void genCmpLt (iCode *ic, iCode *ifx)
4495 operand *left, *right, *result;
4496 sym_link *letype , *retype;
4500 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4502 right= IC_RIGHT(ic);
4503 result = IC_RESULT(ic);
4505 letype = getSpec(operandType(left));
4506 retype =getSpec(operandType(right));
4507 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4509 /* assign the amsops */
4510 aopOp (left,ic,FALSE);
4511 aopOp (right,ic,FALSE);
4512 aopOp (result,ic,TRUE);
4514 genCmp(left, right, result, ifx, sign);
4516 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4517 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4518 freeAsmop(result,NULL,ic,TRUE);
4521 /*-----------------------------------------------------------------*/
4522 /* genc16bit2lit - compare a 16 bit value to a literal */
4523 /*-----------------------------------------------------------------*/
4524 static void genc16bit2lit(operand *op, int lit, int offset)
4529 DEBUGpic14_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
4530 if( (lit&0xff) == 0)
4535 switch( BYTEofLONG(lit,i)) {
4537 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4540 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4543 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4546 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4547 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4552 switch( BYTEofLONG(lit,i)) {
4554 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4558 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4562 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4565 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4567 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4573 /*-----------------------------------------------------------------*/
4574 /* gencjneshort - compare and jump if not equal */
4575 /*-----------------------------------------------------------------*/
4576 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4578 int size = max(AOP_SIZE(left),AOP_SIZE(right));
4580 int res_offset = 0; /* the result may be a different size then left or right */
4581 int res_size = AOP_SIZE(result);
4585 unsigned long lit = 0L;
4587 if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4588 emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4591 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4592 DEBUGpic14_AopType(__LINE__,left,right,result);
4594 DEBUGpic14_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
4595 resolveIfx(&rIfx,ifx);
4596 lbl = newiTempLabel(NULL);
4599 /* if the left side is a literal or
4600 if the right is in a pointer register and left
4602 if ((AOP_TYPE(left) == AOP_LIT) ||
4603 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4608 if(AOP_TYPE(right) == AOP_LIT)
4609 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4611 /* if the right side is a literal then anything goes */
4612 if (AOP_TYPE(right) == AOP_LIT &&
4613 AOP_TYPE(left) != AOP_DIR ) {
4616 genc16bit2lit(left, lit, 0);
4618 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4623 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4624 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4626 emitpcode(POC_MOVF,popGet(AOP(left),offset));
4630 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4632 if(res_offset < res_size-1)
4640 /* if the right side is in a register or in direct space or
4641 if the left is a pointer register & right is not */
4642 else if (AOP_TYPE(right) == AOP_REG ||
4643 AOP_TYPE(right) == AOP_DIR ||
4644 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4645 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4646 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4647 int lbl_key = lbl->key;
4650 if (AOP_TYPE(result) != AOP_CRY)
4651 emitpcode(POC_CLRF,popGet(AOP(result),res_offset));
4652 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4654 DEBUGpic14_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
4655 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
4656 __FUNCTION__,__LINE__);
4660 /* switch(size) { */
4662 /* genc16bit2lit(left, lit, 0); */
4664 /* emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
4669 if((AOP_TYPE(left) == AOP_DIR) &&
4670 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4672 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4673 emitpcode(POC_XORFW,popGet(AOP(right),offset));
4675 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4677 switch (lit & 0xff) {
4679 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4682 emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4683 emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4684 //emitpcode(POC_GOTO,popGetLabel(lbl->key));
4688 emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4689 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4690 //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4691 emitpcode(POC_GOTO,popGetLabel(lbl_key));
4695 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4696 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4701 emitpcode(POC_MOVF,popGet(AOP(left),offset));
4704 if(AOP_TYPE(result) == AOP_CRY) {
4705 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
4710 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4712 /* fix me. probably need to check result size too */
4713 //emitpcode(POC_CLRF,popGet(AOP(result),0));
4718 emitpcode(POC_GOTO,popGetLabel(lbl_key));
4719 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4726 if(res_offset < res_size-1)
4731 } else if(AOP_TYPE(right) == AOP_REG &&
4732 AOP_TYPE(left) != AOP_DIR){
4735 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4736 emitpcode(POC_XORFW,popGet(AOP(right),offset));
4737 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
4742 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4744 if(res_offset < res_size-1)
4749 /* right is a pointer reg need both a & b */
4751 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4753 pic14_emitcode("mov","b,%s",l);
4754 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4755 pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
4760 emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4762 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4764 emitpLabel(lbl->key);
4766 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4773 /*-----------------------------------------------------------------*/
4774 /* gencjne - compare and jump if not equal */
4775 /*-----------------------------------------------------------------*/
4776 static void gencjne(operand *left, operand *right, iCode *ifx)
4778 symbol *tlbl = newiTempLabel(NULL);
4780 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4781 gencjneshort(left, right, lbl);
4783 pic14_emitcode("mov","a,%s",one);
4784 pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
4785 pic14_emitcode("","%05d_DS_:",lbl->key+100);
4786 pic14_emitcode("clr","a");
4787 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4789 emitpLabel(lbl->key);
4790 emitpLabel(tlbl->key);
4795 /*-----------------------------------------------------------------*/
4796 /* genCmpEq - generates code for equal to */
4797 /*-----------------------------------------------------------------*/
4798 static void genCmpEq (iCode *ic, iCode *ifx)
4800 operand *left, *right, *result;
4801 unsigned long lit = 0L;
4805 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4808 DEBUGpic14_emitcode ("; ifx is non-null","");
4810 DEBUGpic14_emitcode ("; ifx is null","");
4812 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4813 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4814 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4816 size = max(AOP_SIZE(left),AOP_SIZE(right));
4818 DEBUGpic14_AopType(__LINE__,left,right,result);
4820 /* if literal, literal on the right or
4821 if the right is in a pointer register and left
4823 if (aop_isLitLike (AOP(IC_LEFT(ic)))
4824 || (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4825 operand *tmp = right ;
4831 if(ifx && !AOP_SIZE(result)){
4833 /* if they are both bit variables */
4834 if (AOP_TYPE(left) == AOP_CRY &&
4835 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4836 if(AOP_TYPE(right) == AOP_LIT){
4837 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4839 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4840 pic14_emitcode("cpl","c");
4841 } else if(lit == 1L) {
4842 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4844 pic14_emitcode("clr","c");
4846 /* AOP_TYPE(right) == AOP_CRY */
4848 symbol *lbl = newiTempLabel(NULL);
4849 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4850 pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4851 pic14_emitcode("cpl","c");
4852 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4854 /* if true label then we jump if condition
4856 tlbl = newiTempLabel(NULL);
4857 if ( IC_TRUE(ifx) ) {
4858 pic14_emitcode("jnc","%05d_DS_",tlbl->key+100);
4859 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4861 pic14_emitcode("jc","%05d_DS_",tlbl->key+100);
4862 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4864 pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4867 /* left and right are both bit variables, result is carry */
4870 resolveIfx(&rIfx,ifx);
4872 emitpcode(POC_MOVLW,popGet(AOP(left),0));
4873 emitpcode(POC_ANDFW,popGet(AOP(left),0));
4874 emitpcode(POC_BTFSC,popGet(AOP(right),0));
4875 emitpcode(POC_ANDLW,popGet(AOP(left),0));
4880 /* They're not both bit variables. Is the right a literal? */
4881 if(AOP_TYPE(right) == AOP_LIT) {
4882 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4887 switch(lit & 0xff) {
4889 if ( IC_TRUE(ifx) ) {
4890 emitpcode(POC_DECFW,popGet(AOP(left),offset));
4892 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4894 emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4895 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4899 if ( IC_TRUE(ifx) ) {
4900 emitpcode(POC_INCFW,popGet(AOP(left),offset));
4902 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4904 emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4905 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4909 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4911 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4916 /* end of size == 1 */
4920 genc16bit2lit(left,lit,offset);
4923 /* end of size == 2 */
4928 emitpcode(POC_MOVFW,popGet(AOP(left),0));
4929 emitpcode(POC_IORFW,popGet(AOP(left),1));
4930 emitpcode(POC_IORFW,popGet(AOP(left),2));
4931 emitpcode(POC_IORFW,popGet(AOP(left),3));
4935 /* search for patterns that can be optimized */
4937 genc16bit2lit(left,lit,0);
4940 genSkipz(ifx,IC_TRUE(ifx) == NULL);
4942 genc16bit2lit(left,lit,2);
4944 emitpcode(POC_IORFW,popGet(AOP(left),2));
4945 emitpcode(POC_IORFW,popGet(AOP(left),3));
4958 } else if(AOP_TYPE(right) == AOP_CRY ) {
4959 /* we know the left is not a bit, but that the right is */
4960 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4961 emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4962 popGet(AOP(right),offset));
4963 emitpcode(POC_XORLW,popGetLit(1));
4965 /* if the two are equal, then W will be 0 and the Z bit is set
4966 * we could test Z now, or go ahead and check the high order bytes if
4967 * the variable we're comparing is larger than a byte. */
4970 emitpcode(POC_IORFW,popGet(AOP(left),offset));
4972 if ( IC_TRUE(ifx) ) {
4974 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4975 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4978 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4979 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4983 /* They're both variables that are larger than bits */
4986 tlbl = newiTempLabel(NULL);
4989 mov2w (AOP(right),offset); /* right might be litLike() */
4990 emitpcode(POC_XORFW,popGet(AOP(left),offset));
4992 if ( IC_TRUE(ifx) ) {
4995 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
4996 pic14_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4999 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5000 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5004 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
5005 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5009 if(s>1 && IC_TRUE(ifx)) {
5010 emitpLabel(tlbl->key);
5011 pic14_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);
5015 /* mark the icode as generated */
5020 /* if they are both bit variables */
5021 if (AOP_TYPE(left) == AOP_CRY &&
5022 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5023 if(AOP_TYPE(right) == AOP_LIT){
5024 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5026 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5027 pic14_emitcode("cpl","c");
5028 } else if(lit == 1L) {
5029 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5031 pic14_emitcode("clr","c");
5033 /* AOP_TYPE(right) == AOP_CRY */
5035 symbol *lbl = newiTempLabel(NULL);
5036 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5037 pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5038 pic14_emitcode("cpl","c");
5039 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
5042 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5043 pic14_outBitC(result);
5047 genIfxJump (ifx,"c");
5050 /* if the result is used in an arithmetic operation
5051 then put the result in place */
5052 pic14_outBitC(result);
5055 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5056 gencjne(left,right,result,ifx);
5059 gencjne(left,right,newiTempLabel(NULL));
5061 if(IC_TRUE(ifx)->key)
5062 gencjne(left,right,IC_TRUE(ifx)->key);
5064 gencjne(left,right,IC_FALSE(ifx)->key);
5068 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5069 aopPut(AOP(result),"a",0);
5074 genIfxJump (ifx,"a");
5078 /* if the result is used in an arithmetic operation
5079 then put the result in place */
5081 if (AOP_TYPE(result) != AOP_CRY)
5082 pic14_outAcc(result);
5084 /* leave the result in acc */
5088 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5089 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5090 freeAsmop(result,NULL,ic,TRUE);
5093 /*-----------------------------------------------------------------*/
5094 /* ifxForOp - returns the icode containing the ifx for operand */
5095 /*-----------------------------------------------------------------*/
5096 static iCode *ifxForOp ( operand *op, iCode *ic )
5099 /* if true symbol then needs to be assigned */
5100 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5101 if (IS_TRUE_SYMOP(op))
5104 /* if this has register type condition and
5105 the next instruction is ifx with the same operand
5106 and live to of the operand is upto the ifx only then */
5108 ic->next->op == IFX &&
5109 IC_COND(ic->next)->key == op->key &&
5110 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5114 ic->next->op == IFX &&
5115 IC_COND(ic->next)->key == op->key) {
5116 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5120 DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5122 ic->next->op == IFX)
5123 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5126 ic->next->op == IFX &&
5127 IC_COND(ic->next)->key == op->key) {
5128 DEBUGpic14_emitcode ("; "," key is okay");
5129 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5130 OP_SYMBOL(op)->liveTo,
5137 /*-----------------------------------------------------------------*/
5138 /* genAndOp - for && operation */
5139 /*-----------------------------------------------------------------*/
5140 static void genAndOp (iCode *ic)
5142 operand *left,*right, *result;
5146 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5147 /* note here that && operations that are in an
5148 if statement are taken away by backPatchLabels
5149 only those used in arthmetic operations remain */
5150 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5151 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5152 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5154 DEBUGpic14_AopType(__LINE__,left,right,result);
5156 emitpcode(POC_MOVFW,popGet(AOP(left),0));
5157 emitpcode(POC_ANDFW,popGet(AOP(right),0));
5158 emitpcode(POC_MOVWF,popGet(AOP(result),0));
5160 /* if both are bit variables */
5161 /* if (AOP_TYPE(left) == AOP_CRY && */
5162 /* AOP_TYPE(right) == AOP_CRY ) { */
5163 /* pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5164 /* pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5165 /* pic14_outBitC(result); */
5167 /* tlbl = newiTempLabel(NULL); */
5168 /* pic14_toBoolean(left); */
5169 /* pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5170 /* pic14_toBoolean(right); */
5171 /* pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5172 /* pic14_outBitAcc(result); */
5175 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5176 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5177 freeAsmop(result,NULL,ic,TRUE);
5181 /*-----------------------------------------------------------------*/
5182 /* genOrOp - for || operation */
5183 /*-----------------------------------------------------------------*/
5186 modified this code, but it doesn't appear to ever get called
5189 static void genOrOp (iCode *ic)
5191 operand *left,*right, *result;
5194 /* note here that || operations that are in an
5195 if statement are taken away by backPatchLabels
5196 only those used in arthmetic operations remain */
5198 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5199 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5200 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5201 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5203 DEBUGpic14_AopType(__LINE__,left,right,result);
5205 /* if both are bit variables */
5206 if (AOP_TYPE(left) == AOP_CRY &&
5207 AOP_TYPE(right) == AOP_CRY ) {
5208 pic14_emitcode("clrc","");
5209 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5210 AOP(left)->aopu.aop_dir,
5211 AOP(left)->aopu.aop_dir);
5212 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5213 AOP(right)->aopu.aop_dir,
5214 AOP(right)->aopu.aop_dir);
5215 pic14_emitcode("setc","");
5218 tlbl = newiTempLabel(NULL);
5219 pic14_toBoolean(left);
5221 pic14_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5222 pic14_toBoolean(right);
5223 pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5225 pic14_outBitAcc(result);
5228 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5229 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5230 freeAsmop(result,NULL,ic,TRUE);
5233 /*-----------------------------------------------------------------*/
5234 /* isLiteralBit - test if lit == 2^n */
5235 /*-----------------------------------------------------------------*/
5236 static int isLiteralBit(unsigned long lit)
5238 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5239 0x100L,0x200L,0x400L,0x800L,
5240 0x1000L,0x2000L,0x4000L,0x8000L,
5241 0x10000L,0x20000L,0x40000L,0x80000L,
5242 0x100000L,0x200000L,0x400000L,0x800000L,
5243 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5244 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5248 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5249 for(idx = 0; idx < 32; idx++)
5255 /*-----------------------------------------------------------------*/
5256 /* continueIfTrue - */
5257 /*-----------------------------------------------------------------*/
5258 static void continueIfTrue (iCode *ic)
5261 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5263 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5267 /*-----------------------------------------------------------------*/
5269 /*-----------------------------------------------------------------*/
5270 static void jumpIfTrue (iCode *ic)
5273 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5275 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5279 /*-----------------------------------------------------------------*/
5280 /* jmpTrueOrFalse - */
5281 /*-----------------------------------------------------------------*/
5282 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5285 // ugly but optimized by peephole
5286 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5288 symbol *nlbl = newiTempLabel(NULL);
5289 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5290 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5291 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5292 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5295 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5296 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5301 /*-----------------------------------------------------------------*/
5302 /* genAnd - code for and */
5303 /*-----------------------------------------------------------------*/
5304 static void genAnd (iCode *ic, iCode *ifx)
5306 operand *left, *right, *result;
5308 unsigned long lit = 0L;
5313 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5314 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5315 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5316 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5318 resolveIfx(&rIfx,ifx);
5320 /* if left is a literal & right is not then exchange them */
5321 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5322 AOP_NEEDSACC(left)) {
5323 operand *tmp = right ;
5328 /* if result = right then exchange them */
5329 if(pic14_sameRegs(AOP(result),AOP(right))){
5330 operand *tmp = right ;
5335 /* if right is bit then exchange them */
5336 if (AOP_TYPE(right) == AOP_CRY &&
5337 AOP_TYPE(left) != AOP_CRY){
5338 operand *tmp = right ;
5342 if(AOP_TYPE(right) == AOP_LIT)
5343 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5345 size = AOP_SIZE(result);
5347 DEBUGpic14_AopType(__LINE__,left,right,result);
5350 // result = bit & yy;
5351 if (AOP_TYPE(left) == AOP_CRY){
5352 // c = bit & literal;
5353 if(AOP_TYPE(right) == AOP_LIT){
5355 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5358 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5361 if(size && (AOP_TYPE(result) == AOP_CRY)){
5362 pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5365 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5369 pic14_emitcode("clr","c");
5372 if (AOP_TYPE(right) == AOP_CRY){
5374 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5375 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5378 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5380 pic14_emitcode("rrc","a");
5381 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5387 pic14_outBitC(result);
5389 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5390 genIfxJump(ifx, "c");
5394 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5395 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5396 if((AOP_TYPE(right) == AOP_LIT) &&
5397 (AOP_TYPE(result) == AOP_CRY) &&
5398 (AOP_TYPE(left) != AOP_CRY)){
5399 int posbit = isLiteralBit(lit);
5403 //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5406 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5411 while (posbit > 7) {
5415 emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5416 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5417 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5424 symbol *tlbl = newiTempLabel(NULL);
5425 int sizel = AOP_SIZE(left);
5427 pic14_emitcode("setb","c");
5429 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5430 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5432 if((posbit = isLiteralBit(bytelit)) != 0)
5433 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5435 if(bytelit != 0x0FFL)
5436 pic14_emitcode("anl","a,%s",
5437 aopGet(AOP(right),offset,FALSE,TRUE));
5438 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5443 // bit = left & literal
5445 pic14_emitcode("clr","c");
5446 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5448 // if(left & literal)
5451 jmpTrueOrFalse(ifx, tlbl);
5455 pic14_outBitC(result);
5459 /* if left is same as result */
5460 if(pic14_sameRegs(AOP(result),AOP(left))){
5462 for(;size--; offset++,lit>>=8) {
5463 if(AOP_TYPE(right) == AOP_LIT){
5464 switch(lit & 0xff) {
5466 /* and'ing with 0 has clears the result */
5467 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5470 /* and'ing with 0xff is a nop when the result and left are the same */
5475 int p = my_powof2( (~lit) & 0xff );
5477 /* only one bit is set in the literal, so use a bcf instruction */
5478 emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5481 if(know_W != (int)(lit&0xff))
5482 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5484 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5489 if (AOP_TYPE(left) == AOP_ACC) {
5490 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5492 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5493 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5500 // left & result in different registers
5501 if(AOP_TYPE(result) == AOP_CRY){
5503 // if(size), result in bit
5504 // if(!size && ifx), conditional oper: if(left & right)
5505 symbol *tlbl = newiTempLabel(NULL);
5506 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5508 pic14_emitcode("setb","c");
5510 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5511 pic14_emitcode("anl","a,%s",
5512 aopGet(AOP(left),offset,FALSE,FALSE));
5513 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5518 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5519 pic14_outBitC(result);
5521 jmpTrueOrFalse(ifx, tlbl);
5523 for(;(size--);offset++) {
5525 // result = left & right
5526 if(AOP_TYPE(right) == AOP_LIT){
5527 int t = (lit >> (offset*8)) & 0x0FFL;
5530 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5533 if(AOP_TYPE(left) != AOP_ACC) {
5534 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5536 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5539 if(AOP_TYPE(left) == AOP_ACC) {
5540 emitpcode(POC_ANDLW, popGetLit(t));
5542 emitpcode(POC_MOVLW, popGetLit(t));
5543 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5545 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5550 if (AOP_TYPE(left) == AOP_ACC) {
5551 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5553 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5554 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5556 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5562 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5563 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5564 freeAsmop(result,NULL,ic,TRUE);
5567 /*-----------------------------------------------------------------*/
5568 /* genOr - code for or */
5569 /*-----------------------------------------------------------------*/
5570 static void genOr (iCode *ic, iCode *ifx)
5572 operand *left, *right, *result;
5574 unsigned long lit = 0L;
5577 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5579 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5580 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5581 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5583 DEBUGpic14_AopType(__LINE__,left,right,result);
5585 /* if left is a literal & right is not then exchange them */
5586 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5587 AOP_NEEDSACC(left)) {
5588 operand *tmp = right ;
5593 /* if result = right then exchange them */
5594 if(pic14_sameRegs(AOP(result),AOP(right))){
5595 operand *tmp = right ;
5600 /* if right is bit then exchange them */
5601 if (AOP_TYPE(right) == AOP_CRY &&
5602 AOP_TYPE(left) != AOP_CRY){
5603 operand *tmp = right ;
5608 DEBUGpic14_AopType(__LINE__,left,right,result);
5610 if(AOP_TYPE(right) == AOP_LIT)
5611 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5613 size = AOP_SIZE(result);
5617 if (AOP_TYPE(left) == AOP_CRY){
5618 if(AOP_TYPE(right) == AOP_LIT){
5619 // c = bit & literal;
5621 // lit != 0 => result = 1
5622 if(AOP_TYPE(result) == AOP_CRY){
5624 emitpcode(POC_BSF, popGet(AOP(result),0));
5625 //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5626 // AOP(result)->aopu.aop_dir,
5627 // AOP(result)->aopu.aop_dir);
5629 continueIfTrue(ifx);
5633 // lit == 0 => result = left
5634 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5636 pic14_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5639 if (AOP_TYPE(right) == AOP_CRY){
5640 if(pic14_sameRegs(AOP(result),AOP(left))){
5642 emitpcode(POC_BCF, popGet(AOP(result),0));
5643 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5644 emitpcode(POC_BSF, popGet(AOP(result),0));
5646 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5647 AOP(result)->aopu.aop_dir,
5648 AOP(result)->aopu.aop_dir);
5649 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5650 AOP(right)->aopu.aop_dir,
5651 AOP(right)->aopu.aop_dir);
5652 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5653 AOP(result)->aopu.aop_dir,
5654 AOP(result)->aopu.aop_dir);
5656 if( AOP_TYPE(result) == AOP_ACC) {
5657 emitpcode(POC_MOVLW, popGetLit(0));
5658 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5659 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5660 emitpcode(POC_MOVLW, popGetLit(1));
5664 emitpcode(POC_BCF, popGet(AOP(result),0));
5665 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5666 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5667 emitpcode(POC_BSF, popGet(AOP(result),0));
5669 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5670 AOP(result)->aopu.aop_dir,
5671 AOP(result)->aopu.aop_dir);
5672 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5673 AOP(right)->aopu.aop_dir,
5674 AOP(right)->aopu.aop_dir);
5675 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5676 AOP(left)->aopu.aop_dir,
5677 AOP(left)->aopu.aop_dir);
5678 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5679 AOP(result)->aopu.aop_dir,
5680 AOP(result)->aopu.aop_dir);
5685 symbol *tlbl = newiTempLabel(NULL);
5686 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5689 emitpcode(POC_BCF, popGet(AOP(result),0));
5690 if( AOP_TYPE(right) == AOP_ACC) {
5691 emitpcode(POC_IORLW, popGetLit(0));
5693 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5694 emitpcode(POC_BSF, popGet(AOP(result),0));
5699 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5700 pic14_emitcode(";XXX setb","c");
5701 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5702 AOP(left)->aopu.aop_dir,tlbl->key+100);
5703 pic14_toBoolean(right);
5704 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5705 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5706 jmpTrueOrFalse(ifx, tlbl);
5710 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5717 pic14_outBitC(result);
5719 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5720 genIfxJump(ifx, "c");
5724 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5725 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5726 if((AOP_TYPE(right) == AOP_LIT) &&
5727 (AOP_TYPE(result) == AOP_CRY) &&
5728 (AOP_TYPE(left) != AOP_CRY)){
5730 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5733 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5735 continueIfTrue(ifx);
5738 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5739 // lit = 0, result = boolean(left)
5741 pic14_emitcode(";XXX setb","c");
5742 pic14_toBoolean(right);
5744 symbol *tlbl = newiTempLabel(NULL);
5745 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5747 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5749 genIfxJump (ifx,"a");
5753 pic14_outBitC(result);
5757 /* if left is same as result */
5758 if(pic14_sameRegs(AOP(result),AOP(left))){
5760 for(;size--; offset++,lit>>=8) {
5761 if(AOP_TYPE(right) == AOP_LIT){
5762 if((lit & 0xff) == 0)
5763 /* or'ing with 0 has no effect */
5766 int p = my_powof2(lit & 0xff);
5768 /* only one bit is set in the literal, so use a bsf instruction */
5770 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5772 if(know_W != (int)(lit & 0xff))
5773 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5774 know_W = lit & 0xff;
5775 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5780 if (AOP_TYPE(left) == AOP_ACC) {
5781 emitpcode(POC_IORFW, popGet(AOP(right),offset));
5782 pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5784 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
5785 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5787 pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5788 pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5794 // left & result in different registers
5795 if(AOP_TYPE(result) == AOP_CRY){
5797 // if(size), result in bit
5798 // if(!size && ifx), conditional oper: if(left | right)
5799 symbol *tlbl = newiTempLabel(NULL);
5800 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5801 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5805 pic14_emitcode(";XXX setb","c");
5807 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5808 pic14_emitcode(";XXX orl","a,%s",
5809 aopGet(AOP(left),offset,FALSE,FALSE));
5810 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5815 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5816 pic14_outBitC(result);
5818 jmpTrueOrFalse(ifx, tlbl);
5819 } else for(;(size--);offset++){
5821 // result = left | right
5822 if(AOP_TYPE(right) == AOP_LIT){
5823 int t = (lit >> (offset*8)) & 0x0FFL;
5826 if (AOP_TYPE(left) != AOP_ACC) {
5827 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
5829 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5833 if (AOP_TYPE(left) == AOP_ACC) {
5834 emitpcode(POC_IORLW, popGetLit(t));
5836 emitpcode(POC_MOVLW, popGetLit(t));
5837 emitpcode(POC_IORFW, popGet(AOP(left),offset));
5839 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5844 // faster than result <- left, anl result,right
5845 // and better if result is SFR
5846 if (AOP_TYPE(left) == AOP_ACC) {
5847 emitpcode(POC_IORFW,popGet(AOP(right),offset));
5849 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5850 emitpcode(POC_IORFW,popGet(AOP(left),offset));
5852 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5857 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5858 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5859 freeAsmop(result,NULL,ic,TRUE);
5862 /*-----------------------------------------------------------------*/
5863 /* genXor - code for xclusive or */
5864 /*-----------------------------------------------------------------*/
5865 static void genXor (iCode *ic, iCode *ifx)
5867 operand *left, *right, *result;
5869 unsigned long lit = 0L;
5872 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5874 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5875 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5876 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5878 /* if left is a literal & right is not ||
5879 if left needs acc & right does not */
5880 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5881 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5882 operand *tmp = right ;
5887 /* if result = right then exchange them */
5888 if(pic14_sameRegs(AOP(result),AOP(right))){
5889 operand *tmp = right ;
5894 /* if right is bit then exchange them */
5895 if (AOP_TYPE(right) == AOP_CRY &&
5896 AOP_TYPE(left) != AOP_CRY){
5897 operand *tmp = right ;
5901 if(AOP_TYPE(right) == AOP_LIT)
5902 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5904 size = AOP_SIZE(result);
5908 if (AOP_TYPE(left) == AOP_CRY){
5909 if(AOP_TYPE(right) == AOP_LIT){
5910 // c = bit & literal;
5912 // lit>>1 != 0 => result = 1
5913 if(AOP_TYPE(result) == AOP_CRY){
5915 {emitpcode(POC_BSF, popGet(AOP(result),offset));
5916 pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
5918 continueIfTrue(ifx);
5921 pic14_emitcode("setb","c");
5925 // lit == 0, result = left
5926 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5928 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5930 // lit == 1, result = not(left)
5931 if(size && pic14_sameRegs(AOP(result),AOP(left))){
5932 emitpcode(POC_MOVLW, popGet(AOP(result),offset));
5933 emitpcode(POC_XORWF, popGet(AOP(result),offset));
5934 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5937 assert ( !"incomplete genXor" );
5938 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5939 pic14_emitcode("cpl","c");
5946 symbol *tlbl = newiTempLabel(NULL);
5947 if (AOP_TYPE(right) == AOP_CRY){
5949 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5952 int sizer = AOP_SIZE(right);
5954 // if val>>1 != 0, result = 1
5955 pic14_emitcode("setb","c");
5957 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5959 // test the msb of the lsb
5960 pic14_emitcode("anl","a,#0xfe");
5961 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5965 pic14_emitcode("rrc","a");
5967 pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5968 pic14_emitcode("cpl","c");
5969 pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
5974 pic14_outBitC(result);
5976 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5977 genIfxJump(ifx, "c");
5981 if(pic14_sameRegs(AOP(result),AOP(left))){
5982 /* if left is same as result */
5983 for(;size--; offset++) {
5984 if(AOP_TYPE(right) == AOP_LIT){
5985 int t = (lit >> (offset*8)) & 0x0FFL;
5989 if (IS_AOP_PREG(left)) {
5990 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5991 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5992 aopPut(AOP(result),"a",offset);
5994 emitpcode(POC_MOVLW, popGetLit(t));
5995 emitpcode(POC_XORWF,popGet(AOP(left),offset));
5996 pic14_emitcode("xrl","%s,%s",
5997 aopGet(AOP(left),offset,FALSE,TRUE),
5998 aopGet(AOP(right),offset,FALSE,FALSE));
6001 if (AOP_TYPE(left) == AOP_ACC)
6002 pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6004 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6005 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6007 if (IS_AOP_PREG(left)) {
6008 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6009 aopPut(AOP(result),"a",offset);
6011 pic14_emitcode("xrl","%s,a",
6012 aopGet(AOP(left),offset,FALSE,TRUE));
6018 // left & result in different registers
6019 if(AOP_TYPE(result) == AOP_CRY){
6021 // if(size), result in bit
6022 // if(!size && ifx), conditional oper: if(left ^ right)
6023 symbol *tlbl = newiTempLabel(NULL);
6024 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6026 pic14_emitcode("setb","c");
6028 if((AOP_TYPE(right) == AOP_LIT) &&
6029 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6030 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6032 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6033 pic14_emitcode("xrl","a,%s",
6034 aopGet(AOP(left),offset,FALSE,FALSE));
6036 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6041 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6042 pic14_outBitC(result);
6044 jmpTrueOrFalse(ifx, tlbl);
6045 } else for(;(size--);offset++){
6047 // result = left & right
6048 if(AOP_TYPE(right) == AOP_LIT){
6049 int t = (lit >> (offset*8)) & 0x0FFL;
6052 if (AOP_TYPE(left) != AOP_ACC) {
6053 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6055 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6056 pic14_emitcode("movf","%s,w",
6057 aopGet(AOP(left),offset,FALSE,FALSE));
6058 pic14_emitcode("movwf","%s",
6059 aopGet(AOP(result),offset,FALSE,FALSE));
6062 if (AOP_TYPE(left) == AOP_ACC) {
6063 emitpcode(POC_XORLW, popGetLit(t));
6065 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6067 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6070 if (AOP_TYPE(left) == AOP_ACC) {
6071 emitpcode(POC_XORLW, popGetLit(t));
6073 emitpcode(POC_MOVLW, popGetLit(t));
6074 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6076 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6077 pic14_emitcode("movlw","0x%x",t);
6078 pic14_emitcode("xorwf","%s,w",
6079 aopGet(AOP(left),offset,FALSE,FALSE));
6080 pic14_emitcode("movwf","%s",
6081 aopGet(AOP(result),offset,FALSE,FALSE));
6087 // faster than result <- left, anl result,right
6088 // and better if result is SFR
6089 if (AOP_TYPE(left) == AOP_ACC) {
6090 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6092 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6093 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6095 if ( AOP_TYPE(result) != AOP_ACC){
6096 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6102 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6103 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6104 freeAsmop(result,NULL,ic,TRUE);
6107 /*-----------------------------------------------------------------*/
6108 /* genInline - write the inline code out */
6109 /*-----------------------------------------------------------------*/
6110 static void genInline (iCode *ic)
6112 char *buffer, *bp, *bp1;
6115 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6117 _G.inLine += (!options.asmpeep);
6119 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6120 strcpy(buffer,IC_INLINE(ic));
6122 /* emit each line as a code */
6128 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6136 /* print label, use this special format with NULL directive
6137 * to denote that the argument should not be indented with tab */
6138 addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6145 if ((bp1 != bp) && *bp1)
6146 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6150 _G.inLine -= (!options.asmpeep);
6153 /*-----------------------------------------------------------------*/
6154 /* genRRC - rotate right with carry */
6155 /*-----------------------------------------------------------------*/
6156 static void genRRC (iCode *ic)
6158 operand *left , *result ;
6159 int size, offset = 0, same;
6162 /* rotate right with carry */
6164 result=IC_RESULT(ic);
6165 aopOp (left,ic,FALSE);
6166 aopOp (result,ic,FALSE);
6168 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6170 same = pic14_sameRegs(AOP(result),AOP(left));
6172 size = AOP_SIZE(result);
6174 /* get the lsb and put it into the carry */
6175 emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6182 emitpcode(POC_RRF, popGet(AOP(left),offset));
6184 emitpcode(POC_RRFW, popGet(AOP(left),offset));
6185 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6191 freeAsmop(left,NULL,ic,TRUE);
6192 freeAsmop(result,NULL,ic,TRUE);
6195 /*-----------------------------------------------------------------*/
6196 /* genRLC - generate code for rotate left with carry */
6197 /*-----------------------------------------------------------------*/
6198 static void genRLC (iCode *ic)
6200 operand *left , *result ;
6201 int size, offset = 0;
6205 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6206 /* rotate right with carry */
6208 result=IC_RESULT(ic);
6209 aopOp (left,ic,FALSE);
6210 aopOp (result,ic,FALSE);
6212 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6214 same = pic14_sameRegs(AOP(result),AOP(left));
6216 /* move it to the result */
6217 size = AOP_SIZE(result);
6219 /* get the msb and put it into the carry */
6220 emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6227 emitpcode(POC_RLF, popGet(AOP(left),offset));
6229 emitpcode(POC_RLFW, popGet(AOP(left),offset));
6230 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6237 freeAsmop(left,NULL,ic,TRUE);
6238 freeAsmop(result,NULL,ic,TRUE);
6241 /*-----------------------------------------------------------------*/
6242 /* genGetHbit - generates code get highest order bit */
6243 /*-----------------------------------------------------------------*/
6244 static void genGetHbit (iCode *ic)
6246 operand *left, *result;
6248 result=IC_RESULT(ic);
6249 aopOp (left,ic,FALSE);
6250 aopOp (result,ic,FALSE);
6253 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6254 /* get the highest order byte into a */
6255 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6256 if(AOP_TYPE(result) == AOP_CRY){
6257 pic14_emitcode("rlc","a");
6258 pic14_outBitC(result);
6261 pic14_emitcode("rl","a");
6262 pic14_emitcode("anl","a,#0x01");
6263 pic14_outAcc(result);
6267 freeAsmop(left,NULL,ic,TRUE);
6268 freeAsmop(result,NULL,ic,TRUE);
6271 /*-----------------------------------------------------------------*/
6272 /* AccRol - rotate left accumulator by known count */
6273 /*-----------------------------------------------------------------*/
6274 static void AccRol (operand *op,int offset,int shCount)
6277 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6278 shCount &= 0x0007; // shCount : 0..7
6283 pic14_emitcode("rl","a");
6284 emitpcode(POC_RLF,popGet(AOP(op),offset));
6287 pic14_emitcode("rl","a");
6288 pic14_emitcode("rl","a");
6289 emitpcode(POC_RLF,popGet(AOP(op),offset));
6290 emitpcode(POC_RLF,popGet(AOP(op),offset));
6293 pic14_emitcode("swap","a");
6294 pic14_emitcode("rr","a");
6295 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6296 emitpcode(POC_RRF,popGet(AOP(op),offset));
6299 pic14_emitcode("swap","a");
6300 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6303 pic14_emitcode("swap","a");
6304 pic14_emitcode("rl","a");
6305 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6306 emitpcode(POC_RLF,popGet(AOP(op),offset));
6309 pic14_emitcode("rr","a");
6310 pic14_emitcode("rr","a");
6311 emitpcode(POC_RRF,popGet(AOP(op),offset));
6312 emitpcode(POC_RRF,popGet(AOP(op),offset));
6315 pic14_emitcode("rr","a");
6316 emitpcode(POC_RRF,popGet(AOP(op),offset));
6321 /*-----------------------------------------------------------------*/
6322 /* AccLsh - left shift accumulator by known count */
6323 /*-----------------------------------------------------------------*/
6324 static void AccLsh (operand *op,int offset,int shCount)
6327 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6332 emitpcode (POC_RLF, popGet (AOP(op), 0));
6334 /* rotate left accumulator */
6335 AccRol(op,offset,shCount);
6336 /* and kill the lower order bits */
6337 emitpcode(POC_MOVLW,popGetLit(SLMask[shCount]));
6338 emitpcode (POC_ANDWF, popGet (AOP(op),0));
6343 /*-----------------------------------------------------------------*/
6344 /* AccRsh - right shift accumulator by known count */
6345 /*-----------------------------------------------------------------*/
6346 static void AccRsh (operand *op,int offset,int shCount)
6349 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6353 emitpcode (POC_RRF, popGet (AOP(op), 0));
6355 /* rotate right accumulator */
6356 AccRol(op,offset,8 - shCount);
6357 /* and kill the higher order bits */
6358 emitpcode (POC_MOVLW, popGetLit (SRMask[shCount]));
6359 emitpcode (POC_ANDWF, popGet (AOP(op),0));
6365 /*-----------------------------------------------------------------*/
6366 /* AccSRsh - signed right shift accumulator by known count */
6367 /*-----------------------------------------------------------------*/
6368 static void AccSRsh (int shCount)
6371 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6374 pic14_emitcode("mov","c,acc.7");
6375 pic14_emitcode("rrc","a");
6376 } else if(shCount == 2){
6377 pic14_emitcode("mov","c,acc.7");
6378 pic14_emitcode("rrc","a");
6379 pic14_emitcode("mov","c,acc.7");
6380 pic14_emitcode("rrc","a");
6382 tlbl = newiTempLabel(NULL);
6383 /* rotate right accumulator */
6384 AccRol(8 - shCount);
6385 /* and kill the higher order bits */
6386 pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6387 pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6388 pic14_emitcode("orl","a,#0x%02x",
6389 (unsigned char)~SRMask[shCount]);
6390 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6395 /*-----------------------------------------------------------------*/
6396 /* shiftR1Left2Result - shift right one byte from left to result */
6397 /*-----------------------------------------------------------------*/
6398 static void shiftR1Left2ResultSigned (operand *left, int offl,
6399 operand *result, int offr,
6405 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6407 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6411 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6413 emitpcode(POC_RRF, popGet(AOP(result),offr));
6415 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6416 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6422 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6424 emitpcode(POC_RRF, popGet(AOP(result),offr));
6426 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6427 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6429 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6430 emitpcode(POC_RRF, popGet(AOP(result),offr));
6436 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6438 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6439 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6442 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6443 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6444 emitpcode(POC_ANDLW, popGetLit(0x1f));
6446 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6447 emitpcode(POC_IORLW, popGetLit(0xe0));
6449 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6453 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6454 emitpcode(POC_ANDLW, popGetLit(0x0f));
6455 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6456 emitpcode(POC_IORLW, popGetLit(0xf0));
6457 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6461 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6463 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6464 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6466 emitpcode(POC_RRFW, popGet(AOP(result),offr));
6467 emitpcode(POC_ANDLW, popGetLit(0x07));
6468 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6469 emitpcode(POC_IORLW, popGetLit(0xf8));
6470 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6475 emitpcode(POC_MOVLW, popGetLit(0x00));
6476 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6477 emitpcode(POC_MOVLW, popGetLit(0xfe));
6478 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6479 emitpcode(POC_IORLW, popGetLit(0x01));
6480 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6482 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6483 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6484 emitpcode(POC_DECF, popGet(AOP(result),offr));
6485 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6486 emitpcode(POC_BCF, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6492 emitpcode(POC_MOVLW, popGetLit(0x00));
6493 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6494 emitpcode(POC_MOVLW, popGetLit(0xff));
6495 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6497 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6498 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6499 emitpcode(POC_DECF, popGet(AOP(result),offr));
6507 /*-----------------------------------------------------------------*/
6508 /* shiftR1Left2Result - shift right one byte from left to result */
6509 /*-----------------------------------------------------------------*/
6510 static void shiftR1Left2Result (operand *left, int offl,
6511 operand *result, int offr,
6512 int shCount, int sign)
6517 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6519 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6521 /* Copy the msb into the carry if signed. */
6523 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6533 emitpcode(POC_RRF, popGet(AOP(result),offr));
6535 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6536 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6542 emitpcode(POC_RRF, popGet(AOP(result),offr));
6544 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6545 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6548 emitpcode(POC_RRF, popGet(AOP(result),offr));
6553 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6555 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6556 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6559 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6560 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6561 emitpcode(POC_ANDLW, popGetLit(0x1f));
6562 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6566 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6567 emitpcode(POC_ANDLW, popGetLit(0x0f));
6568 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6572 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6573 emitpcode(POC_ANDLW, popGetLit(0x0f));
6574 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6576 emitpcode(POC_RRF, popGet(AOP(result),offr));
6581 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6582 emitpcode(POC_ANDLW, popGetLit(0x80));
6583 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6584 emitpcode(POC_RLF, popGet(AOP(result),offr));
6585 emitpcode(POC_RLF, popGet(AOP(result),offr));
6590 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6591 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6592 emitpcode(POC_RLF, popGet(AOP(result),offr));
6601 /*-----------------------------------------------------------------*/
6602 /* shiftL1Left2Result - shift left one byte from left to result */
6603 /*-----------------------------------------------------------------*/
6604 static void shiftL1Left2Result (operand *left, int offl,
6605 operand *result, int offr, int shCount)
6611 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6613 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6614 DEBUGpic14_emitcode ("; ***","same = %d",same);
6615 // l = aopGet(AOP(left),offl,FALSE,FALSE);
6617 /* shift left accumulator */
6618 //AccLsh(shCount); // don't comment out just yet...
6619 // aopPut(AOP(result),"a",offr);
6623 /* Shift left 1 bit position */
6624 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6626 emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6628 emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6629 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6633 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6634 emitpcode(POC_ANDLW,popGetLit(0x7e));
6635 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6636 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6639 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6640 emitpcode(POC_ANDLW,popGetLit(0x3e));
6641 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6642 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6643 emitpcode(POC_RLF, popGet(AOP(result),offr));
6646 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6647 emitpcode(POC_ANDLW, popGetLit(0xf0));
6648 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6651 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6652 emitpcode(POC_ANDLW, popGetLit(0xf0));
6653 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6654 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6657 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6658 emitpcode(POC_ANDLW, popGetLit(0x30));
6659 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6660 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6661 emitpcode(POC_RLF, popGet(AOP(result),offr));
6664 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6665 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6666 emitpcode(POC_RRF, popGet(AOP(result),offr));
6670 DEBUGpic14_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6676 /*-----------------------------------------------------------------*/
6677 /* movLeft2Result - move byte from left to result */
6678 /*-----------------------------------------------------------------*/
6679 static void movLeft2Result (operand *left, int offl,
6680 operand *result, int offr)
6684 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6685 if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6686 l = aopGet(AOP(left),offl,FALSE,FALSE);
6688 if (*l == '@' && (IS_AOP_PREG(result))) {
6689 pic14_emitcode("mov","a,%s",l);
6690 aopPut(AOP(result),"a",offr);
6692 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6693 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6698 /*-----------------------------------------------------------------*/
6699 /* shiftLeft_Left2ResultLit - shift left by known count */
6700 /*-----------------------------------------------------------------*/
6702 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6704 int size, same, offr, i;
6706 size = AOP_SIZE(left);
6707 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6709 same = pic14_sameRegs (AOP(left), AOP(result));
6712 shCount = shCount & 0x07;
6718 case 0: /* takes 0 or 2N cycles (for offr==0) */
6719 if (!same || offr) {
6720 for (i=size-1; i >= 0; i--)
6721 movLeft2Result (left, i, result, offr + i);
6725 case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6727 shiftLeft_Left2ResultLit (left, result, 8 * offr);
6728 shiftLeft_Left2ResultLit (result, result, shCount);
6729 return; /* prevent clearing result again */
6732 for (i=0; i < size; i++) {
6733 if (same && !offr) {
6734 emitpcode (POC_RLF, popGet (AOP(left), i));
6736 emitpcode (POC_RLFW, popGet (AOP(left), i));
6737 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6743 case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
6744 /* works in-place/with offr as well */
6745 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
6746 emitpcode (POC_ANDLW, popGetLit (0xF0));
6747 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
6749 for (i = size - 2; i >= 0; i--)
6751 emitpcode (POC_SWAPFW, popGet (AOP(left), i));
6752 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6753 emitpcode (POC_ANDLW, popGetLit (0x0F));
6754 emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
6755 emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
6759 case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
6760 /* works in-place/with offr as well */
6761 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
6762 for (i = size-2; i >= 0; i--) {
6763 emitpcode (POC_RRFW, popGet (AOP(left), i));
6764 emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
6766 emitpcode (POC_CLRF, popGet (AOP(result), offr));
6767 emitpcode (POC_RRF, popGet (AOP(result), offr));
6771 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
6772 shiftLeft_Left2ResultLit (result, result, 1);
6773 return; /* prevent clearing result again */
6779 emitpcode (POC_CLRF, popGet (AOP(result), offr));
6783 /*-----------------------------------------------------------------*/
6784 /* shiftRight_Left2ResultLit - shift right by known count */
6785 /*-----------------------------------------------------------------*/
6787 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
6789 int size, same, offr, i;
6791 size = AOP_SIZE(left);
6792 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6794 same = pic14_sameRegs (AOP(left), AOP(result));
6797 shCount = shCount & 0x07;
6805 case 0: /* takes 0 or 2N cycles (for offr==0) */
6806 if (!same || offr) {
6807 for (i=0; i < size; i++)
6808 movLeft2Result (left, i + offr, result, i);
6812 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
6813 emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
6815 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
6816 shiftRight_Left2ResultLit (result, result, shCount, sign);
6817 return; /* prevent sign-extending result again */
6821 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
6824 for (i = size-1; i >= 0; i--) {
6825 if (same && !offr) {
6826 emitpcode (POC_RRF, popGet (AOP(left), i));
6828 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
6829 emitpcode (POC_MOVWF, popGet (AOP(result), i));
6835 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
6836 /* works in-place/with offr as well */
6837 emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
6838 emitpcode (POC_ANDLW, popGetLit (0x0F));
6839 emitpcode (POC_MOVWF, popGet(AOP(result), 0));
6841 for (i = 1; i < size; i++)
6843 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
6844 emitpcode (POC_MOVWF, popGet (AOP(result), i));
6845 emitpcode (POC_ANDLW, popGetLit (0xF0));
6846 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
6847 emitpcode (POC_XORWF, popGet (AOP(result), i));
6852 emitpcode (POC_MOVLW, popGetLit (0xF0));
6853 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
6854 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
6858 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
6859 /* works in-place/with offr as well */
6860 emitpcode (POC_RLFW, popGet (AOP(left), offr));
6861 for (i = 0; i < size-1; i++) {
6862 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
6863 emitpcode (POC_MOVWF, popGet (AOP(result), i));
6865 emitpcode (POC_CLRF, popGet (AOP(result), size-1));
6867 emitpcode (POC_RLF, popGet (AOP(result), size-1));
6870 emitpcode (POC_DECF, popGet (AOP(result), size-1));
6875 shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
6876 shiftRight_Left2ResultLit (result, result, 1, sign);
6877 return; /* prevent sign extending result again */
6882 addSign (result, size, sign);
6886 /*-----------------------------------------------------------------*/
6887 /* shiftL2Left2Result - shift left two bytes from left to result */
6888 /*-----------------------------------------------------------------*/
6889 static void shiftL2Left2Result (operand *left, int offl,
6890 operand *result, int offr, int shCount)
6894 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6896 if(pic14_sameRegs(AOP(result), AOP(left))) {
6904 emitpcode(POC_MOVFW,popGet(AOP(result),offr));
6905 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6906 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6910 emitpcode(POC_RLF, popGet(AOP(result),offr));
6911 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6917 emitpcode(POC_MOVLW, popGetLit(0x0f));
6918 emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
6919 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6920 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6921 emitpcode(POC_ANDFW, popGet(AOP(result),offr));
6922 emitpcode(POC_XORWF, popGet(AOP(result),offr));
6923 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6925 emitpcode(POC_RLF, popGet(AOP(result),offr));
6926 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6930 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6931 emitpcode(POC_RRF, popGet(AOP(result),offr));
6932 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6933 emitpcode(POC_RRF, popGet(AOP(result),offr));
6934 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6935 emitpcode(POC_ANDLW,popGetLit(0xc0));
6936 emitpcode(POC_XORFW,popGet(AOP(result),offr));
6937 emitpcode(POC_XORWF,popGet(AOP(result),offr));
6938 emitpcode(POC_XORFW,popGet(AOP(result),offr));
6939 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6942 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6943 emitpcode(POC_RRFW, popGet(AOP(result),offr));
6944 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6945 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6946 emitpcode(POC_RRF, popGet(AOP(result),offr));
6956 /* note, use a mov/add for the shift since the mov has a
6957 chance of getting optimized out */
6958 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6959 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6960 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6961 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6962 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6966 emitpcode(POC_RLF, popGet(AOP(result),offr));
6967 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6973 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6974 emitpcode(POC_ANDLW, popGetLit(0xF0));
6975 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6976 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6977 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6978 emitpcode(POC_ANDLW, popGetLit(0xF0));
6979 emitpcode(POC_XORWF, popGet(AOP(result),offr));
6980 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6984 emitpcode(POC_RLF, popGet(AOP(result),offr));
6985 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6989 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6990 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6991 emitpcode(POC_RRFW, popGet(AOP(result),offl));
6992 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6994 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6995 emitpcode(POC_RRF, popGet(AOP(result),offr));
6996 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6997 emitpcode(POC_ANDLW,popGetLit(0xc0));
6998 emitpcode(POC_XORFW,popGet(AOP(result),offr));
6999 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7000 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7001 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7004 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7005 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7006 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7007 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7008 emitpcode(POC_RRF, popGet(AOP(result),offr));
7014 /*-----------------------------------------------------------------*/
7015 /* shiftR2Left2Result - shift right two bytes from left to result */
7016 /*-----------------------------------------------------------------*/
7017 static void shiftR2Left2Result (operand *left, int offl,
7018 operand *result, int offr,
7019 int shCount, int sign)
7024 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7025 same = pic14_sameRegs(AOP(result), AOP(left));
7027 if(same && ((offl + MSB16) == offr)){
7029 /* don't crash result[offr] */
7030 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7031 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7034 movLeft2Result(left,offl, result, offr);
7035 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7038 /* a:x >> shCount (x = lsb(result))*/
7041 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7043 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7052 emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7057 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7058 emitpcode(POC_RRF,popGet(AOP(result),offr));
7060 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7061 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7062 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7063 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7068 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7071 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7072 emitpcode(POC_RRF,popGet(AOP(result),offr));
7079 emitpcode(POC_MOVLW, popGetLit(0xf0));
7080 emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7081 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7083 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7084 emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7085 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7086 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7088 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7089 emitpcode(POC_ANDLW, popGetLit(0x0f));
7090 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7092 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7093 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7094 emitpcode(POC_ANDLW, popGetLit(0xf0));
7095 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7096 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7100 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7101 emitpcode(POC_RRF, popGet(AOP(result),offr));
7105 emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7106 emitpcode(POC_BTFSC,
7107 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7108 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7116 emitpcode(POC_RLF, popGet(AOP(result),offr));
7117 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7119 emitpcode(POC_RLF, popGet(AOP(result),offr));
7120 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7121 emitpcode(POC_RLFW, popGet(AOP(result),offr));
7122 emitpcode(POC_ANDLW,popGetLit(0x03));
7124 emitpcode(POC_BTFSC,
7125 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7126 emitpcode(POC_IORLW,popGetLit(0xfc));
7128 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7129 emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7130 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7131 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7133 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7134 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7135 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7136 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7137 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7138 emitpcode(POC_RLF, popGet(AOP(result),offr));
7139 emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7140 emitpcode(POC_ANDLW,popGetLit(0x03));
7142 emitpcode(POC_BTFSC,
7143 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7144 emitpcode(POC_IORLW,popGetLit(0xfc));
7146 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7147 //emitpcode(POC_RLF, popGet(AOP(result),offr));
7154 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7155 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7156 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7157 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7160 emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7162 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7166 /*-----------------------------------------------------------------*/
7167 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7168 /*-----------------------------------------------------------------*/
7169 static void shiftLLeftOrResult (operand *left, int offl,
7170 operand *result, int offr, int shCount)
7173 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7175 /* shift left accumulator */
7176 AccLsh(left,offl,shCount);
7177 /* or with result */
7178 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7179 assert ( !"broken (modifies left, fails for left==result))" );
7182 /*-----------------------------------------------------------------*/
7183 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7184 /*-----------------------------------------------------------------*/
7185 static void shiftRLeftOrResult (operand *left, int offl,
7186 operand *result, int offr, int shCount)
7189 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7191 /* shift right accumulator */
7192 AccRsh(left,offl,shCount);
7193 /* or with result */
7194 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7195 assert ( !"broken (modifies left, fails for left==result))" );
7198 /*-----------------------------------------------------------------*/
7199 /* genlshOne - left shift a one byte quantity by known count */
7200 /*-----------------------------------------------------------------*/
7201 static void genlshOne (operand *result, operand *left, int shCount)
7204 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7205 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7208 /*-----------------------------------------------------------------*/
7209 /* genlshTwo - left shift two bytes by known amount != 0 */
7210 /*-----------------------------------------------------------------*/
7211 static void genlshTwo (operand *result,operand *left, int shCount)
7216 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7217 size = pic14_getDataSize(result);
7219 /* if shCount >= 8 */
7225 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7227 movLeft2Result(left, LSB, result, MSB16);
7229 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7232 /* 1 <= shCount <= 7 */
7235 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7237 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7241 /*-----------------------------------------------------------------*/
7242 /* shiftLLong - shift left one long from left to result */
7243 /* offl = LSB or MSB16 */
7244 /*-----------------------------------------------------------------*/
7245 static void shiftLLong (operand *left, operand *result, int offr )
7248 int size = AOP_SIZE(result);
7251 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7252 if(size >= LSB+offr){
7253 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7255 pic14_emitcode("add","a,acc");
7256 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7257 size >= MSB16+offr && offr != LSB )
7258 pic14_emitcode("xch","a,%s",
7259 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7261 aopPut(AOP(result),"a",LSB+offr);
7264 if(size >= MSB16+offr){
7265 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7266 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7269 pic14_emitcode("rlc","a");
7270 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7271 size >= MSB24+offr && offr != LSB)
7272 pic14_emitcode("xch","a,%s",
7273 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7275 aopPut(AOP(result),"a",MSB16+offr);
7278 if(size >= MSB24+offr){
7279 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7280 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7283 pic14_emitcode("rlc","a");
7284 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7285 size >= MSB32+offr && offr != LSB )
7286 pic14_emitcode("xch","a,%s",
7287 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7289 aopPut(AOP(result),"a",MSB24+offr);
7292 if(size > MSB32+offr){
7293 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7294 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7297 pic14_emitcode("rlc","a");
7298 aopPut(AOP(result),"a",MSB32+offr);
7301 aopPut(AOP(result),zero,LSB);
7304 /*-----------------------------------------------------------------*/
7305 /* genlshFour - shift four byte by a known amount != 0 */
7306 /*-----------------------------------------------------------------*/
7307 static void genlshFour (operand *result, operand *left, int shCount)
7312 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7313 size = AOP_SIZE(result);
7315 /* if shifting more that 3 bytes */
7316 if (shCount >= 24 ) {
7319 /* lowest order of left goes to the highest
7320 order of the destination */
7321 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7323 movLeft2Result(left, LSB, result, MSB32);
7324 aopPut(AOP(result),zero,LSB);
7325 aopPut(AOP(result),zero,MSB16);
7326 aopPut(AOP(result),zero,MSB32);
7330 /* more than two bytes */
7331 else if ( shCount >= 16 ) {
7332 /* lower order two bytes goes to higher order two bytes */
7334 /* if some more remaining */
7336 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7338 movLeft2Result(left, MSB16, result, MSB32);
7339 movLeft2Result(left, LSB, result, MSB24);
7341 aopPut(AOP(result),zero,MSB16);
7342 aopPut(AOP(result),zero,LSB);
7346 /* if more than 1 byte */
7347 else if ( shCount >= 8 ) {
7348 /* lower order three bytes goes to higher order three bytes */
7352 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7354 movLeft2Result(left, LSB, result, MSB16);
7356 else{ /* size = 4 */
7358 movLeft2Result(left, MSB24, result, MSB32);
7359 movLeft2Result(left, MSB16, result, MSB24);
7360 movLeft2Result(left, LSB, result, MSB16);
7361 aopPut(AOP(result),zero,LSB);
7363 else if(shCount == 1)
7364 shiftLLong(left, result, MSB16);
7366 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7367 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7368 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7369 aopPut(AOP(result),zero,LSB);
7374 /* 1 <= shCount <= 7 */
7375 else if(shCount <= 2){
7376 shiftLLong(left, result, LSB);
7378 shiftLLong(result, result, LSB);
7380 /* 3 <= shCount <= 7, optimize */
7382 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7383 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7384 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7390 /*-----------------------------------------------------------------*/
7391 /* genLeftShiftLiteral - left shifting by known count */
7392 /*-----------------------------------------------------------------*/
7393 static void genLeftShiftLiteral (operand *left,
7398 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7402 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7403 freeAsmop(right,NULL,ic,TRUE);
7405 aopOp(left,ic,FALSE);
7406 aopOp(result,ic,FALSE);
7408 size = getSize(operandType(result));
7411 pic14_emitcode("; shift left ","result %d, left %d",size,
7415 /* I suppose that the left size >= result size */
7418 movLeft2Result(left, size, result, size);
7422 else if(shCount >= (size * 8))
7424 aopPut(AOP(result),zero,size);
7428 genlshOne (result,left,shCount);
7433 genlshTwo (result,left,shCount);
7437 genlshFour (result,left,shCount);
7441 freeAsmop(left,NULL,ic,TRUE);
7442 freeAsmop(result,NULL,ic,TRUE);
7446 /*-----------------------------------------------------------------*
7447 * genMultiAsm - repeat assembly instruction for size of register.
7448 * if endian == 1, then the high byte (i.e base address + size of
7449 * register) is used first else the low byte is used first;
7450 *-----------------------------------------------------------------*/
7451 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7457 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7470 emitpcode(poc, popGet(AOP(reg),offset));
7475 /*-----------------------------------------------------------------*/
7476 /* genLeftShift - generates code for left shifting */
7477 /*-----------------------------------------------------------------*/
7478 static void genLeftShift (iCode *ic)
7480 operand *left,*right, *result;
7482 unsigned long lit = 0L;
7484 symbol *tlbl , *tlbl1;
7488 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7490 right = IC_RIGHT(ic);
7492 result = IC_RESULT(ic);
7494 aopOp(right,ic,FALSE);
7495 aopOp(left,ic,FALSE);
7496 aopOp(result,ic,FALSE);
7499 /* if the shift count is known then do it
7500 as efficiently as possible */
7501 if (AOP_TYPE(right) == AOP_LIT) {
7502 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7506 /* shift count is unknown then we have to form
7507 a loop get the loop count in B : Note: we take
7508 only the lower order byte since shifting
7509 more that 32 bits make no sense anyway, ( the
7510 largest size of an object can be only 32 bits ) */
7513 /* now move the left to the result if they are not the
7515 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
7516 AOP_SIZE(result) > 1) {
7518 size = AOP_SIZE(result);
7521 l = aopGet(AOP(left),offset,FALSE,TRUE);
7522 if (*l == '@' && (IS_AOP_PREG(result))) {
7524 pic14_emitcode("mov","a,%s",l);
7525 aopPut(AOP(result),"a",offset);
7527 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
7528 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7529 //aopPut(AOP(result),l,offset);
7535 if(AOP_TYPE(left) == AOP_LIT)
7536 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7538 size = AOP_SIZE(result);
7540 /* if it is only one byte then */
7542 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7543 emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7544 emitpcode(POC_ANDLW, popGetLit(0xf0));
7545 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7546 emitpcode(POC_MOVFW, popGet(AOP(left),0));
7547 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7548 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7549 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7550 emitpcode(POC_RLFW, popGet(AOP(result),0));
7551 emitpcode(POC_ANDLW, popGetLit(0xfe));
7552 emitpcode(POC_ADDFW, popGet(AOP(result),0));
7553 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7554 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7557 tlbl = newiTempLabel(NULL);
7558 if (!pic14_sameRegs(AOP(left),AOP(result))) {
7559 if (AOP_TYPE(left) == AOP_LIT)
7560 emitpcode(POC_MOVLW, popGetLit(lit));
7562 emitpcode(POC_MOVFW, popGet(AOP(left),0));
7563 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7566 emitpcode(POC_COMFW, popGet(AOP(right),0));
7567 emitpcode(POC_RRF, popGet(AOP(result),0));
7568 emitpLabel(tlbl->key);
7569 emitpcode(POC_RLF, popGet(AOP(result),0));
7570 emitpcode(POC_ADDLW, popGetLit(1));
7572 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7577 if (pic14_sameRegs(AOP(left),AOP(result))) {
7579 tlbl = newiTempLabel(NULL);
7580 emitpcode(POC_COMFW, popGet(AOP(right),0));
7581 genMultiAsm(POC_RRF, result, size,1);
7582 emitpLabel(tlbl->key);
7583 genMultiAsm(POC_RLF, result, size,0);
7584 emitpcode(POC_ADDLW, popGetLit(1));
7586 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7590 //tlbl = newiTempLabel(NULL);
7592 //tlbl1 = newiTempLabel(NULL);
7594 //reAdjustPreg(AOP(result));
7596 //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7597 //pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7598 //l = aopGet(AOP(result),offset,FALSE,FALSE);
7600 //pic14_emitcode("add","a,acc");
7601 //aopPut(AOP(result),"a",offset++);
7603 // l = aopGet(AOP(result),offset,FALSE,FALSE);
7605 // pic14_emitcode("rlc","a");
7606 // aopPut(AOP(result),"a",offset++);
7608 //reAdjustPreg(AOP(result));
7610 //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7611 //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7614 tlbl = newiTempLabel(NULL);
7615 tlbl1= newiTempLabel(NULL);
7617 size = AOP_SIZE(result);
7620 pctemp = popGetTempReg(); /* grab a temporary working register. */
7622 emitpcode(POC_MOVFW, popGet(AOP(right),0));
7624 /* offset should be 0, 1 or 3 */
7625 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7627 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
7629 emitpcode(POC_MOVWF, pctemp);
7632 emitpLabel(tlbl->key);
7635 emitpcode(POC_RLF, popGet(AOP(result),0));
7637 emitpcode(POC_RLF, popGet(AOP(result),offset++));
7639 emitpcode(POC_DECFSZ, pctemp);
7640 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7641 emitpLabel(tlbl1->key);
7643 popReleaseTempReg(pctemp);
7647 freeAsmop (right,NULL,ic,TRUE);
7648 freeAsmop(left,NULL,ic,TRUE);
7649 freeAsmop(result,NULL,ic,TRUE);
7653 /*-----------------------------------------------------------------*/
7654 /* genrshOne - right shift a one byte quantity by known count */
7655 /*-----------------------------------------------------------------*/
7656 static void genrshOne (operand *result, operand *left,
7657 int shCount, int sign)
7660 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7661 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7664 /*-----------------------------------------------------------------*/
7665 /* genrshTwo - right shift two bytes by known amount != 0 */
7666 /*-----------------------------------------------------------------*/
7667 static void genrshTwo (operand *result,operand *left,
7668 int shCount, int sign)
7671 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7672 /* if shCount >= 8 */
7676 shiftR1Left2Result(left, MSB16, result, LSB,
7679 movLeft2Result(left, MSB16, result, LSB);
7681 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7684 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7685 emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7689 /* 1 <= shCount <= 7 */
7691 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
7694 /*-----------------------------------------------------------------*/
7695 /* shiftRLong - shift right one long from left to result */
7696 /* offl = LSB or MSB16 */
7697 /*-----------------------------------------------------------------*/
7698 static void shiftRLong (operand *left, int offl,
7699 operand *result, int sign)
7704 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7706 size = AOP_SIZE(left);
7707 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7710 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7714 assert (offl >= 0 && offl < size);
7716 same = pic14_sameRegs (AOP(left), AOP(result));
7718 /* perform the shift */
7721 if (same && !offl) {
7722 emitpcode (POC_RRF, popGet (AOP(result), size));
7724 emitpcode (POC_RRFW, popGet (AOP(left), size));
7725 emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7729 addSign (result, AOP_SIZE(left) - offl, sign);
7732 /*-----------------------------------------------------------------*/
7733 /* genrshFour - shift four byte by a known amount != 0 */
7734 /*-----------------------------------------------------------------*/
7735 static void genrshFour (operand *result, operand *left,
7736 int shCount, int sign)
7739 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7740 /* if shifting more that 3 bytes */
7741 if(shCount >= 24 ) {
7744 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7746 movLeft2Result(left, MSB32, result, LSB);
7748 addSign(result, MSB16, sign);
7750 else if(shCount >= 16){
7753 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7755 movLeft2Result(left, MSB24, result, LSB);
7756 movLeft2Result(left, MSB32, result, MSB16);
7758 addSign(result, MSB24, sign);
7760 else if(shCount >= 8){
7763 shiftRLong(left, MSB16, result, sign);
7764 else if(shCount == 0){
7765 movLeft2Result(left, MSB16, result, LSB);
7766 movLeft2Result(left, MSB24, result, MSB16);
7767 movLeft2Result(left, MSB32, result, MSB24);
7768 addSign(result, MSB32, sign);
7771 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7772 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7773 /* the last shift is signed */
7774 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7775 addSign(result, MSB32, sign);
7778 else{ /* 1 <= shCount <= 7 */
7780 shiftRLong(left, LSB, result, sign);
7782 shiftRLong(result, LSB, result, sign);
7785 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7786 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7787 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7792 /*-----------------------------------------------------------------*/
7793 /* genRightShiftLiteral - right shifting by known count */
7794 /*-----------------------------------------------------------------*/
7795 static void genRightShiftLiteral (operand *left,
7801 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7805 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7806 freeAsmop(right,NULL,ic,TRUE);
7808 aopOp(left,ic,FALSE);
7809 aopOp(result,ic,FALSE);
7812 pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7816 lsize = pic14_getDataSize(left);
7817 res_size = pic14_getDataSize(result);
7818 /* test the LEFT size !!! */
7820 /* I suppose that the left size >= result size */
7823 movLeft2Result(left, res_size, result, res_size);
7826 else if(shCount >= (lsize * 8)){
7829 emitpcode(POC_CLRF, popGet(AOP(result),LSB));
7831 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7832 emitpcode(POC_DECF, popGet(AOP(result),LSB));
7837 emitpcode(POC_MOVLW, popGetLit(0));
7838 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7839 emitpcode(POC_MOVLW, popGetLit(0xff));
7841 emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
7846 emitpcode(POC_CLRF, popGet(AOP(result),res_size));
7853 genrshOne (result,left,shCount,sign);
7857 genrshTwo (result,left,shCount,sign);
7861 genrshFour (result,left,shCount,sign);
7869 freeAsmop(left,NULL,ic,TRUE);
7870 freeAsmop(result,NULL,ic,TRUE);
7874 /*-----------------------------------------------------------------*/
7875 /* genSignedRightShift - right shift of signed number */
7876 /*-----------------------------------------------------------------*/
7877 static void genSignedRightShift (iCode *ic)
7879 operand *right, *left, *result;
7882 symbol *tlbl, *tlbl1 ;
7885 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7887 /* we do it the hard way put the shift count in b
7888 and loop thru preserving the sign */
7890 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7892 right = IC_RIGHT(ic);
7894 result = IC_RESULT(ic);
7896 aopOp(right,ic,FALSE);
7897 aopOp(left,ic,FALSE);
7898 aopOp(result,ic,FALSE);
7901 if ( AOP_TYPE(right) == AOP_LIT) {
7902 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
7903 //genRightShiftLiteral (left,right,result,ic,1);
7906 /* shift count is unknown then we have to form
7907 a loop get the loop count in B : Note: we take
7908 only the lower order byte since shifting
7909 more that 32 bits make no sense anyway, ( the
7910 largest size of an object can be only 32 bits ) */
7912 //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7913 //pic14_emitcode("inc","b");
7914 //freeAsmop (right,NULL,ic,TRUE);
7915 //aopOp(left,ic,FALSE);
7916 //aopOp(result,ic,FALSE);
7918 /* now move the left to the result if they are not the
7920 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
7921 AOP_SIZE(result) > 1) {
7923 size = AOP_SIZE(result);
7927 l = aopGet(AOP(left),offset,FALSE,TRUE);
7928 if (*l == '@' && IS_AOP_PREG(result)) {
7929 pic14_emitcode("mov","a,%s",l);
7930 aopPut(AOP(result),"a",offset);
7932 aopPut(AOP(result),l,offset);
7934 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
7935 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7941 /* mov the highest order bit to OVR */
7942 tlbl = newiTempLabel(NULL);
7943 tlbl1= newiTempLabel(NULL);
7945 size = AOP_SIZE(result);
7948 pctemp = popGetTempReg(); /* grab a temporary working register. */
7950 emitpcode(POC_MOVFW, popGet(AOP(right),0));
7952 /* offset should be 0, 1 or 3 */
7953 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7955 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
7957 emitpcode(POC_MOVWF, pctemp);
7960 emitpLabel(tlbl->key);
7962 emitpcode(POC_RLFW, popGet(AOP(result),offset));
7963 emitpcode(POC_RRF, popGet(AOP(result),offset));
7966 emitpcode(POC_RRF, popGet(AOP(result),--offset));
7969 emitpcode(POC_DECFSZ, pctemp);
7970 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7971 emitpLabel(tlbl1->key);
7973 popReleaseTempReg(pctemp);
7975 size = AOP_SIZE(result);
7977 pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
7978 pic14_emitcode("rlc","a");
7979 pic14_emitcode("mov","ov,c");
7980 /* if it is only one byte then */
7982 l = aopGet(AOP(left),0,FALSE,FALSE);
7984 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7985 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7986 pic14_emitcode("mov","c,ov");
7987 pic14_emitcode("rrc","a");
7988 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7989 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7990 aopPut(AOP(result),"a",0);
7994 reAdjustPreg(AOP(result));
7995 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7996 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7997 pic14_emitcode("mov","c,ov");
7999 l = aopGet(AOP(result),offset,FALSE,FALSE);
8001 pic14_emitcode("rrc","a");
8002 aopPut(AOP(result),"a",offset--);
8004 reAdjustPreg(AOP(result));
8005 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8006 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8011 freeAsmop(left,NULL,ic,TRUE);
8012 freeAsmop(result,NULL,ic,TRUE);
8013 freeAsmop(right,NULL,ic,TRUE);
8016 /*-----------------------------------------------------------------*/
8017 /* genRightShift - generate code for right shifting */
8018 /*-----------------------------------------------------------------*/
8019 static void genRightShift (iCode *ic)
8021 operand *right, *left, *result;
8025 symbol *tlbl, *tlbl1 ;
8028 /* if signed then we do it the hard way preserve the
8029 sign bit moving it inwards */
8030 retype = getSpec(operandType(IC_RESULT(ic)));
8031 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8033 if (!SPEC_USIGN(retype)) {
8034 genSignedRightShift (ic);
8038 /* signed & unsigned types are treated the same : i.e. the
8039 signed is NOT propagated inwards : quoting from the
8040 ANSI - standard : "for E1 >> E2, is equivalent to division
8041 by 2**E2 if unsigned or if it has a non-negative value,
8042 otherwise the result is implementation defined ", MY definition
8043 is that the sign does not get propagated */
8045 right = IC_RIGHT(ic);
8047 result = IC_RESULT(ic);
8049 aopOp(right,ic,FALSE);
8050 aopOp(left,ic,FALSE);
8051 aopOp(result,ic,FALSE);
8053 /* if the shift count is known then do it
8054 as efficiently as possible */
8055 if (AOP_TYPE(right) == AOP_LIT) {
8056 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 0);
8057 //genRightShiftLiteral (left,right,result,ic, 0);
8061 /* shift count is unknown then we have to form
8062 a loop get the loop count in B : Note: we take
8063 only the lower order byte since shifting
8064 more that 32 bits make no sense anyway, ( the
8065 largest size of an object can be only 32 bits ) */
8067 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8068 pic14_emitcode("inc","b");
8070 /* now move the left to the result if they are not the
8072 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
8073 AOP_SIZE(result) > 1) {
8075 size = AOP_SIZE(result);
8078 l = aopGet(AOP(left),offset,FALSE,TRUE);
8079 if (*l == '@' && IS_AOP_PREG(result)) {
8081 pic14_emitcode("mov","a,%s",l);
8082 aopPut(AOP(result),"a",offset);
8084 aopPut(AOP(result),l,offset);
8089 tlbl = newiTempLabel(NULL);
8090 tlbl1= newiTempLabel(NULL);
8091 size = AOP_SIZE(result);
8094 /* if it is only one byte then */
8097 tlbl = newiTempLabel(NULL);
8098 if (!pic14_sameRegs(AOP(left),AOP(result))) {
8099 emitpcode(POC_MOVFW, popGet(AOP(left),0));
8100 emitpcode(POC_MOVWF, popGet(AOP(result),0));
8103 emitpcode(POC_COMFW, popGet(AOP(right),0));
8104 emitpcode(POC_RLF, popGet(AOP(result),0));
8105 emitpLabel(tlbl->key);
8106 emitpcode(POC_RRF, popGet(AOP(result),0));
8107 emitpcode(POC_ADDLW, popGetLit(1));
8109 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8114 reAdjustPreg(AOP(result));
8115 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8116 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8119 l = aopGet(AOP(result),offset,FALSE,FALSE);
8121 pic14_emitcode("rrc","a");
8122 aopPut(AOP(result),"a",offset--);
8124 reAdjustPreg(AOP(result));
8126 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8127 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8130 freeAsmop(left,NULL,ic,TRUE);
8131 freeAsmop (right,NULL,ic,TRUE);
8132 freeAsmop(result,NULL,ic,TRUE);
8135 /*-----------------------------------------------------------------*/
8136 /* genUnpackBits - generates code for unpacking bits */
8137 /*-----------------------------------------------------------------*/
8138 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype, iCode *ifx)
8141 int offset = 0; /* result byte offset */
8142 int rsize; /* result size */
8143 int rlen = 0; /* remaining bitfield length */
8144 sym_link *etype; /* bitfield type information */
8145 int blen; /* bitfield length */
8146 int bstr; /* bitfield starting bit within byte */
8149 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8150 etype = getSpec(operandType(result));
8151 rsize = getSize (operandType (result));
8152 blen = SPEC_BLEN (etype);
8153 bstr = SPEC_BSTR (etype);
8155 /* single bit field case */
8157 if (ifx) { /* that is for an if statement */
8160 resolveIfx(&rIfx,ifx);
8161 if (ptype == -1) /* direct */
8162 pcop = newpCodeOpBit(AOP(left)->aopu.pcop->name,bstr,0);
8164 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8165 emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8166 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8170 if (ptype == -1) /* direct */
8171 pcop = newpCodeOpBit(AOP(left)->aopu.pcop->name,bstr,0);
8173 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8174 emitpcode(POC_BTFSC,pcop);
8175 emitpcode(POC_BSF,newpCodeOpBit(AOP(result)->aopu.pcop->name,bstr,0));
8177 if (ptype == -1) /* direct */
8178 pcop = newpCodeOpBit(AOP(left)->aopu.pcop->name,bstr,0);
8180 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8181 emitpcode(POC_BTFSS,pcop);
8182 emitpcode(POC_BCF,newpCodeOpBit(AOP(result)->aopu.pcop->name,bstr,0));
8187 /* read the first byte */
8192 // pic14_emitcode("mov","a,@%s",rname);
8193 emitpcode(POC_MOVFW, popCopyReg(&pc_indf));
8197 pic14_emitcode("movx","a,@%s",rname);
8201 pic14_emitcode("movx","a,@dptr");
8205 pic14_emitcode("clr","a");
8206 pic14_emitcode("movc","a","@a+dptr");
8210 pic14_emitcode("lcall","__gptrget");
8214 /* if we have bitdisplacement then it fits */
8215 /* into this byte completely or if length is */
8216 /* less than a byte */
8217 if ((shCnt = SPEC_BSTR(etype)) || blen <= 8) {
8219 /* shift right acc */
8220 AccRsh(left,0,shCnt);
8222 pic14_emitcode("anl","a,#0x%02x",
8223 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
8224 aopPut(AOP(result),"a",offset);
8228 /* bit field did not fit in a byte */
8229 rlen = SPEC_BLEN(etype) - 8;
8230 aopPut(AOP(result),"a",offset++);
8237 pic14_emitcode("inc","%s",rname);
8238 pic14_emitcode("mov","a,@%s",rname);
8242 pic14_emitcode("inc","%s",rname);
8243 pic14_emitcode("movx","a,@%s",rname);
8247 pic14_emitcode("inc","dptr");
8248 pic14_emitcode("movx","a,@dptr");
8252 pic14_emitcode("clr","a");
8253 pic14_emitcode("inc","dptr");
8254 pic14_emitcode("movc","a","@a+dptr");
8258 pic14_emitcode("inc","dptr");
8259 pic14_emitcode("lcall","__gptrget");
8264 /* if we are done */
8268 aopPut(AOP(result),"a",offset++);
8273 pic14_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
8274 aopPut(AOP(result),"a",offset);
8281 /*-----------------------------------------------------------------*/
8282 /* genDataPointerGet - generates code when ptr offset is known */
8283 /*-----------------------------------------------------------------*/
8284 static void genDataPointerGet (operand *left,
8288 int size , offset = 0;
8291 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8294 /* optimization - most of the time, left and result are the same
8295 * address, but different types. for the pic code, we could omit
8298 aopOp(result,ic,TRUE);
8300 if (pic14_sameRegs (AOP(left), AOP(result)))
8303 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8305 //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8307 size = AOP_SIZE(result);
8308 if (size > AOP_SIZE(left)) size = AOP_SIZE(left);
8311 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8312 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8316 freeAsmop(left,NULL,ic,TRUE);
8317 freeAsmop(result,NULL,ic,TRUE);
8320 /*-----------------------------------------------------------------*/
8321 /* genNearPointerGet - pic14_emitcode for near pointer fetch */
8322 /*-----------------------------------------------------------------*/
8323 static void genNearPointerGet (operand *left,
8328 sym_link *ltype = operandType(left);
8329 sym_link *rtype = operandType(result);
8330 sym_link *retype= getSpec(rtype); /* bitfield type information */
8334 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8337 aopOp(left,ic,FALSE);
8339 /* if left is rematerialisable and
8340 result is not bit variable type and
8341 the left is pointer to data space i.e
8342 lower 128 bytes of space */
8343 if (AOP_TYPE(left) == AOP_PCODE && //AOP_TYPE(left) == AOP_IMMD &&
8344 !IS_BITVAR(retype) &&
8345 DCL_TYPE(ltype) == POINTER) {
8346 genDataPointerGet (left,result,ic);
8350 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8351 aopOp (result,ic,FALSE);
8353 /* Check if can access directly instead of via a pointer */
8354 if (PCOP(AOP(left))->type == PO_LITERAL && AOP_SIZE(result) == 1) {
8358 /* If the pointer value is not in a the FSR then need to put it in */
8359 if (!AOP_INPREG(AOP(left)) && !direct) {
8360 /* otherwise get a free pointer register */
8361 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8362 if (PCOP(AOP(result))->type == PO_LITERAL) /* XXX: check me */
8363 emitpcode(POC_MOVLW, popGet(AOP(left),0));
8365 emitpcode(POC_MOVFW, popGet(AOP(left),0));
8366 emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
8371 /* if bitfield then unpack the bits */
8372 if (IS_BITFIELD(retype))
8373 genUnpackBits (result,left,"indf",direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8375 /* we have can just get the values */
8376 int size = AOP_SIZE(result);
8379 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8383 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8385 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8386 if (AOP_TYPE(result) == AOP_LIT) {
8387 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8389 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8391 if (size && !direct)
8392 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8397 /* now some housekeeping stuff */
8399 /* we had to allocate for this iCode */
8400 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8401 freeAsmop(NULL,aop,ic,TRUE);
8403 /* we did not allocate which means left
8404 already in a pointer register, then
8405 if size > 0 && this could be used again
8406 we have to point it back to where it
8408 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8409 if (AOP_SIZE(result) > 1 &&
8410 !OP_SYMBOL(left)->remat &&
8411 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8413 int size = AOP_SIZE(result) - 1;
8415 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8420 freeAsmop(left,NULL,ic,TRUE);
8421 freeAsmop(result,NULL,ic,TRUE);
8425 /*-----------------------------------------------------------------*/
8426 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch */
8427 /*-----------------------------------------------------------------*/
8428 static void genPagedPointerGet (operand *left,
8435 sym_link *rtype, *retype;
8438 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8440 rtype = operandType(result);
8441 retype= getSpec(rtype);
8443 aopOp(left,ic,FALSE);
8445 /* if the value is already in a pointer register
8446 then don't need anything more */
8447 if (!AOP_INPREG(AOP(left))) {
8448 /* otherwise get a free pointer register */
8450 preg = getFreePtr(ic,&aop,FALSE);
8451 pic14_emitcode("mov","%s,%s",
8453 aopGet(AOP(left),0,FALSE,TRUE));
8454 rname = preg->name ;
8456 rname = aopGet(AOP(left),0,FALSE,FALSE);
8458 freeAsmop(left,NULL,ic,TRUE);
8459 aopOp (result,ic,FALSE);
8461 /* if bitfield then unpack the bits */
8462 if (IS_BITFIELD(retype))
8463 genUnpackBits (result,left,rname,PPOINTER,0);
8465 /* we have can just get the values */
8466 int size = AOP_SIZE(result);
8471 pic14_emitcode("movx","a,@%s",rname);
8472 aopPut(AOP(result),"a",offset);
8477 pic14_emitcode("inc","%s",rname);
8481 /* now some housekeeping stuff */
8483 /* we had to allocate for this iCode */
8484 freeAsmop(NULL,aop,ic,TRUE);
8486 /* we did not allocate which means left
8487 already in a pointer register, then
8488 if size > 0 && this could be used again
8489 we have to point it back to where it
8491 if (AOP_SIZE(result) > 1 &&
8492 !OP_SYMBOL(left)->remat &&
8493 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8495 int size = AOP_SIZE(result) - 1;
8497 pic14_emitcode("dec","%s",rname);
8502 freeAsmop(result,NULL,ic,TRUE);
8507 /*-----------------------------------------------------------------*/
8508 /* genFarPointerGet - gget value from far space */
8509 /*-----------------------------------------------------------------*/
8510 static void genFarPointerGet (operand *left,
8511 operand *result, iCode *ic)
8514 sym_link *retype = getSpec(operandType(result));
8517 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8519 aopOp(left,ic,FALSE);
8521 /* if the operand is already in dptr
8522 then we do nothing else we move the value to dptr */
8523 if (AOP_TYPE(left) != AOP_STR) {
8524 /* if this is remateriazable */
8525 if (AOP_TYPE(left) == AOP_IMMD)
8526 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8527 else { /* we need to get it byte by byte */
8528 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8529 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8530 if (options.model == MODEL_FLAT24)
8532 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8536 /* so dptr know contains the address */
8537 freeAsmop(left,NULL,ic,TRUE);
8538 aopOp(result,ic,FALSE);
8540 /* if bit then unpack */
8541 if (IS_BITFIELD(retype))
8542 genUnpackBits(result,left,"dptr",FPOINTER,0);
8544 size = AOP_SIZE(result);
8548 pic14_emitcode("movx","a,@dptr");
8549 aopPut(AOP(result),"a",offset++);
8551 pic14_emitcode("inc","dptr");
8555 freeAsmop(result,NULL,ic,TRUE);
8558 /*-----------------------------------------------------------------*/
8559 /* genCodePointerGet - get value from code space */
8560 /*-----------------------------------------------------------------*/
8561 static void genCodePointerGet (operand *left,
8562 operand *result, iCode *ic)
8565 sym_link *retype = getSpec(operandType(result));
8567 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8569 aopOp(left,ic,FALSE);
8571 /* if the operand is already in dptr
8572 then we do nothing else we move the value to dptr */
8573 if (AOP_TYPE(left) != AOP_STR) {
8574 /* if this is remateriazable */
8575 if (AOP_TYPE(left) == AOP_IMMD)
8576 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8577 else { /* we need to get it byte by byte */
8578 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8579 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8580 if (options.model == MODEL_FLAT24)
8582 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8586 /* so dptr know contains the address */
8587 freeAsmop(left,NULL,ic,TRUE);
8588 aopOp(result,ic,FALSE);
8590 /* if bit then unpack */
8591 if (IS_BITFIELD(retype))
8592 genUnpackBits(result,left,"dptr",CPOINTER,0);
8594 size = AOP_SIZE(result);
8598 pic14_emitcode("clr","a");
8599 pic14_emitcode("movc","a,@a+dptr");
8600 aopPut(AOP(result),"a",offset++);
8602 pic14_emitcode("inc","dptr");
8606 freeAsmop(result,NULL,ic,TRUE);
8609 /*-----------------------------------------------------------------*/
8610 /* genGenPointerGet - gget value from generic pointer space */
8611 /*-----------------------------------------------------------------*/
8612 static void genGenPointerGet (operand *left,
8613 operand *result, iCode *ic)
8616 sym_link *retype = getSpec(operandType(result));
8619 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8620 aopOp(left,ic,FALSE);
8621 aopOp(result,ic,FALSE);
8624 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8626 /* if the operand is already in dptr
8627 then we do nothing else we move the value to dptr */
8628 // if (AOP_TYPE(left) != AOP_STR) {
8629 /* if this is remateriazable */
8630 if (AOP_TYPE(left) == AOP_IMMD) {
8631 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8632 pic14_emitcode("mov","b,#%d",pointerCode(retype));
8634 else { /* we need to get it byte by byte */
8636 emitpcode(POC_MOVFW,popGet(AOP(left),0));
8637 emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8639 size = AOP_SIZE(result);
8643 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8644 emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
8646 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8651 /* so dptr know contains the address */
8653 /* if bit then unpack */
8654 //if (IS_BITFIELD(retype))
8655 // genUnpackBits(result,"dptr",GPOINTER);
8658 freeAsmop(left,NULL,ic,TRUE);
8659 freeAsmop(result,NULL,ic,TRUE);
8663 /*-----------------------------------------------------------------*/
8664 /* genConstPointerGet - get value from const generic pointer space */
8665 /*-----------------------------------------------------------------*/
8666 static void genConstPointerGet (operand *left,
8667 operand *result, iCode *ic)
8669 //sym_link *retype = getSpec(operandType(result));
8670 symbol *albl, *blbl;//, *clbl;
8676 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8677 aopOp(left,ic,FALSE);
8678 aopOp(result,ic,FALSE);
8680 size = AOP_SIZE(result);
8682 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8684 DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
8686 lit = aop_isLitLike (AOP(left));
8687 poc = lit ? POC_MOVLW : POC_MOVFW;
8691 for (i = 0; i < size; i++)
8693 albl = newiTempLabel(NULL);
8694 blbl = newiTempLabel(NULL);
8696 emitpcode(POC_CALL,popGetLabel(albl->key));
8697 pcop = popGetLabel(blbl->key);
8698 emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
8699 emitpcode(POC_GOTO,pcop);
8701 emitpLabel(albl->key);
8702 emitpcode(poc,popGetAddr(AOP(left),1,i));
8703 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
8704 emitpcode(poc,popGetAddr(AOP(left),0,i));
8705 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
8707 emitpLabel(blbl->key);
8708 emitpcode(POC_MOVWF,popGet(AOP(result),i));
8711 albl = newiTempLabel(NULL);
8712 blbl = newiTempLabel(NULL);
8713 //clbl = newiTempLabel(NULL);
8715 emitpcode (POC_GOTO, popGetLabel (blbl->key));
8717 emitpLabel(albl->key);
8718 emitpcode(poc,popGet(AOP(left),1));
8719 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
8720 emitpcode(poc,popGet(AOP(left),0));
8721 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
8723 emitpLabel(blbl->key);
8725 for (i = 0; i < size; i++)
8727 emitpcode(POC_CALL,popGetLabel(albl->key));
8728 /* the next two instructions (plus clbl) might be useless... */
8729 //pcop = popGetLabel(clbl->key);
8730 //emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
8731 //emitpcode(POC_GOTO,pcop);
8732 //emitpLabel(clbl->key);
8735 emitpcode (POC_INCF, popGet (AOP(left), 0));
8737 emitpcode (POC_INCF, popGet (AOP(left), 1));
8739 emitpcode(POC_MOVWF,popGet(AOP(result),i));
8742 /* restore left's value */
8743 emitpcode (POC_MOVLW, popGetLit (size-1));
8744 emitpcode (POC_SUBWF, popGet (AOP(left), 0));
8746 emitpcode (POC_DECF, popGet (AOP(left), 1));
8750 freeAsmop(left,NULL,ic,TRUE);
8751 freeAsmop(result,NULL,ic,TRUE);
8754 /*-----------------------------------------------------------------*/
8755 /* genPointerGet - generate code for pointer get */
8756 /*-----------------------------------------------------------------*/
8757 static void genPointerGet (iCode *ic)
8759 operand *left, *result ;
8760 sym_link *type, *etype;
8764 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8767 result = IC_RESULT(ic) ;
8769 /* depending on the type of pointer we need to
8770 move it to the correct pointer register */
8771 type = operandType(left);
8772 etype = getSpec(type);
8774 if (IS_PTR_CONST(type))
8775 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
8777 /* if left is of type of pointer then it is simple */
8778 if (IS_PTR(type) && !IS_FUNC(type->next))
8779 p_type = DCL_TYPE(type);
8781 /* we have to go by the storage class */
8782 p_type = PTR_TYPE(SPEC_OCLS(etype));
8784 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8786 if (SPEC_OCLS(etype)->codesp ) {
8787 DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
8788 //p_type = CPOINTER ;
8791 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
8792 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
8793 /*p_type = FPOINTER ;*/
8795 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
8796 DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
8797 /* p_type = PPOINTER; */
8799 if (SPEC_OCLS(etype) == idata )
8800 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
8801 /* p_type = IPOINTER; */
8803 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
8804 /* p_type = POINTER ; */
8807 /* now that we have the pointer type we assign
8808 the pointer values */
8813 genNearPointerGet (left,result,ic);
8817 genPagedPointerGet(left,result,ic);
8821 genFarPointerGet (left,result,ic);
8825 genConstPointerGet (left,result,ic);
8826 //pic14_emitcodePointerGet (left,result,ic);
8830 if (IS_CODEPTR(type) || IS_PTR_CONST(type))
8831 genConstPointerGet (left,result,ic);
8833 genGenPointerGet (left,result,ic);
8836 assert ( !"unhandled pointer type" );
8842 /*-----------------------------------------------------------------*/
8843 /* emitPtrByteGet - for legacy 8051 emits code to get a byte into */
8844 /* A through a pointer register (R0, R1, or DPTR). The original */
8845 /* value of A can be preserved in B. */
8846 /* PIC has to use INDF register. */
8847 /*-----------------------------------------------------------------*/
8849 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
8857 pic14_emitcode ("mov", "b,a");
8858 // pic14_emitcode ("mov", "a,@%s", rname);
8859 emitpcode(POC_MOVFW, popCopyReg(&pc_indf));
8864 pic14_emitcode ("mov", "b,a");
8865 pic14_emitcode ("movx", "a,@%s", rname);
8870 pic14_emitcode ("mov", "b,a");
8871 pic14_emitcode ("movx", "a,@dptr");
8876 pic14_emitcode ("mov", "b,a");
8877 pic14_emitcode ("clr", "a");
8878 pic14_emitcode ("movc", "a,@a+dptr");
8884 pic14_emitcode ("push", "b");
8885 pic14_emitcode ("push", "acc");
8887 pic14_emitcode ("lcall", "__gptrget");
8889 pic14_emitcode ("pop", "b");
8894 /*-----------------------------------------------------------------*/
8895 /* emitPtrByteSet - emits code to set a byte from src through a */
8896 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR). */
8897 /*-----------------------------------------------------------------*/
8899 emitPtrByteSet (char *rname, int p_type, char *src)
8909 pic14_emitcode ("mov", "@%s,a", rname);
8912 // pic14_emitcode ("mov", "@%s,%s", rname, src);
8913 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8918 pic14_emitcode ("movx", "@%s,a", rname);
8923 pic14_emitcode ("movx", "@dptr,a");
8928 pic14_emitcode ("lcall", "__gptrput");
8933 /*-----------------------------------------------------------------*/
8934 /* genPackBits - generates code for packed bit storage */
8935 /*-----------------------------------------------------------------*/
8936 static void genPackBits(sym_link *etype,operand *result,operand *right,char *rname,int p_type)
8938 int offset = 0; /* source byte offset */
8939 int rlen = 0; /* remaining bitfield length */
8940 int blen; /* bitfield length */
8941 int bstr; /* bitfield starting bit within byte */
8942 int litval; /* source literal value (if AOP_LIT) */
8943 unsigned char mask; /* bitmask within current byte */
8946 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8948 blen = SPEC_BLEN (etype);
8949 bstr = SPEC_BSTR (etype);
8951 /* If the bitfield length is less than a byte */
8954 mask = ((unsigned char) (0xFF << (blen + bstr)) |
8955 (unsigned char) (0xFF >> (8 - bstr)));
8957 if (AOP_TYPE (right) == AOP_LIT)
8959 /* Case with a bitfield length <8 and literal source
8961 int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8965 if (AOP(result)->type == AOP_PCODE)
8966 pcop = newpCodeOpBit(AOP(result)->aopu.pcop->name,bstr,0);
8968 pcop = popGet(AOP(result),0);
8969 emitpcode(lit?POC_BSF:POC_BCF,pcop);
8971 emitpcode(lit?POC_BSF:POC_BCF,popCopyReg(&pc_indf));
8975 litval = lit << bstr;
8976 litval &= (~mask) & 0xff;
8978 emitpcode(POC_MOVFW,popGet(AOP(result),0));
8980 emitPtrByteGet (rname, p_type, FALSE);
8981 if ((mask|litval)!=0xff)
8982 emitpcode(POC_ANDLW,popGetLit(mask));
8984 emitpcode(POC_IORLW,popGetLit(litval));
8991 /* Note more efficient code, of pre clearing bit then only setting it if required, can only be done if it is known that the result is not a SFR */
8992 emitpcode(POC_RLF,popGet(AOP(right),0));
8994 emitpcode(POC_BCF,popGet(AOP(result),0));
8996 emitpcode(POC_BSF,popGet(AOP(result),0));
8997 } else if (p_type!=GPOINTER) {
8998 /* Case with a bitfield length == 1 and no generic pointer
9000 if (AOP_TYPE (right) == AOP_CRY)
9001 pic14_emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9004 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
9005 pic14_emitcode ("rrc","a");
9007 emitPtrByteGet (rname, p_type, FALSE);
9008 pic14_emitcode ("mov","acc.%d,c",bstr);
9014 /* Case with a bitfield length < 8 and arbitrary source
9016 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
9017 /* shift and mask source value */
9018 AccLsh (right,0,bstr);
9019 pic14_emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9020 emitpcode(POC_ANDLW, popGetLit((~mask) & 0xff));
9022 //pushedB = pushB ();
9024 emitpcode(POC_MOVFW,popGet(AOP(result),0));
9026 emitPtrByteGet (rname, p_type, TRUE);
9028 pic14_emitcode ("anl", "a,#0x%02x", mask);
9029 pic14_emitcode ("orl", "a,b");
9030 emitpcode(POC_ANDLW,popGetLit(mask));
9031 emitpcode(POC_IORFW,popGet(AOP(right),0));
9032 if (p_type == GPOINTER)
9033 pic14_emitcode ("pop", "b");
9040 emitpcode(POC_MOVWF,popGet(AOP(result),0));
9042 emitPtrByteSet (rname, p_type, "a");
9046 /* Bit length is greater than 7 bits. In this case, copy */
9047 /* all except the partial byte at the end */
9048 for (rlen=blen;rlen>=8;rlen-=8)
9050 emitPtrByteSet (rname, p_type,
9051 aopGet (AOP (right), offset++, FALSE, TRUE) );
9053 pic14_emitcode ("inc", "%s", rname);
9056 /* If there was a partial byte at the end */
9059 mask = (((unsigned char) -1 << rlen) & 0xff);
9061 if (AOP_TYPE (right) == AOP_LIT)
9063 /* Case with partial byte and literal source
9065 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9066 litval >>= (blen-rlen);
9067 litval &= (~mask) & 0xff;
9068 emitPtrByteGet (rname, p_type, FALSE);
9069 if ((mask|litval)!=0xff)
9070 pic14_emitcode ("anl","a,#0x%02x", mask);
9072 pic14_emitcode ("orl","a,#0x%02x", litval);
9077 /* Case with partial byte and arbitrary source
9079 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
9080 pic14_emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9082 //pushedB = pushB ();
9083 /* transfer A to B and get next byte */
9084 emitPtrByteGet (rname, p_type, TRUE);
9086 pic14_emitcode ("anl", "a,#0x%02x", mask);
9087 pic14_emitcode ("orl", "a,b");
9088 if (p_type == GPOINTER)
9089 pic14_emitcode ("pop", "b");
9093 emitPtrByteSet (rname, p_type, "a");
9098 /*-----------------------------------------------------------------*/
9099 /* SetIrp - Set IRP bit */
9100 /*-----------------------------------------------------------------*/
9101 void SetIrp(operand *result) {
9103 if (AOP_TYPE(result) == AOP_LIT) {
9104 unsigned lit = (unsigned)operandLitValue(result);
9105 emitpcode((lit&0x100)?POC_BSF:POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
9107 if (PCOP(AOP(result))->type == PO_LITERAL) {
9108 int addrs = PCOL(AOP(result))->lit;
9109 emitpcode((addrs&0x100)?POC_BSF:POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
9111 emitpcode(POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT)); /* always ensure this is clear as it may have previouly been set */
9112 if(AOP_SIZE(result) > 1) {
9113 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
9114 emitpcode(POC_BSF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
9120 /*-----------------------------------------------------------------*/
9121 /* genDataPointerSet - remat pointer to data space */
9122 /*-----------------------------------------------------------------*/
9123 static void genDataPointerSet(operand *right,
9127 int size, offset = 0 ;
9128 char *l, buffer[256];
9131 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9132 aopOp(right,ic,FALSE);
9134 l = aopGet(AOP(result),0,FALSE,TRUE);
9135 size = AOP_SIZE(right);
9137 if ( AOP_TYPE(result) == AOP_PCODE) {
9138 fprintf(stderr,"genDataPointerSet %s, %d\n",
9139 AOP(result)->aopu.pcop->name,
9140 PCOI(AOP(result)->aopu.pcop)->offset);
9144 // tsd, was l+1 - the underline `_' prefix was being stripped
9146 emitpComment ("%s:%u: size=%i, offset=%i", __FILE__,__LINE__, size, offset);
9148 sprintf(buffer,"(%s + %d)",l,offset);
9149 fprintf(stderr,"%s:%i: oops %s (%i, AOP_LIT=%i)\n",__FILE__,__LINE__,buffer, AOP_TYPE(right), AOP_LIT);
9151 sprintf(buffer,"%s",l);
9153 if (AOP_TYPE(right) == AOP_LIT) {
9154 unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9155 lit = lit >> (8*offset);
9157 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9158 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9160 emitpcode(POC_CLRF, popGet(AOP(result),offset));
9163 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9164 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9170 freeAsmop(right,NULL,ic,TRUE);
9171 freeAsmop(result,NULL,ic,TRUE);
9174 /*-----------------------------------------------------------------*/
9175 /* genNearPointerSet - pic14_emitcode for near pointer put */
9176 /*-----------------------------------------------------------------*/
9177 static void genNearPointerSet (operand *right,
9182 sym_link *ptype = operandType(result);
9183 sym_link *retype = getSpec(operandType(right));
9184 sym_link *letype = getSpec(ptype);
9189 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9190 aopOp(result,ic,FALSE);
9193 /* if the result is rematerializable &
9194 in data space & not a bit variable */
9195 //if (AOP_TYPE(result) == AOP_IMMD &&
9196 if (AOP_TYPE(result) == AOP_PCODE &&
9197 DCL_TYPE(ptype) == POINTER &&
9198 !IS_BITVAR (retype) &&
9199 !IS_BITVAR (letype)) {
9200 genDataPointerSet (right,result,ic);
9201 freeAsmop(result,NULL,ic,TRUE);
9205 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9206 aopOp(right,ic,FALSE);
9207 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9209 /* Check if can access directly instead of via a pointer */
9210 if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9214 /* If the pointer value is not in a the FSR then need to put it in */
9215 if (!AOP_INPREG(AOP(result)) && !direct) {
9216 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9217 if (PCOP(AOP(result))->type == PO_LITERAL)
9218 emitpcode(POC_MOVLW, popGet(AOP(result),0));
9220 emitpcode(POC_MOVFW, popGet(AOP(result),0));
9221 emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
9224 /* Must set/reset IRP bit for use with FSR. */
9225 /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9229 /* if bitfield then unpack the bits */
9230 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9231 genPackBits ((IS_BITFIELD (retype) ? retype : letype), result, right, "indf", direct?-1:POINTER);
9233 /* we have can just get the values */
9234 int size = AOP_SIZE(right);
9237 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9239 char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9241 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9243 if (AOP_TYPE(right) == AOP_LIT) {
9244 emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9246 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9249 emitpcode(POC_MOVWF,popGet(AOP(result),0));
9251 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9253 if (size && !direct)
9254 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9259 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9260 /* now some housekeeping stuff */
9262 /* we had to allocate for this iCode */
9263 freeAsmop(NULL,aop,ic,TRUE);
9265 /* we did not allocate which means left
9266 already in a pointer register, then
9267 if size > 0 && this could be used again
9268 we have to point it back to where it
9270 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9271 if (AOP_SIZE(right) > 1 &&
9272 !OP_SYMBOL(result)->remat &&
9273 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9275 int size = AOP_SIZE(right) - 1;
9277 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9281 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9284 freeAsmop(right,NULL,ic,TRUE);
9285 freeAsmop(result,NULL,ic,TRUE);
9288 /*-----------------------------------------------------------------*/
9289 /* genPagedPointerSet - pic14_emitcode for Paged pointer put */
9290 /*-----------------------------------------------------------------*/
9291 static void genPagedPointerSet (operand *right,
9301 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9303 retype= getSpec(operandType(right));
9305 aopOp(result,ic,FALSE);
9307 /* if the value is already in a pointer register
9308 then don't need anything more */
9309 if (!AOP_INPREG(AOP(result))) {
9310 /* otherwise get a free pointer register */
9312 preg = getFreePtr(ic,&aop,FALSE);
9313 pic14_emitcode("mov","%s,%s",
9315 aopGet(AOP(result),0,FALSE,TRUE));
9316 rname = preg->name ;
9318 rname = aopGet(AOP(result),0,FALSE,FALSE);
9320 freeAsmop(result,NULL,ic,TRUE);
9321 aopOp (right,ic,FALSE);
9323 /* if bitfield then unpack the bits */
9324 if (IS_BITFIELD(retype))
9325 genPackBits (retype,result,right,rname,PPOINTER);
9327 /* we have can just get the values */
9328 int size = AOP_SIZE(right);
9332 l = aopGet(AOP(right),offset,FALSE,TRUE);
9335 pic14_emitcode("movx","@%s,a",rname);
9338 pic14_emitcode("inc","%s",rname);
9344 /* now some housekeeping stuff */
9346 /* we had to allocate for this iCode */
9347 freeAsmop(NULL,aop,ic,TRUE);
9349 /* we did not allocate which means left
9350 already in a pointer register, then
9351 if size > 0 && this could be used again
9352 we have to point it back to where it
9354 if (AOP_SIZE(right) > 1 &&
9355 !OP_SYMBOL(result)->remat &&
9356 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9358 int size = AOP_SIZE(right) - 1;
9360 pic14_emitcode("dec","%s",rname);
9365 freeAsmop(right,NULL,ic,TRUE);
9370 /*-----------------------------------------------------------------*/
9371 /* genFarPointerSet - set value from far space */
9372 /*-----------------------------------------------------------------*/
9373 static void genFarPointerSet (operand *right,
9374 operand *result, iCode *ic)
9377 sym_link *retype = getSpec(operandType(right));
9380 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9381 aopOp(result,ic,FALSE);
9383 /* if the operand is already in dptr
9384 then we do nothing else we move the value to dptr */
9385 if (AOP_TYPE(result) != AOP_STR) {
9386 /* if this is remateriazable */
9387 if (AOP_TYPE(result) == AOP_IMMD)
9388 pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9389 else { /* we need to get it byte by byte */
9390 pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9391 pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9392 if (options.model == MODEL_FLAT24)
9394 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9398 /* so dptr know contains the address */
9399 freeAsmop(result,NULL,ic,TRUE);
9400 aopOp(right,ic,FALSE);
9402 /* if bit then unpack */
9403 if (IS_BITFIELD(retype))
9404 genPackBits(retype,result,right,"dptr",FPOINTER);
9406 size = AOP_SIZE(right);
9410 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9412 pic14_emitcode("movx","@dptr,a");
9414 pic14_emitcode("inc","dptr");
9418 freeAsmop(right,NULL,ic,TRUE);
9421 /*-----------------------------------------------------------------*/
9422 /* genGenPointerSet - set value from generic pointer space */
9423 /*-----------------------------------------------------------------*/
9424 static void genGenPointerSet (operand *right,
9425 operand *result, iCode *ic)
9427 sym_link *ptype = operandType(result);
9428 sym_link *retype = getSpec(operandType(right));
9429 sym_link *letype = getSpec (ptype);
9432 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9434 aopOp(result,ic,FALSE);
9435 aopOp(right,ic,FALSE);
9437 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9439 /* if the operand is already in dptr
9440 then we do nothing else we move the value to dptr */
9441 if (AOP_TYPE(result) != AOP_STR) {
9442 /* if this is remateriazable */
9443 if (AOP_TYPE(result) == AOP_IMMD) {
9444 pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9445 pic14_emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
9448 emitpcode(POC_MOVFW,popGet(AOP(result),0));
9449 emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
9451 /* Must set/reset IRP bit for use with FSR. */
9452 /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9457 /* if bitfield then unpack the bits */
9458 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9459 genPackBits ((IS_BITFIELD (retype) ? retype : letype),result, right, "indf", POINTER);
9461 /* we have can just get the values */
9462 int size = AOP_SIZE(right);
9465 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9467 char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9469 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9471 if (AOP_TYPE(right) == AOP_LIT) {
9472 emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9474 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9476 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9479 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9484 freeAsmop(right,NULL,ic,TRUE);
9485 freeAsmop(result,NULL,ic,TRUE);
9488 /*-----------------------------------------------------------------*/
9489 /* genPointerSet - stores the value into a pointer location */
9490 /*-----------------------------------------------------------------*/
9491 static void genPointerSet (iCode *ic)
9493 operand *right, *result ;
9494 sym_link *type, *etype;
9498 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9500 right = IC_RIGHT(ic);
9501 result = IC_RESULT(ic) ;
9503 /* depending on the type of pointer we need to
9504 move it to the correct pointer register */
9505 type = operandType(result);
9506 etype = getSpec(type);
9507 /* if left is of type of pointer then it is simple */
9508 if (IS_PTR(type) && !IS_FUNC(type->next)) {
9509 p_type = DCL_TYPE(type);
9512 /* we have to go by the storage class */
9513 p_type = PTR_TYPE(SPEC_OCLS(etype));
9515 /* if (SPEC_OCLS(etype)->codesp ) { */
9516 /* p_type = CPOINTER ; */
9519 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9520 /* p_type = FPOINTER ; */
9522 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9523 /* p_type = PPOINTER ; */
9525 /* if (SPEC_OCLS(etype) == idata ) */
9526 /* p_type = IPOINTER ; */
9528 /* p_type = POINTER ; */
9531 /* now that we have the pointer type we assign
9532 the pointer values */
9537 genNearPointerSet (right,result,ic);
9541 genPagedPointerSet (right,result,ic);
9545 genFarPointerSet (right,result,ic);
9549 genGenPointerSet (right,result,ic);
9553 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9554 "genPointerSet: illegal pointer type");
9558 /*-----------------------------------------------------------------*/
9559 /* genIfx - generate code for Ifx statement */
9560 /*-----------------------------------------------------------------*/
9561 static void genIfx (iCode *ic, iCode *popIc)
9563 operand *cond = IC_COND(ic);
9567 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9569 aopOp(cond,ic,FALSE);
9571 /* get the value into acc */
9572 if (AOP_TYPE(cond) != AOP_CRY)
9573 pic14_toBoolean(cond);
9576 /* the result is now in the accumulator */
9577 freeAsmop(cond,NULL,ic,TRUE);
9579 /* if there was something to be popped then do it */
9583 /* if the condition is a bit variable */
9584 if (isbit && IS_ITEMP(cond) &&
9586 genIfxJump(ic,SPIL_LOC(cond)->rname);
9587 DEBUGpic14_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9590 if (isbit && !IS_ITEMP(cond))
9591 genIfxJump(ic,OP_SYMBOL(cond)->rname);
9599 /*-----------------------------------------------------------------*/
9600 /* genAddrOf - generates code for address of */
9601 /*-----------------------------------------------------------------*/
9602 static void genAddrOf (iCode *ic)
9604 operand *right, *result, *left;
9608 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9611 //aopOp(IC_RESULT(ic),ic,FALSE);
9613 aopOp((left=IC_LEFT(ic)),ic,FALSE);
9614 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9615 aopOp((result=IC_RESULT(ic)),ic,TRUE);
9617 DEBUGpic14_AopType(__LINE__,left,right,result);
9618 assert (IS_SYMOP (left));
9620 /* sanity check: generic pointers to code space are not yet supported,
9621 * pionters to codespace must not be assigned addresses of __data values. */
9623 fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9624 fprintf (stderr, "result->type : "); printTypeChain (OP_SYM_TYPE(result), stderr); fprintf (stderr, ", codesp:%d, codeptr:%d, constptr:%d\n", IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(result)))), IS_CODEPTR(OP_SYM_TYPE(result)), IS_PTR_CONST(OP_SYM_TYPE(result)));
9625 fprintf (stderr, "result->etype: "); printTypeChain (OP_SYM_ETYPE(result), stderr); fprintf (stderr, ", codesp:%d, codeptr:%d, constptr:%d\n", IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_ETYPE(result)))), IS_CODEPTR(OP_SYM_ETYPE(result)), IS_PTR_CONST(OP_SYM_ETYPE(result)));
9626 fprintf (stderr, "left->type : "); printTypeChain (OP_SYM_TYPE(left), stderr); fprintf (stderr, ", codesp:%d, codeptr:%d, constptr:%d\n", IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left)))), IS_CODEPTR(OP_SYM_TYPE(left)), IS_PTR_CONST(OP_SYM_TYPE(left)));
9627 fprintf (stderr, "left->etype : "); printTypeChain (OP_SYM_ETYPE(left), stderr); fprintf (stderr, ", codesp:%d, codeptr:%d, constptr:%d\n",IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_ETYPE(left)))), IS_CODEPTR(OP_SYM_ETYPE(left)), IS_PTR_CONST(OP_SYM_ETYPE(left)));
9630 if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9631 fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9632 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9633 OP_SYMBOL(left)->name);
9634 } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9635 fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9636 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9637 OP_SYMBOL(left)->name);
9640 size = AOP_SIZE(IC_RESULT(ic));
9644 /* fixing bug #863624, reported from (errolv) */
9645 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9646 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9649 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9650 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9655 freeAsmop(left,NULL,ic,FALSE);
9656 freeAsmop(result,NULL,ic,TRUE);
9661 /*-----------------------------------------------------------------*/
9662 /* genFarFarAssign - assignment when both are in far space */
9663 /*-----------------------------------------------------------------*/
9664 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9666 int size = AOP_SIZE(right);
9669 /* first push the right side on to the stack */
9671 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9673 pic14_emitcode ("push","acc");
9676 freeAsmop(right,NULL,ic,FALSE);
9677 /* now assign DPTR to result */
9678 aopOp(result,ic,FALSE);
9679 size = AOP_SIZE(result);
9681 pic14_emitcode ("pop","acc");
9682 aopPut(AOP(result),"a",--offset);
9684 freeAsmop(result,NULL,ic,FALSE);
9689 /*-----------------------------------------------------------------*/
9690 /* genAssign - generate code for assignment */
9691 /*-----------------------------------------------------------------*/
9692 static void genAssign (iCode *ic)
9694 operand *result, *right;
9695 int size, offset,know_W;
9696 unsigned long lit = 0L;
9698 result = IC_RESULT(ic);
9699 right = IC_RIGHT(ic) ;
9702 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9704 /* if they are the same */
9705 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9708 aopOp(right,ic,FALSE);
9709 aopOp(result,ic,TRUE);
9711 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9713 /* if they are the same registers */
9714 if (pic14_sameRegs(AOP(right),AOP(result)))
9717 /* special case: assign from __code */
9718 if (!IS_ITEMP(right) /* --> iTemps never reside in __code */
9719 && IS_SYMOP (right) /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
9720 && !IS_FUNC(OP_SYM_TYPE(right)) /* --> we would want its address instead of the first instruction */
9721 && !IS_CODEPTR(OP_SYM_TYPE(right)) /* --> get symbols address instread */
9722 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
9724 emitpComment ("genAssign from CODESPACE");
9725 genConstPointerGet (right, result, ic);
9729 /* just for symmetry reasons... */
9730 if (!IS_ITEMP(result)
9731 && IS_SYMOP (result)
9732 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
9734 assert ( !"cannot write to CODESPACE" );
9737 /* if the result is a bit */
9738 if (AOP_TYPE(result) == AOP_CRY) {
9740 /* if the right size is a literal then
9741 we know what the value is */
9742 if (AOP_TYPE(right) == AOP_LIT) {
9744 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9745 popGet(AOP(result),0));
9747 if (((int) operandLitValue(right)))
9748 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9749 AOP(result)->aopu.aop_dir,
9750 AOP(result)->aopu.aop_dir);
9752 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9753 AOP(result)->aopu.aop_dir,
9754 AOP(result)->aopu.aop_dir);
9758 /* the right is also a bit variable */
9759 if (AOP_TYPE(right) == AOP_CRY) {
9760 emitpcode(POC_BCF, popGet(AOP(result),0));
9761 emitpcode(POC_BTFSC, popGet(AOP(right),0));
9762 emitpcode(POC_BSF, popGet(AOP(result),0));
9764 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9765 AOP(result)->aopu.aop_dir,
9766 AOP(result)->aopu.aop_dir);
9767 pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
9768 AOP(right)->aopu.aop_dir,
9769 AOP(right)->aopu.aop_dir);
9770 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9771 AOP(result)->aopu.aop_dir,
9772 AOP(result)->aopu.aop_dir);
9777 emitpcode(POC_BCF, popGet(AOP(result),0));
9778 pic14_toBoolean(right);
9780 emitpcode(POC_BSF, popGet(AOP(result),0));
9781 //aopPut(AOP(result),"a",0);
9785 /* bit variables done */
9787 size = AOP_SIZE(result);
9789 if(AOP_TYPE(right) == AOP_LIT)
9790 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9792 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
9793 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9794 if(aopIdx(AOP(result),0) == 4) {
9795 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9796 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9797 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9800 DEBUGpic14_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
9805 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9806 if(AOP_TYPE(right) == AOP_LIT) {
9808 if(know_W != (int)(lit&0xff))
9809 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
9811 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9813 emitpcode(POC_CLRF, popGet(AOP(result),offset));
9817 } else if (AOP_TYPE(right) == AOP_CRY) {
9818 emitpcode(POC_CLRF, popGet(AOP(result),offset));
9820 emitpcode(POC_BTFSS, popGet(AOP(right),0));
9821 emitpcode(POC_INCF, popGet(AOP(result),0));
9824 mov2w (AOP(right), offset);
9825 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9833 freeAsmop (right,NULL,ic,FALSE);
9834 freeAsmop (result,NULL,ic,TRUE);
9837 /*-----------------------------------------------------------------*/
9838 /* genJumpTab - genrates code for jump table */
9839 /*-----------------------------------------------------------------*/
9840 static void genJumpTab (iCode *ic)
9846 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9848 aopOp(IC_JTCOND(ic),ic,FALSE);
9849 /* get the condition into accumulator */
9850 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9852 /* multiply by three */
9853 pic14_emitcode("add","a,acc");
9854 pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9856 jtab = newiTempLabel(NULL);
9857 pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9858 pic14_emitcode("jmp","@a+dptr");
9859 pic14_emitcode("","%05d_DS_:",jtab->key+100);
9861 emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
9862 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
9863 emitpcode(POC_MOVLW, popGetLabel(jtab->key));
9864 emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
9866 emitpcode(POC_INCF, popCopyReg(&pc_pclath));
9867 emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
9868 emitpLabel(jtab->key);
9870 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9872 /* now generate the jump labels */
9873 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9874 jtab = setNextItem(IC_JTLABELS(ic))) {
9875 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
9876 emitpcode(POC_GOTO,popGetLabel(jtab->key));
9882 /*-----------------------------------------------------------------*/
9883 /* genMixedOperation - gen code for operators between mixed types */
9884 /*-----------------------------------------------------------------*/
9886 TSD - Written for the PIC port - but this unfortunately is buggy.
9887 This routine is good in that it is able to efficiently promote
9888 types to different (larger) sizes. Unfortunately, the temporary
9889 variables that are optimized out by this routine are sometimes
9890 used in other places. So until I know how to really parse the
9891 iCode tree, I'm going to not be using this routine :(.
9893 static int genMixedOperation (iCode *ic)
9897 operand *result = IC_RESULT(ic);
9898 sym_link *ctype = operandType(IC_LEFT(ic));
9899 operand *right = IC_RIGHT(ic);
9905 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9907 pic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
9913 nextright = IC_RIGHT(nextic);
9914 nextleft = IC_LEFT(nextic);
9915 nextresult = IC_RESULT(nextic);
9917 aopOp(right,ic,FALSE);
9918 aopOp(result,ic,FALSE);
9919 aopOp(nextright, nextic, FALSE);
9920 aopOp(nextleft, nextic, FALSE);
9921 aopOp(nextresult, nextic, FALSE);
9923 if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9929 pic14_emitcode(";remove right +","");
9931 } else if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9937 pic14_emitcode(";remove left +","");
9941 big = AOP_SIZE(nextleft);
9942 small = AOP_SIZE(nextright);
9944 switch(nextic->op) {
9947 pic14_emitcode(";optimize a +","");
9948 /* if unsigned or not an integral type */
9949 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9950 pic14_emitcode(";add a bit to something","");
9953 pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9955 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9956 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9957 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9959 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9967 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9968 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9969 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9972 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9974 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
9975 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9976 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9977 pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9978 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9981 pic14_emitcode("rlf","known_zero,w");
9988 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9989 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9990 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9992 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10002 freeAsmop(right,NULL,ic,TRUE);
10003 freeAsmop(result,NULL,ic,TRUE);
10004 freeAsmop(nextright,NULL,ic,TRUE);
10005 freeAsmop(nextleft,NULL,ic,TRUE);
10007 nextic->generated = 1;
10014 /*-----------------------------------------------------------------*/
10015 /* genCast - gen code for casting */
10016 /*-----------------------------------------------------------------*/
10017 static void genCast (iCode *ic)
10019 operand *result = IC_RESULT(ic);
10020 sym_link *ctype = operandType(IC_LEFT(ic));
10021 sym_link *rtype = operandType(IC_RIGHT(ic));
10022 operand *right = IC_RIGHT(ic);
10026 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10027 /* if they are equivalent then do nothing */
10028 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10031 aopOp(right,ic,FALSE) ;
10032 aopOp(result,ic,FALSE);
10034 DEBUGpic14_AopType(__LINE__,NULL,right,result);
10036 /* if the result is a bit */
10037 if (AOP_TYPE(result) == AOP_CRY) {
10038 /* if the right size is a literal then
10039 we know what the value is */
10040 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10041 if (AOP_TYPE(right) == AOP_LIT) {
10043 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10044 popGet(AOP(result),0));
10046 if (((int) operandLitValue(right)))
10047 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
10048 AOP(result)->aopu.aop_dir,
10049 AOP(result)->aopu.aop_dir);
10051 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
10052 AOP(result)->aopu.aop_dir,
10053 AOP(result)->aopu.aop_dir);
10058 /* the right is also a bit variable */
10059 if (AOP_TYPE(right) == AOP_CRY) {
10062 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10064 pic14_emitcode("clrc","");
10065 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10066 AOP(right)->aopu.aop_dir,
10067 AOP(right)->aopu.aop_dir);
10068 aopPut(AOP(result),"c",0);
10072 /* we need to or */
10073 if (AOP_TYPE(right) == AOP_REG) {
10074 emitpcode(POC_BCF, popGet(AOP(result),0));
10075 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
10076 emitpcode(POC_BSF, popGet(AOP(result),0));
10078 pic14_toBoolean(right);
10079 aopPut(AOP(result),"a",0);
10083 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10085 size = AOP_SIZE(result);
10087 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10089 emitpcode(POC_CLRF, popGet(AOP(result),0));
10090 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10091 emitpcode(POC_INCF, popGet(AOP(result),0));
10094 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
10099 /* if they are the same size : or less */
10100 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10102 /* if they are in the same place */
10103 if (pic14_sameRegs(AOP(right),AOP(result)))
10106 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10107 if (IS_PTR_CONST(rtype))
10108 DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10109 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10110 DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10112 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10113 emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10114 emitpcode(POC_MOVWF, popGet(AOP(result),0));
10115 emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10116 emitpcode(POC_MOVWF, popGet(AOP(result),1));
10117 if(AOP_SIZE(result) <2)
10118 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10122 /* if they in different places then copy */
10123 size = AOP_SIZE(result);
10126 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10127 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10129 //aopPut(AOP(result),
10130 // aopGet(AOP(right),offset,FALSE,FALSE),
10140 /* if the result is of type pointer */
10141 if (IS_PTR(ctype)) {
10144 sym_link *type = operandType(right);
10145 sym_link *etype = getSpec(type);
10146 DEBUGpic14_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
10148 /* pointer to generic pointer */
10149 if (IS_GENPTR(ctype)) {
10153 p_type = DCL_TYPE(type);
10155 /* we have to go by the storage class */
10156 p_type = PTR_TYPE(SPEC_OCLS(etype));
10158 /* if (SPEC_OCLS(etype)->codesp ) */
10159 /* p_type = CPOINTER ; */
10161 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10162 /* p_type = FPOINTER ; */
10164 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10165 /* p_type = PPOINTER; */
10167 /* if (SPEC_OCLS(etype) == idata ) */
10168 /* p_type = IPOINTER ; */
10170 /* p_type = POINTER ; */
10173 /* the first two bytes are known */
10174 DEBUGpic14_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
10175 size = GPTRSIZE - 1;
10178 if(offset < AOP_SIZE(right)) {
10179 DEBUGpic14_emitcode("; ***","%s %d - pointer cast3",__FUNCTION__,__LINE__);
10180 if ((AOP_TYPE(right) == AOP_PCODE) &&
10181 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10182 emitpcode(POC_MOVLW, popGetAddr(AOP(right),offset,0));
10183 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10185 aopPut(AOP(result),
10186 aopGet(AOP(right),offset,FALSE,FALSE),
10190 emitpcode(POC_CLRF,popGet(AOP(result),offset));
10193 /* the last byte depending on type */
10197 emitpcode(POC_CLRF,popGet(AOP(result),GPTRSIZE - 1));
10200 pic14_emitcode(";BUG!? ","%d",__LINE__);
10204 pic14_emitcode(";BUG!? ","%d",__LINE__);
10208 pic14_emitcode(";BUG!? ","%d",__LINE__);
10213 /* this should never happen */
10214 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10215 "got unknown pointer type");
10218 //aopPut(AOP(result),l, GPTRSIZE - 1);
10222 /* just copy the pointers */
10223 size = AOP_SIZE(result);
10226 aopPut(AOP(result),
10227 aopGet(AOP(right),offset,FALSE,FALSE),
10236 /* so we now know that the size of destination is greater
10237 than the size of the source.
10238 Now, if the next iCode is an operator then we might be
10239 able to optimize the operation without performing a cast.
10241 if(genMixedOperation(ic))
10244 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10246 /* we move to result for the size of source */
10247 size = AOP_SIZE(right);
10250 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10251 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10255 /* now depending on the sign of the destination */
10256 size = AOP_SIZE(result) - AOP_SIZE(right);
10257 /* if unsigned or not an integral type */
10258 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
10260 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
10262 /* we need to extend the sign :{ */
10265 /* Save one instruction of casting char to int */
10266 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10267 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10268 emitpcode(POC_DECF, popGet(AOP(result),offset));
10270 emitpcodeNULLop(POC_CLRW);
10273 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10275 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),offset,FALSE,FALSE),7,0));
10277 emitpcode(POC_MOVLW, popGetLit(0xff));
10280 emitpcode(POC_MOVWF, popGet(AOP(result),offset++));
10285 freeAsmop(right,NULL,ic,TRUE);
10286 freeAsmop(result,NULL,ic,TRUE);
10290 /*-----------------------------------------------------------------*/
10291 /* genDjnz - generate decrement & jump if not zero instrucion */
10292 /*-----------------------------------------------------------------*/
10293 static int genDjnz (iCode *ic, iCode *ifx)
10295 symbol *lbl, *lbl1;
10297 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10302 /* if the if condition has a false label
10303 then we cannot save */
10307 /* if the minus is not of the form
10309 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10310 !IS_OP_LITERAL(IC_RIGHT(ic)))
10313 if (operandLitValue(IC_RIGHT(ic)) != 1)
10316 /* if the size of this greater than one then no
10318 if (getSize(operandType(IC_RESULT(ic))) > 1)
10321 /* otherwise we can save BIG */
10322 lbl = newiTempLabel(NULL);
10323 lbl1= newiTempLabel(NULL);
10325 aopOp(IC_RESULT(ic),ic,FALSE);
10327 if (IS_AOP_PREG(IC_RESULT(ic))) {
10328 pic14_emitcode("dec","%s",
10329 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10330 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10331 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10335 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10336 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10338 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10339 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10342 /* pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10343 /* pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10344 /* pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10345 /* pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10348 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10349 ifx->generated = 1;
10353 /*-----------------------------------------------------------------*/
10354 /* genReceive - generate code for a receive iCode */
10355 /*-----------------------------------------------------------------*/
10356 static void genReceive (iCode *ic)
10359 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10361 if (isOperandInFarSpace(IC_RESULT(ic)) &&
10362 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10363 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10365 int size = getSize(operandType(IC_RESULT(ic)));
10366 int offset = fReturnSizePic - size;
10368 pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10369 fReturn[fReturnSizePic - offset - 1] : "acc"));
10372 aopOp(IC_RESULT(ic),ic,FALSE);
10373 size = AOP_SIZE(IC_RESULT(ic));
10376 pic14_emitcode ("pop","acc");
10377 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10382 aopOp(IC_RESULT(ic),ic,FALSE);
10384 assignResultValue(IC_RESULT(ic));
10387 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10390 /*-----------------------------------------------------------------*/
10391 /* genDummyRead - generate code for dummy read of volatiles */
10392 /*-----------------------------------------------------------------*/
10394 genDummyRead (iCode * ic)
10397 pic14_emitcode ("; genDummyRead","");
10398 pic14_emitcode ("; not implemented","");
10403 /*-----------------------------------------------------------------*/
10404 /* genpic14Code - generate code for pic14 based controllers */
10405 /*-----------------------------------------------------------------*/
10407 * At this point, ralloc.c has gone through the iCode and attempted
10408 * to optimize in a way suitable for a PIC. Now we've got to generate
10409 * PIC instructions that correspond to the iCode.
10411 * Once the instructions are generated, we'll pass through both the
10412 * peep hole optimizer and the pCode optimizer.
10413 *-----------------------------------------------------------------*/
10415 void genpic14Code (iCode *lic)
10422 lineHead = lineCurr = NULL;
10424 pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10427 /* if debug information required */
10428 if (options.debug && currFunc) {
10430 debugFile->writeFunction (currFunc, lic);
10435 for (ic = lic ; ic ; ic = ic->next ) {
10437 //DEBUGpic14_emitcode(";ic","");
10438 //fprintf (stderr, "in ic loop\n");
10439 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10440 //ic->lineno, printCLine(ic->filename, ic->lineno));
10442 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10444 //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10445 cline = printCLine (ic->filename, ic->lineno);
10446 if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10447 addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10448 //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10451 if (options.iCodeInAsm) {
10452 emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10454 /* if the result is marked as
10455 spilt and rematerializable or code for
10456 this has already been generated then
10458 if (resultRemat(ic) || ic->generated )
10461 /* depending on the operation */
10480 /* IPOP happens only when trying to restore a
10481 spilt live range, if there is an ifx statement
10482 following this pop then the if statement might
10483 be using some of the registers being popped which
10484 would destory the contents of the register so
10485 we need to check for this condition and handle it */
10487 ic->next->op == IFX &&
10488 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10489 genIfx (ic->next,ic);
10507 genEndFunction (ic);
10527 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10544 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
10548 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10555 /* note these two are xlated by algebraic equivalence
10556 during parsing SDCC.y */
10557 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10558 "got '>=' or '<=' shouldn't have come here");
10562 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10574 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10578 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10582 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10606 genRightShift (ic);
10609 case GET_VALUE_AT_ADDRESS:
10614 if (POINTER_SET(ic))
10641 addSet(&_G.sendSet,ic);
10644 case DUMMY_READ_VOLATILE:
10654 /* now we are ready to call the
10655 peep hole optimizer */
10656 if (!options.nopeep) {
10657 peepHole (&lineHead);
10659 /* now do the actual printing */
10660 printLine (lineHead,codeOutFile);
10663 DFPRINTF((stderr,"printing pBlock\n\n"));
10664 printpBlock(stdout,pb);
10671 aop_isLitLike (asmop *aop)
10674 if (aop->type == AOP_LIT) return 1;
10675 if (aop->type == AOP_IMMD) return 1;
10676 if ((aop->type == AOP_PCODE) &&
10677 ((aop->aopu.pcop->type == PO_LITERAL) || (aop->aopu.pcop->type == PO_IMMEDIATE)))
10679 /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10680 * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10687 op_isLitLike (operand *op)
10690 if (aop_isLitLike (AOP(op))) return 1;