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 = NULL; /* this is wrong: 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);
857 /* WREG is not usable as an ordinary operand with PIC architecture,
858 * one might introduce a scratch register that can be used to make
859 * WREG accesible as an operand... disable WREG for now */
862 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
863 aop->size = getSize(sym->type);
864 for ( i = 0 ; i < 2 ; i++ )
865 aop->aopu.aop_str[i] = accUse[i];
866 DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
872 if(sym->isptr) { // && sym->uptr
873 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
874 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
876 //PCOI(aop->aopu.pcop)->_const = 0;
877 //PCOI(aop->aopu.pcop)->index = 0;
879 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
880 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
882 //allocDirReg (IC_LEFT(ic));
884 aop->size = getSize(sym->type);
885 DEBUGpic14_emitcode(";","%d",__LINE__);
892 aop = op->aop = sym->aop = newAsmop(AOP_STR);
893 aop->size = getSize(sym->type);
894 for ( i = 0 ; i < fReturnSizePic ; i++ )
895 aop->aopu.aop_str[i] = fReturn[i];
897 DEBUGpic14_emitcode(";","%d",__LINE__);
902 /* else spill location */
903 if (sym->usl.spillLoc)
905 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
907 /* force a new aop if sizes differ */
908 sym->usl.spillLoc->aop = NULL;
910 DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
911 __FUNCTION__,__LINE__,
912 sym->usl.spillLoc->rname,
913 sym->rname, sym->usl.spillLoc->offset);
915 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
916 //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
917 aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname,
919 sym->usl.spillLoc->offset);
920 aop->size = getSize(sym->type);
927 sym_link *type = operandType(op);
928 if(IS_PTR_CONST(type))
929 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
932 /* must be in a register */
933 DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
934 sym->aop = op->aop = aop = newAsmop(AOP_REG);
935 aop->size = sym->nRegs;
936 for ( i = 0 ; i < sym->nRegs ;i++)
937 aop->aopu.aop_reg[i] = sym->regs[i];
940 /*-----------------------------------------------------------------*/
941 /* freeAsmop - free up the asmop given to an operand */
942 /*----------------------------------------------------------------*/
943 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
960 /* depending on the asmop type only three cases need work AOP_RO
961 , AOP_R1 && AOP_STK */
967 pic14_emitcode ("pop","ar0");
971 bitVectUnSetBit(ic->rUsed,R0_IDX);
977 pic14_emitcode ("pop","ar1");
981 bitVectUnSetBit(ic->rUsed,R1_IDX);
987 int stk = aop->aopu.aop_stk + aop->size;
988 bitVectUnSetBit(ic->rUsed,R0_IDX);
989 bitVectUnSetBit(ic->rUsed,R1_IDX);
991 getFreePtr(ic,&aop,FALSE);
993 if (options.stack10bit)
995 /* I'm not sure what to do here yet... */
998 "*** Warning: probably generating bad code for "
999 "10 bit stack mode.\n");
1003 pic14_emitcode ("mov","a,_bp");
1004 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1005 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1007 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1011 pic14_emitcode("pop","acc");
1012 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1014 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1017 freeAsmop(op,NULL,ic,TRUE);
1019 pic14_emitcode("pop","ar0");
1024 pic14_emitcode("pop","ar1");
1032 /* all other cases just dealloc */
1036 OP_SYMBOL(op)->aop = NULL;
1037 /* if the symbol has a spill */
1039 SPIL_LOC(op)->aop = NULL;
1044 /*-----------------------------------------------------------------*/
1045 /* aopGet - for fetching value of the aop */
1046 /*-----------------------------------------------------------------*/
1047 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1052 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1053 /* offset is greater than
1055 if (offset > (aop->size - 1) &&
1056 aop->type != AOP_LIT)
1059 /* depending on type */
1060 switch (aop->type) {
1064 DEBUGpic14_emitcode(";","%d",__LINE__);
1065 /* if we need to increment it */
1066 while (offset > aop->coff) {
1067 pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);
1071 while (offset < aop->coff) {
1072 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1076 aop->coff = offset ;
1078 pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1079 return (dname ? "acc" : "a");
1081 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1082 rs = Safe_calloc(1,strlen(s)+1);
1088 DEBUGpic14_emitcode(";","%d",__LINE__);
1089 if (aop->type == AOP_DPTR2)
1094 while (offset > aop->coff) {
1095 pic14_emitcode ("inc","dptr");
1099 while (offset < aop->coff) {
1100 pic14_emitcode("lcall","__decdptr");
1106 pic14_emitcode("clr","a");
1107 pic14_emitcode("movc","a,@a+dptr");
1110 pic14_emitcode("movx","a,@dptr");
1113 if (aop->type == AOP_DPTR2)
1118 return (dname ? "acc" : "a");
1123 sprintf (s,"%s",aop->aopu.aop_immd);
1126 sprintf(s,"(%s >> %d)",
1131 aop->aopu.aop_immd);
1132 DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1133 rs = Safe_calloc(1,strlen(s)+1);
1139 sprintf(s,"(%s + %d)",
1142 DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1144 sprintf(s,"%s",aop->aopu.aop_dir);
1145 rs = Safe_calloc(1,strlen(s)+1);
1151 // return aop->aopu.aop_reg[offset]->dname;
1153 return aop->aopu.aop_reg[offset]->name;
1156 //pic14_emitcode(";","%d",__LINE__);
1157 return aop->aopu.aop_dir;
1160 DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1161 return "AOP_accumulator_bug";
1164 sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1165 rs = Safe_calloc(1,strlen(s)+1);
1170 aop->coff = offset ;
1171 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1174 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1176 return aop->aopu.aop_str[offset];
1180 pCodeOp *pcop = aop->aopu.pcop;
1181 DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1184 DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
1185 sprintf(s,"(%s+%d)", pcop->name,offset);
1187 DEBUGpic14_emitcode(";","%s",pcop->name);
1188 sprintf(s,"%s", pcop->name);
1191 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1194 rs = Safe_calloc(1,strlen(s)+1);
1200 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1201 "aopget got unsupported aop->type");
1206 /*-----------------------------------------------------------------*/
1207 /* popGetTempReg - create a new temporary pCodeOp */
1208 /*-----------------------------------------------------------------*/
1209 pCodeOp *popGetTempReg(void)
1214 pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1215 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1216 PCOR(pcop)->r->wasUsed=1;
1217 PCOR(pcop)->r->isFree=0;
1223 /*-----------------------------------------------------------------*/
1224 /* popReleaseTempReg - create a new temporary pCodeOp */
1225 /*-----------------------------------------------------------------*/
1226 void popReleaseTempReg(pCodeOp *pcop)
1229 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1230 PCOR(pcop)->r->isFree = 1;
1233 /*-----------------------------------------------------------------*/
1234 /* popGetLabel - create a new pCodeOp of type PO_LABEL */
1235 /*-----------------------------------------------------------------*/
1236 pCodeOp *popGetLabel(unsigned int key)
1239 DEBUGpic14_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1241 if(key>(unsigned int)max_key)
1244 return newpCodeOpLabel(NULL,key+100+labelOffset);
1247 /*-------------------------------------------------------------------*/
1248 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1249 /*-------------------------------------------------------------------*/
1250 pCodeOp *popGetHighLabel(unsigned int key)
1253 pcop = popGetLabel(key);
1254 PCOLAB(pcop)->offset = 1;
1258 /*-----------------------------------------------------------------*/
1259 /* popGetLit - asm operator to pcode operator conversion */
1260 /*-----------------------------------------------------------------*/
1261 pCodeOp *popGetLit(unsigned int lit)
1264 return newpCodeOpLit(lit);
1267 /*-----------------------------------------------------------------*/
1268 /* popGetImmd - asm operator to pcode immediate conversion */
1269 /*-----------------------------------------------------------------*/
1270 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1273 return newpCodeOpImmd(name, offset,index, 0, is_func);
1277 /*-----------------------------------------------------------------*/
1278 /* popGetWithString - asm operator to pcode operator conversion */
1279 /*-----------------------------------------------------------------*/
1280 pCodeOp *popGetWithString(char *str, int isExtern)
1286 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1290 pcop = newpCodeOp(str,PO_STR);
1291 PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1296 /*-----------------------------------------------------------------*/
1297 /* popRegFromString - */
1298 /*-----------------------------------------------------------------*/
1299 pCodeOp *popRegFromString(char *str, int size, int offset)
1302 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1303 pcop->type = PO_DIR;
1305 DEBUGpic14_emitcode(";","%d",__LINE__);
1310 pcop->name = Safe_calloc(1,strlen(str)+1);
1311 strcpy(pcop->name,str);
1313 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1315 PCOR(pcop)->r = dirregWithName(pcop->name);
1316 if(PCOR(pcop)->r == NULL) {
1317 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1318 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1319 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1321 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1323 PCOR(pcop)->instance = offset;
1328 /*-----------------------------------------------------------------*/
1329 /*-----------------------------------------------------------------*/
1330 pCodeOp *popRegFromIdx(int rIdx)
1334 DEBUGpic14_emitcode ("; ***","%s,%d , rIdx=0x%x",
1335 __FUNCTION__,__LINE__,rIdx);
1337 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1339 PCOR(pcop)->rIdx = rIdx;
1340 PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1341 PCOR(pcop)->r->isFree = 0;
1342 PCOR(pcop)->r->wasUsed = 1;
1344 pcop->type = PCOR(pcop)->r->pc_type;
1350 /*-----------------------------------------------------------------*/
1351 /* popGet - asm operator to pcode operator conversion */
1352 /*-----------------------------------------------------------------*/
1353 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1355 //char *s = buffer ;
1360 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1361 /* offset is greater than
1364 if (!(offset >= 0 && ((offset < aop->size) || (aop->size == 0))))
1366 fprintf (stderr, "%s:%u: offset=%d, aop-type:%s, size:%d\n", __FILE__, __LINE__, offset, AopType (aop->type), aop->size);
1368 assert (offset >= 0 && ((offset < aop->size) || (aop->size == 0)));
1370 /* XXX: still needed for BIT operands (AOP_CRY) */
1371 if (offset > (aop->size - 1) &&
1372 aop->type != AOP_LIT)
1373 return NULL; //zero;
1375 /* depending on type */
1376 switch (aop->type) {
1383 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1387 DEBUGpic14_emitcode(";","%d",__LINE__);
1388 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1391 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1393 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1394 pcop->type = PO_DIR;
1396 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1397 strcpy(pcop->name,aop->aopu.aop_dir);
1398 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1399 if(PCOR(pcop)->r == NULL) {
1400 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1401 PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1402 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1404 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1406 PCOR(pcop)->instance = offset;
1413 int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1415 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1416 PCOR(pcop)->rIdx = rIdx;
1417 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1418 PCOR(pcop)->r->wasUsed=1;
1419 PCOR(pcop)->r->isFree=0;
1421 PCOR(pcop)->instance = offset;
1422 pcop->type = PCOR(pcop)->r->pc_type;
1423 //rs = aop->aopu.aop_reg[offset]->name;
1424 DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1429 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1430 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1431 //if(PCOR(pcop)->r == NULL)
1432 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1436 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1439 DEBUGpic14_emitcode(";","%d %s",__LINE__,aop->aopu.aop_str[offset]);
1440 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1442 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1443 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1444 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1445 pcop->type = PCOR(pcop)->r->pc_type;
1446 pcop->name = PCOR(pcop)->r->name;
1453 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1455 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1456 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1457 switch (aop->aopu.pcop->type)
1460 pcop = pCodeOpCopy (aop->aopu.pcop);
1461 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1462 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1463 PCOI(pcop)->index += offset;
1464 //PCOI(pcop)->offset = 0;
1467 pcop = pCodeOpCopy (aop->aopu.pcop);
1468 PCOR(pcop)->instance = offset;
1471 assert ( !"unhandled pCode type" );
1477 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1478 "popGet got unsupported aop->type");
1482 /*-----------------------------------------------------------------*/
1483 /* popGetAddr - access the low/high word of a symbol (immediate) */
1484 /* (for non-PO_IMMEDIATEs this is the same as poGet) */
1485 /*-----------------------------------------------------------------*/
1486 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1488 if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1490 pCodeOp *pcop = aop->aopu.pcop;
1491 pcop = pCodeOpCopy (pcop);
1492 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1493 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1494 PCOI(pcop)->offset += offset;
1495 PCOI(pcop)->index += index;
1498 return popGet (aop, offset + index);
1502 /*-----------------------------------------------------------------*/
1503 /* aopPut - puts a string for a aop */
1504 /*-----------------------------------------------------------------*/
1505 void aopPut (asmop *aop, char *s, int offset)
1510 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1512 if (aop->size && offset > ( aop->size - 1)) {
1513 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1514 "aopPut got offset > aop->size");
1518 /* will assign value to value */
1519 /* depending on where it is ofcourse */
1520 switch (aop->type) {
1523 sprintf(d,"(%s + %d)",
1524 aop->aopu.aop_dir,offset);
1525 fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1528 sprintf(d,"%s",aop->aopu.aop_dir);
1531 DEBUGpic14_emitcode(";","%d",__LINE__);
1533 pic14_emitcode("movf","%s,w",s);
1534 pic14_emitcode("movwf","%s",d);
1537 pic14_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
1538 if(offset >= aop->size) {
1539 emitpcode(POC_CLRF,popGet(aop,offset));
1542 emitpcode(POC_MOVLW,popGetImmd(s,offset,0,0));
1545 emitpcode(POC_MOVWF,popGet(aop,offset));
1552 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1553 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1556 strcmp(s,"r0") == 0 ||
1557 strcmp(s,"r1") == 0 ||
1558 strcmp(s,"r2") == 0 ||
1559 strcmp(s,"r3") == 0 ||
1560 strcmp(s,"r4") == 0 ||
1561 strcmp(s,"r5") == 0 ||
1562 strcmp(s,"r6") == 0 ||
1563 strcmp(s,"r7") == 0 )
1564 pic14_emitcode("mov","%s,%s ; %d",
1565 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1569 if(strcmp(s,"W")==0 )
1570 pic14_emitcode("movf","%s,w ; %d",s,__LINE__);
1572 pic14_emitcode("movwf","%s",
1573 aop->aopu.aop_reg[offset]->name);
1575 if(strcmp(s,zero)==0) {
1576 emitpcode(POC_CLRF,popGet(aop,offset));
1578 } else if(strcmp(s,"W")==0) {
1579 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1580 pcop->type = PO_GPR_REGISTER;
1582 PCOR(pcop)->rIdx = -1;
1583 PCOR(pcop)->r = NULL;
1585 DEBUGpic14_emitcode(";","%d",__LINE__);
1586 pcop->name = Safe_strdup(s);
1587 emitpcode(POC_MOVFW,pcop);
1588 emitpcode(POC_MOVWF,popGet(aop,offset));
1589 } else if(strcmp(s,one)==0) {
1590 emitpcode(POC_CLRF,popGet(aop,offset));
1591 emitpcode(POC_INCF,popGet(aop,offset));
1593 emitpcode(POC_MOVWF,popGet(aop,offset));
1601 if (aop->type == AOP_DPTR2)
1607 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1608 "aopPut writting to code space");
1612 while (offset > aop->coff) {
1614 pic14_emitcode ("inc","dptr");
1617 while (offset < aop->coff) {
1619 pic14_emitcode("lcall","__decdptr");
1624 /* if not in accumulater */
1627 pic14_emitcode ("movx","@dptr,a");
1629 if (aop->type == AOP_DPTR2)
1637 while (offset > aop->coff) {
1639 pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1641 while (offset < aop->coff) {
1643 pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1649 pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1654 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1656 if (strcmp(s,"r0") == 0 ||
1657 strcmp(s,"r1") == 0 ||
1658 strcmp(s,"r2") == 0 ||
1659 strcmp(s,"r3") == 0 ||
1660 strcmp(s,"r4") == 0 ||
1661 strcmp(s,"r5") == 0 ||
1662 strcmp(s,"r6") == 0 ||
1663 strcmp(s,"r7") == 0 ) {
1665 sprintf(buffer,"a%s",s);
1666 pic14_emitcode("mov","@%s,%s",
1667 aop->aopu.aop_ptr->name,buffer);
1669 pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1674 if (strcmp(s,"a") == 0)
1675 pic14_emitcode("push","acc");
1677 pic14_emitcode("push","%s",s);
1682 /* if bit variable */
1683 if (!aop->aopu.aop_dir) {
1684 pic14_emitcode("clr","a");
1685 pic14_emitcode("rlc","a");
1688 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1691 pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1694 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1696 lbl = newiTempLabel(NULL);
1698 if (strcmp(s,"a")) {
1701 pic14_emitcode("clr","c");
1702 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1703 pic14_emitcode("cpl","c");
1704 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1705 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1712 if (strcmp(aop->aopu.aop_str[offset],s))
1713 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1718 if (!offset && (strcmp(s,"acc") == 0))
1721 if (strcmp(aop->aopu.aop_str[offset],s))
1722 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1726 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1727 "aopPut got unsupported aop->type");
1733 /*-----------------------------------------------------------------*/
1734 /* mov2w - generate either a MOVLW or MOVFW based operand type */
1735 /*-----------------------------------------------------------------*/
1736 void mov2w (asmop *aop, int offset)
1742 DEBUGpic14_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
1744 if ( aop_isLitLike (aop) )
1745 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1747 emitpcode(POC_MOVFW,popGet(aop,offset));
1751 /*-----------------------------------------------------------------*/
1752 /* reAdjustPreg - points a register back to where it should */
1753 /*-----------------------------------------------------------------*/
1754 static void reAdjustPreg (asmop *aop)
1758 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1760 if ((size = aop->size) <= 1)
1763 switch (aop->type) {
1767 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1771 if (aop->type == AOP_DPTR2)
1777 pic14_emitcode("lcall","__decdptr");
1780 if (aop->type == AOP_DPTR2)
1792 /*-----------------------------------------------------------------*/
1793 /* opIsGptr: returns non-zero if the passed operand is */
1794 /* a generic pointer type. */
1795 /*-----------------------------------------------------------------*/
1796 static int opIsGptr(operand *op)
1798 sym_link *type = operandType(op);
1800 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1801 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1809 /*-----------------------------------------------------------------*/
1810 /* pic14_getDataSize - get the operand data size */
1811 /*-----------------------------------------------------------------*/
1812 int pic14_getDataSize(operand *op)
1814 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1817 return AOP_SIZE(op);
1819 // tsd- in the pic port, the genptr size is 1, so this code here
1820 // fails. ( in the 8051 port, the size was 4).
1823 size = AOP_SIZE(op);
1824 if (size == GPTRSIZE)
1826 sym_link *type = operandType(op);
1827 if (IS_GENPTR(type))
1829 /* generic pointer; arithmetic operations
1830 * should ignore the high byte (pointer type).
1833 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1840 /*-----------------------------------------------------------------*/
1841 /* pic14_outAcc - output Acc */
1842 /*-----------------------------------------------------------------*/
1843 void pic14_outAcc(operand *result)
1846 DEBUGpic14_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
1847 DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1850 size = pic14_getDataSize(result);
1852 emitpcode(POC_MOVWF,popGet(AOP(result),0));
1855 /* unsigned or positive */
1857 emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1862 /*-----------------------------------------------------------------*/
1863 /* pic14_outBitC - output a bit C */
1864 /*-----------------------------------------------------------------*/
1865 void pic14_outBitC(operand *result)
1868 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1869 /* if the result is bit */
1870 if (AOP_TYPE(result) == AOP_CRY)
1871 aopPut(AOP(result),"c",0);
1873 pic14_emitcode("clr","a ; %d", __LINE__);
1874 pic14_emitcode("rlc","a");
1875 pic14_outAcc(result);
1879 /*-----------------------------------------------------------------*/
1880 /* pic14_toBoolean - emit code for orl a,operator(sizeop) */
1881 /*-----------------------------------------------------------------*/
1882 void pic14_toBoolean(operand *oper)
1884 int size = AOP_SIZE(oper) - 1;
1887 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1889 if ( AOP_TYPE(oper) != AOP_ACC) {
1890 emitpcode(POC_MOVFW,popGet(AOP(oper),0));
1893 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
1898 /*-----------------------------------------------------------------*/
1899 /* genNot - generate code for ! operation */
1900 /*-----------------------------------------------------------------*/
1901 static void genNot (iCode *ic)
1908 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1909 /* assign asmOps to operand & result */
1910 aopOp (IC_LEFT(ic),ic,FALSE);
1911 aopOp (IC_RESULT(ic),ic,TRUE);
1913 DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1914 /* if in bit space then a special case */
1915 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1916 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1917 emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
1918 emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
1920 emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
1921 emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
1922 emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
1927 size = AOP_SIZE(IC_LEFT(ic));
1929 emitpcode(POC_COMFW,popGet(AOP(IC_LEFT(ic)),0));
1930 emitpcode(POC_ANDLW,popGetLit(1));
1931 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
1934 pic14_toBoolean(IC_LEFT(ic));
1936 tlbl = newiTempLabel(NULL);
1937 pic14_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1938 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
1939 pic14_outBitC(IC_RESULT(ic));
1942 /* release the aops */
1943 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1944 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1948 /*-----------------------------------------------------------------*/
1949 /* genCpl - generate code for complement */
1950 /*-----------------------------------------------------------------*/
1951 static void genCpl (iCode *ic)
1953 operand *left, *result;
1958 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1959 aopOp((left = IC_LEFT(ic)),ic,FALSE);
1960 aopOp((result=IC_RESULT(ic)),ic,TRUE);
1962 /* if both are in bit space then
1964 if (AOP_TYPE(result) == AOP_CRY &&
1965 AOP_TYPE(left) == AOP_CRY ) {
1967 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir);
1968 pic14_emitcode("cpl","c");
1969 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir);
1973 size = AOP_SIZE(result);
1976 if(AOP_TYPE(left) == AOP_ACC)
1977 emitpcode(POC_XORLW, popGetLit(0xff));
1979 emitpcode(POC_COMFW,popGet(AOP(left),offset));
1981 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
1987 /* release the aops */
1988 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1989 freeAsmop(result,NULL,ic,TRUE);
1992 /*-----------------------------------------------------------------*/
1993 /* genUminusFloat - unary minus for floating points */
1994 /*-----------------------------------------------------------------*/
1995 static void genUminusFloat(operand *op,operand *result)
1997 int size ,offset =0 ;
2002 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2003 /* for this we just need to flip the
2004 first it then copy the rest in place */
2005 size = AOP_SIZE(op) - 1;
2006 l = aopGet(AOP(op),3,FALSE,FALSE);
2010 pic14_emitcode("cpl","acc.7");
2011 aopPut(AOP(result),"a",3);
2015 aopGet(AOP(op),offset,FALSE,FALSE),
2021 /*-----------------------------------------------------------------*/
2022 /* genUminus - unary minus code generation */
2023 /*-----------------------------------------------------------------*/
2024 static void genUminus (iCode *ic)
2027 sym_link *optype, *rtype;
2031 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2033 aopOp(IC_LEFT(ic),ic,FALSE);
2034 aopOp(IC_RESULT(ic),ic,TRUE);
2036 /* if both in bit space then special
2038 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2039 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2041 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0));
2042 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2043 emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0));
2048 optype = operandType(IC_LEFT(ic));
2049 rtype = operandType(IC_RESULT(ic));
2051 /* if float then do float stuff */
2052 if (IS_FLOAT(optype)) {
2053 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2057 /* otherwise subtract from zero by taking the 2's complement */
2058 size = AOP_SIZE(IC_LEFT(ic));
2060 for(i=0; i<size; i++) {
2061 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2062 emitpcode(POC_COMF, popGet(AOP(IC_LEFT(ic)),i));
2064 emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2065 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2069 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0));
2070 for(i=1; i<size; i++) {
2072 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),i));
2076 /* release the aops */
2077 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2078 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2081 /*-----------------------------------------------------------------*/
2082 /* saveRegisters - will look for a call and save the registers */
2083 /*-----------------------------------------------------------------*/
2084 static void saveRegisters(iCode *lic)
2093 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2095 for (ic = lic ; ic ; ic = ic->next)
2096 if (ic->op == CALL || ic->op == PCALL)
2100 fprintf(stderr,"found parameter push with no function call\n");
2104 /* if the registers have been saved already then
2106 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2109 /* find the registers in use at this time
2110 and push them away to safety */
2111 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2115 if (options.useXstack) {
2116 if (bitVectBitValue(rsave,R0_IDX))
2117 pic14_emitcode("mov","b,r0");
2118 pic14_emitcode("mov","r0,%s",spname);
2119 for (i = 0 ; i < pic14_nRegs ; i++) {
2120 if (bitVectBitValue(rsave,i)) {
2122 pic14_emitcode("mov","a,b");
2124 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2125 pic14_emitcode("movx","@r0,a");
2126 pic14_emitcode("inc","r0");
2129 pic14_emitcode("mov","%s,r0",spname);
2130 if (bitVectBitValue(rsave,R0_IDX))
2131 pic14_emitcode("mov","r0,b");
2133 //for (i = 0 ; i < pic14_nRegs ; i++) {
2134 // if (bitVectBitValue(rsave,i))
2135 // pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2138 dtype = operandType(IC_LEFT(ic));
2139 if (currFunc && dtype &&
2140 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2141 IFFUNC_ISISR(currFunc->type) &&
2144 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2147 /*-----------------------------------------------------------------*/
2148 /* unsaveRegisters - pop the pushed registers */
2149 /*-----------------------------------------------------------------*/
2150 static void unsaveRegisters (iCode *ic)
2157 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2158 /* find the registers in use at this time
2159 and push them away to safety */
2160 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2163 if (options.useXstack) {
2164 pic14_emitcode("mov","r0,%s",spname);
2165 for (i = pic14_nRegs ; i >= 0 ; i--) {
2166 if (bitVectBitValue(rsave,i)) {
2167 pic14_emitcode("dec","r0");
2168 pic14_emitcode("movx","a,@r0");
2170 pic14_emitcode("mov","b,a");
2172 pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2176 pic14_emitcode("mov","%s,r0",spname);
2177 if (bitVectBitValue(rsave,R0_IDX))
2178 pic14_emitcode("mov","r0,b");
2180 //for (i = pic14_nRegs ; i >= 0 ; i--) {
2181 // if (bitVectBitValue(rsave,i))
2182 // pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2188 /*-----------------------------------------------------------------*/
2190 /*-----------------------------------------------------------------*/
2191 static void pushSide(operand * oper, int size)
2195 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2197 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2198 if (AOP_TYPE(oper) != AOP_REG &&
2199 AOP_TYPE(oper) != AOP_DIR &&
2201 pic14_emitcode("mov","a,%s",l);
2202 pic14_emitcode("push","acc");
2204 pic14_emitcode("push","%s",l);
2209 /*-----------------------------------------------------------------*/
2210 /* assignResultValue - */
2211 /*-----------------------------------------------------------------*/
2212 static void assignResultValue(operand * oper)
2214 int size = AOP_SIZE(oper);
2218 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2220 DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2223 if (GpsuedoStkPtr++)
2224 emitpcode(POC_MOVFW,popRegFromIdx(Gstack_base_addr+2-GpsuedoStkPtr));
2225 emitpcode(POC_MOVWF, popGet(AOP(oper),size));
2230 /*-----------------------------------------------------------------*/
2231 /* genIpush - genrate code for pushing this gets a little complex */
2232 /*-----------------------------------------------------------------*/
2233 static void genIpush (iCode *ic)
2237 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2239 int size, offset = 0 ;
2243 /* if this is not a parm push : ie. it is spill push
2244 and spill push is always done on the local stack */
2245 if (!ic->parmPush) {
2247 /* and the item is spilt then do nothing */
2248 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2251 aopOp(IC_LEFT(ic),ic,FALSE);
2252 size = AOP_SIZE(IC_LEFT(ic));
2253 /* push it on the stack */
2255 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2260 pic14_emitcode("push","%s",l);
2265 /* this is a paramter push: in this case we call
2266 the routine to find the call and save those
2267 registers that need to be saved */
2270 /* then do the push */
2271 aopOp(IC_LEFT(ic),ic,FALSE);
2274 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2275 size = AOP_SIZE(IC_LEFT(ic));
2278 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2279 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
2280 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2282 pic14_emitcode("mov","a,%s",l);
2283 pic14_emitcode("push","acc");
2285 pic14_emitcode("push","%s",l);
2288 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2292 /*-----------------------------------------------------------------*/
2293 /* genIpop - recover the registers: can happen only for spilling */
2294 /*-----------------------------------------------------------------*/
2295 static void genIpop (iCode *ic)
2299 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2304 /* if the temp was not pushed then */
2305 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2308 aopOp(IC_LEFT(ic),ic,FALSE);
2309 size = AOP_SIZE(IC_LEFT(ic));
2312 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2315 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2319 /*-----------------------------------------------------------------*/
2320 /* unsaverbank - restores the resgister bank from stack */
2321 /*-----------------------------------------------------------------*/
2322 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2326 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2332 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2334 if (options.useXstack) {
2336 r = getFreePtr(ic,&aop,FALSE);
2339 pic14_emitcode("mov","%s,_spx",r->name);
2340 pic14_emitcode("movx","a,@%s",r->name);
2341 pic14_emitcode("mov","psw,a");
2342 pic14_emitcode("dec","%s",r->name);
2345 pic14_emitcode ("pop","psw");
2348 for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2349 if (options.useXstack) {
2350 pic14_emitcode("movx","a,@%s",r->name);
2351 //pic14_emitcode("mov","(%s+%d),a",
2352 // regspic14[i].base,8*bank+regspic14[i].offset);
2353 pic14_emitcode("dec","%s",r->name);
2356 pic14_emitcode("pop",""); //"(%s+%d)",
2357 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2360 if (options.useXstack) {
2362 pic14_emitcode("mov","_spx,%s",r->name);
2363 freeAsmop(NULL,aop,ic,TRUE);
2369 /*-----------------------------------------------------------------*/
2370 /* saverbank - saves an entire register bank on the stack */
2371 /*-----------------------------------------------------------------*/
2372 static void saverbank (int bank, iCode *ic, bool pushPsw)
2376 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2382 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2383 if (options.useXstack) {
2386 r = getFreePtr(ic,&aop,FALSE);
2387 pic14_emitcode("mov","%s,_spx",r->name);
2391 for (i = 0 ; i < pic14_nRegs ;i++) {
2392 if (options.useXstack) {
2393 pic14_emitcode("inc","%s",r->name);
2394 //pic14_emitcode("mov","a,(%s+%d)",
2395 // regspic14[i].base,8*bank+regspic14[i].offset);
2396 pic14_emitcode("movx","@%s,a",r->name);
2398 pic14_emitcode("push","");// "(%s+%d)",
2399 //regspic14[i].base,8*bank+regspic14[i].offset);
2403 if (options.useXstack) {
2404 pic14_emitcode("mov","a,psw");
2405 pic14_emitcode("movx","@%s,a",r->name);
2406 pic14_emitcode("inc","%s",r->name);
2407 pic14_emitcode("mov","_spx,%s",r->name);
2408 freeAsmop (NULL,aop,ic,TRUE);
2411 pic14_emitcode("push","psw");
2413 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2419 /*-----------------------------------------------------------------*/
2420 /* genCall - generates a call statement */
2421 /*-----------------------------------------------------------------*/
2422 static void genCall (iCode *ic)
2426 unsigned char *name;
2431 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2433 /* if caller saves & we have not saved then */
2437 /* if we are calling a function that is not using
2438 the same register bank then we need to save the
2439 destination registers on the stack */
2440 dtype = operandType(IC_LEFT(ic));
2441 if (currFunc && dtype &&
2442 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2443 IFFUNC_ISISR(currFunc->type) &&
2446 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2448 /* if send set is not empty the assign */
2451 /* For the Pic port, there is no data stack.
2452 * So parameters passed to functions are stored
2453 * in registers. (The pCode optimizer will get
2454 * rid of most of these :).
2456 int psuedoStkPtr=-1;
2457 int firstTimeThruLoop = 1;
2459 _G.sendSet = reverseSet(_G.sendSet);
2461 /* First figure how many parameters are getting passed */
2462 for (sic = setFirstItem(_G.sendSet) ; sic ;
2463 sic = setNextItem(_G.sendSet)) {
2465 aopOp(IC_LEFT(sic),sic,FALSE);
2466 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2467 freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2470 for (sic = setFirstItem(_G.sendSet) ; sic ;
2471 sic = setNextItem(_G.sendSet)) {
2472 int size, offset = 0;
2474 aopOp(IC_LEFT(sic),sic,FALSE);
2475 size = AOP_SIZE(IC_LEFT(sic));
2478 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2479 AopType(AOP_TYPE(IC_LEFT(sic))));
2481 if(!firstTimeThruLoop) {
2482 /* If this is not the first time we've been through the loop
2483 * then we need to save the parameter in a temporary
2484 * register. The last byte of the last parameter is
2486 emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2489 firstTimeThruLoop=0;
2491 mov2w (AOP(IC_LEFT(sic)), offset);
2494 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2499 sym = OP_SYMBOL(IC_LEFT(ic));
2500 name = sym->rname[0] ? sym->rname : sym->name;
2501 isExtern = IS_EXTERN(sym->etype);
2503 emitpcode(POC_PAGESEL,popGetWithString(name,1)); /* Extern functions maybe on another page - must call pagesel */
2505 emitpcode(POC_CALL,popGetWithString(name,isExtern));
2507 emitpcode(POC_PAGESEL,popGetWithString("$",0)); /* May have returned from another page - must call pagesel to restore PCLATH before next goto or call instruction */
2510 /* if we need assign a result value */
2511 if ((IS_ITEMP(IC_RESULT(ic)) &&
2512 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2513 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2514 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2517 aopOp(IC_RESULT(ic),ic,FALSE);
2520 assignResultValue(IC_RESULT(ic));
2522 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2523 AopType(AOP_TYPE(IC_RESULT(ic))));
2525 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2528 /* adjust the stack for parameters if
2530 if (ic->parmBytes) {
2532 if (ic->parmBytes > 3) {
2533 pic14_emitcode("mov","a,%s",spname);
2534 pic14_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2535 pic14_emitcode("mov","%s,a",spname);
2537 for ( i = 0 ; i < ic->parmBytes ;i++)
2538 pic14_emitcode("dec","%s",spname);
2542 /* if register bank was saved then pop them */
2544 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2546 /* if we hade saved some registers then unsave them */
2547 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2548 unsaveRegisters (ic);
2553 /*-----------------------------------------------------------------*/
2554 /* genPcall - generates a call by pointer statement */
2555 /*-----------------------------------------------------------------*/
2556 static void genPcall (iCode *ic)
2559 symbol *albl = newiTempLabel(NULL);
2560 symbol *blbl = newiTempLabel(NULL);
2567 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2568 /* if caller saves & we have not saved then */
2572 /* if we are calling a function that is not using
2573 the same register bank then we need to save the
2574 destination registers on the stack */
2575 dtype = operandType(IC_LEFT(ic));
2576 if (currFunc && dtype &&
2577 IFFUNC_ISISR(currFunc->type) &&
2578 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2579 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2582 aopOp(left,ic,FALSE);
2583 DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2585 pushSide(IC_LEFT(ic), FPTRSIZE);
2587 /* if send set is not empty, assign parameters */
2590 DEBUGpic14_emitcode ("; ***","%s %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2591 /* no way to pass args - W always gets used to make the call */
2593 /* first idea - factor out a common helper function and call it.
2594 But don't know how to get it generated only once in its own block
2596 if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2599 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2600 DEBUGpic14_emitcode ("; ***","%s %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2601 buffer = Safe_calloc(1,strlen(rname)+16);
2602 sprintf(buffer, "%s_goto_helper", rname);
2603 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2607 emitpcode(POC_CALL,popGetLabel(albl->key));
2608 pcop = popGetLabel(blbl->key);
2609 emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
2610 emitpcode(POC_GOTO,pcop);
2611 emitpLabel(albl->key);
2613 poc = ( aop_isLitLike (AOP(left)) ? POC_MOVLW : POC_MOVFW );
2615 emitpcode(poc,popGetAddr(AOP(left),1,0));
2616 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2617 emitpcode(poc,popGetAddr(AOP(left),0,0));
2618 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2620 emitpLabel(blbl->key);
2622 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2624 /* if we need to assign a result value */
2625 if ((IS_ITEMP(IC_RESULT(ic)) &&
2626 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2627 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2628 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2631 aopOp(IC_RESULT(ic),ic,FALSE);
2634 assignResultValue(IC_RESULT(ic));
2636 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2639 /* if register bank was saved then unsave them */
2640 if (currFunc && dtype &&
2641 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2642 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2644 /* if we hade saved some registers then
2647 unsaveRegisters (ic);
2651 /*-----------------------------------------------------------------*/
2652 /* resultRemat - result is rematerializable */
2653 /*-----------------------------------------------------------------*/
2654 static int resultRemat (iCode *ic)
2656 // DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2659 if (SKIP_IC(ic) || ic->op == IFX)
2662 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2663 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2664 if (sym->remat && !POINTER_SET(ic))
2671 #if defined(__BORLANDC__) || defined(_MSC_VER)
2672 #define STRCASECMP stricmp
2674 #define STRCASECMP strcasecmp
2678 /*-----------------------------------------------------------------*/
2679 /* inExcludeList - return 1 if the string is in exclude Reg list */
2680 /*-----------------------------------------------------------------*/
2681 static bool inExcludeList(char *s)
2683 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2686 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2687 if (options.excludeRegs[i] &&
2688 STRCASECMP(options.excludeRegs[i],"none") == 0)
2691 for ( i = 0 ; options.excludeRegs[i]; i++) {
2692 if (options.excludeRegs[i] &&
2693 STRCASECMP(s,options.excludeRegs[i]) == 0)
2700 /*-----------------------------------------------------------------*/
2701 /* genFunction - generated code for function entry */
2702 /*-----------------------------------------------------------------*/
2703 static void genFunction (iCode *ic)
2710 DEBUGpic14_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2712 labelOffset += (max_key+4);
2716 /* create the function header */
2717 pic14_emitcode(";","-----------------------------------------");
2718 pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2719 pic14_emitcode(";","-----------------------------------------");
2721 pic14_emitcode("","%s:",sym->rname);
2722 addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2724 ftype = operandType(IC_LEFT(ic));
2726 /* if critical function then turn interrupts off */
2727 if (IFFUNC_ISCRITICAL(ftype))
2728 pic14_emitcode("clr","ea");
2730 /* here we need to generate the equates for the
2731 register bank if required */
2733 if (FUNC_REGBANK(ftype) != rbank) {
2736 rbank = FUNC_REGBANK(ftype);
2737 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2738 if (strcmp(regspic14[i].base,"0") == 0)
2739 pic14_emitcode("","%s = 0x%02x",
2741 8*rbank+regspic14[i].offset);
2743 pic14_emitcode ("","%s = %s + 0x%02x",
2746 8*rbank+regspic14[i].offset);
2751 /* if this is an interrupt service routine */
2752 if (IFFUNC_ISISR(sym->type)) {
2753 /* already done in pic14createInterruptVect() - delete me
2754 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2755 emitpcodeNULLop(POC_NOP);
2756 emitpcodeNULLop(POC_NOP);
2757 emitpcodeNULLop(POC_NOP);
2759 emitpcode(POC_MOVWF, popCopyReg(&pc_wsave));
2760 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2761 emitpcode(POC_CLRF, popCopyReg(&pc_status));
2762 emitpcode(POC_MOVWF, popCopyReg(&pc_ssave));
2763 emitpcode(POC_MOVFW, popCopyReg(&pc_pclath));
2764 emitpcode(POC_MOVWF, popCopyReg(&pc_psave));
2765 emitpcode(POC_CLRF, popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2767 pBlockConvert2ISR(pb);
2769 if (!inExcludeList("acc"))
2770 pic14_emitcode ("push","acc");
2771 if (!inExcludeList("b"))
2772 pic14_emitcode ("push","b");
2773 if (!inExcludeList("dpl"))
2774 pic14_emitcode ("push","dpl");
2775 if (!inExcludeList("dph"))
2776 pic14_emitcode ("push","dph");
2777 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2779 pic14_emitcode ("push", "dpx");
2780 /* Make sure we're using standard DPTR */
2781 pic14_emitcode ("push", "dps");
2782 pic14_emitcode ("mov", "dps, #0x00");
2783 if (options.stack10bit)
2785 /* This ISR could conceivably use DPTR2. Better save it. */
2786 pic14_emitcode ("push", "dpl1");
2787 pic14_emitcode ("push", "dph1");
2788 pic14_emitcode ("push", "dpx1");
2791 /* if this isr has no bank i.e. is going to
2792 run with bank 0 , then we need to save more
2794 if (!FUNC_REGBANK(sym->type)) {
2796 /* if this function does not call any other
2797 function then we can be economical and
2798 save only those registers that are used */
2799 if (! IFFUNC_HASFCALL(sym->type)) {
2802 /* if any registers used */
2803 if (sym->regsUsed) {
2804 /* save the registers used */
2805 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2806 if (bitVectBitValue(sym->regsUsed,i) ||
2807 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2808 pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);
2813 /* this function has a function call cannot
2814 determines register usage so we will have the
2816 saverbank(0,ic,FALSE);
2821 /* if callee-save to be used for this function
2822 then save the registers being used in this function */
2823 if (IFFUNC_CALLEESAVES(sym->type)) {
2826 /* if any registers used */
2827 if (sym->regsUsed) {
2828 /* save the registers used */
2829 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2830 if (bitVectBitValue(sym->regsUsed,i) ||
2831 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2832 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2840 /* set the register bank to the desired value */
2841 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2842 pic14_emitcode("push","psw");
2843 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);
2846 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2848 if (options.useXstack) {
2849 pic14_emitcode("mov","r0,%s",spname);
2850 pic14_emitcode("mov","a,_bp");
2851 pic14_emitcode("movx","@r0,a");
2852 pic14_emitcode("inc","%s",spname);
2856 /* set up the stack */
2857 pic14_emitcode ("push","_bp"); /* save the callers stack */
2859 pic14_emitcode ("mov","_bp,%s",spname);
2862 /* adjust the stack for the function */
2867 werror(W_STACK_OVERFLOW,sym->name);
2869 if (i > 3 && sym->recvSize < 4) {
2871 pic14_emitcode ("mov","a,sp");
2872 pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2873 pic14_emitcode ("mov","sp,a");
2878 pic14_emitcode("inc","sp");
2883 pic14_emitcode ("mov","a,_spx");
2884 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2885 pic14_emitcode ("mov","_spx,a");
2890 /*-----------------------------------------------------------------*/
2891 /* genEndFunction - generates epilogue for functions */
2892 /*-----------------------------------------------------------------*/
2893 static void genEndFunction (iCode *ic)
2895 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2899 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2901 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2903 pic14_emitcode ("mov","%s,_bp",spname);
2906 /* if use external stack but some variables were
2907 added to the local stack then decrement the
2909 if (options.useXstack && sym->stack) {
2910 pic14_emitcode("mov","a,sp");
2911 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2912 pic14_emitcode("mov","sp,a");
2916 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2917 if (options.useXstack) {
2918 pic14_emitcode("mov","r0,%s",spname);
2919 pic14_emitcode("movx","a,@r0");
2920 pic14_emitcode("mov","_bp,a");
2921 pic14_emitcode("dec","%s",spname);
2925 pic14_emitcode ("pop","_bp");
2929 /* restore the register bank */
2930 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2931 pic14_emitcode ("pop","psw");
2933 if (IFFUNC_ISISR(sym->type)) {
2935 /* now we need to restore the registers */
2936 /* if this isr has no bank i.e. is going to
2937 run with bank 0 , then we need to save more
2939 if (!FUNC_REGBANK(sym->type)) {
2941 /* if this function does not call any other
2942 function then we can be economical and
2943 save only those registers that are used */
2944 if (! IFFUNC_HASFCALL(sym->type)) {
2947 /* if any registers used */
2948 if (sym->regsUsed) {
2949 /* save the registers used */
2950 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2951 if (bitVectBitValue(sym->regsUsed,i) ||
2952 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2953 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2958 /* this function has a function call cannot
2959 determines register usage so we will have the
2961 unsaverbank(0,ic,FALSE);
2965 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2967 if (options.stack10bit)
2969 pic14_emitcode ("pop", "dpx1");
2970 pic14_emitcode ("pop", "dph1");
2971 pic14_emitcode ("pop", "dpl1");
2973 pic14_emitcode ("pop", "dps");
2974 pic14_emitcode ("pop", "dpx");
2976 if (!inExcludeList("dph"))
2977 pic14_emitcode ("pop","dph");
2978 if (!inExcludeList("dpl"))
2979 pic14_emitcode ("pop","dpl");
2980 if (!inExcludeList("b"))
2981 pic14_emitcode ("pop","b");
2982 if (!inExcludeList("acc"))
2983 pic14_emitcode ("pop","acc");
2985 if (IFFUNC_ISCRITICAL(sym->type))
2986 pic14_emitcode("setb","ea");
2989 /* if debug then send end of function */
2990 /* if (options.debug && currFunc) { */
2992 debugFile->writeEndFunction (currFunc, ic, 1);
2995 pic14_emitcode ("reti","");
2996 emitpcode(POC_MOVFW, popCopyReg(&pc_psave));
2997 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
2998 emitpcode(POC_CLRF, popCopyReg(&pc_status));
2999 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3000 emitpcode(POC_MOVWF, popCopyReg(&pc_status));
3001 emitpcode(POC_SWAPF, popCopyReg(&pc_wsave));
3002 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3003 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3004 emitpcodeNULLop(POC_RETFIE);
3007 if (IFFUNC_ISCRITICAL(sym->type))
3008 pic14_emitcode("setb","ea");
3010 if (IFFUNC_CALLEESAVES(sym->type)) {
3013 /* if any registers used */
3014 if (sym->regsUsed) {
3015 /* save the registers used */
3016 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3017 if (bitVectBitValue(sym->regsUsed,i) ||
3018 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3019 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3025 /* if debug then send end of function */
3027 debugFile->writeEndFunction (currFunc, ic, 1);
3030 pic14_emitcode ("return","");
3031 emitpcodeNULLop(POC_RETURN);
3033 /* Mark the end of a function */
3034 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3039 /*-----------------------------------------------------------------*/
3040 /* genRet - generate code for return statement */
3041 /*-----------------------------------------------------------------*/
3042 static void genRet (iCode *ic)
3044 int size,offset = 0 , pushed = 0;
3048 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3049 /* if we have no return value then
3050 just generate the "ret" */
3054 /* we have something to return then
3055 move the return value into place */
3056 aopOp(IC_LEFT(ic),ic,FALSE);
3057 size = AOP_SIZE(IC_LEFT(ic));
3061 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3063 l = aopGet(AOP(IC_LEFT(ic)),offset++,
3065 pic14_emitcode("push","%s",l);
3068 l = aopGet(AOP(IC_LEFT(ic)),offset,
3070 if (strcmp(fReturn[offset],l)) {
3071 if ((((AOP(IC_LEFT(ic))->type) == AOP_PCODE) &&
3072 AOP(IC_LEFT(ic))->aopu.pcop->type == PO_IMMEDIATE) ||
3073 ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
3074 ( (AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3075 emitpcode(POC_MOVLW, popGetAddr(AOP(IC_LEFT(ic)),offset,0));
3077 emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset));
3080 emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr+1-size));
3090 if (strcmp(fReturn[pushed],"a"))
3091 pic14_emitcode("pop",fReturn[pushed]);
3093 pic14_emitcode("pop","acc");
3096 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3099 /* generate a jump to the return label
3100 if the next is not the return statement */
3101 if (!(ic->next && ic->next->op == LABEL &&
3102 IC_LABEL(ic->next) == returnLabel)) {
3104 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3105 pic14_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3110 /*-----------------------------------------------------------------*/
3111 /* genLabel - generates a label */
3112 /*-----------------------------------------------------------------*/
3113 static void genLabel (iCode *ic)
3117 /* special case never generate */
3118 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3119 if (IC_LABEL(ic) == entryLabel)
3122 emitpLabel(IC_LABEL(ic)->key);
3123 pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3126 /*-----------------------------------------------------------------*/
3127 /* genGoto - generates a goto */
3128 /*-----------------------------------------------------------------*/
3130 static void genGoto (iCode *ic)
3134 emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3135 pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3139 /*-----------------------------------------------------------------*/
3140 /* genMultbits :- multiplication of bits */
3141 /*-----------------------------------------------------------------*/
3142 static void genMultbits (operand *left,
3147 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3149 if(!pic14_sameRegs(AOP(result),AOP(right)))
3150 emitpcode(POC_BSF, popGet(AOP(result),0));
3152 emitpcode(POC_BTFSC,popGet(AOP(right),0));
3153 emitpcode(POC_BTFSS,popGet(AOP(left),0));
3154 emitpcode(POC_BCF, popGet(AOP(result),0));
3159 /*-----------------------------------------------------------------*/
3160 /* genMultOneByte : 8 bit multiplication & division */
3161 /*-----------------------------------------------------------------*/
3162 static void genMultOneByte (operand *left,
3166 sym_link *opetype = operandType(result);
3173 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3174 DEBUGpic14_AopType(__LINE__,left,right,result);
3175 DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3177 /* (if two literals, the value is computed before) */
3178 /* if one literal, literal on the right */
3179 if (AOP_TYPE(left) == AOP_LIT){
3185 size = AOP_SIZE(result);
3188 if (AOP_TYPE(right) == AOP_LIT){
3189 pic14_emitcode("multiply ","lit val:%s by variable %s and store in %s",
3190 aopGet(AOP(right),0,FALSE,FALSE),
3191 aopGet(AOP(left),0,FALSE,FALSE),
3192 aopGet(AOP(result),0,FALSE,FALSE));
3193 pic14_emitcode("call","genMultLit");
3195 pic14_emitcode("multiply ","variable :%s by variable %s and store in %s",
3196 aopGet(AOP(right),0,FALSE,FALSE),
3197 aopGet(AOP(left),0,FALSE,FALSE),
3198 aopGet(AOP(result),0,FALSE,FALSE));
3199 pic14_emitcode("call","genMult8X8_8");
3202 genMult8X8_8 (left, right,result);
3205 /* signed or unsigned */
3206 //pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3207 //l = aopGet(AOP(left),0,FALSE,FALSE);
3209 //pic14_emitcode("mul","ab");
3210 /* if result size = 1, mul signed = mul unsigned */
3211 //aopPut(AOP(result),"a",0);
3213 } else { // (size > 1)
3215 pic14_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s",
3216 aopGet(AOP(right),0,FALSE,FALSE),
3217 aopGet(AOP(left),0,FALSE,FALSE),
3218 aopGet(AOP(result),0,FALSE,FALSE));
3220 if (SPEC_USIGN(opetype)){
3221 pic14_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3222 genUMult8X8_16 (left, right, result, NULL);
3225 /* for filling the MSBs */
3226 emitpcode(POC_CLRF, popGet(AOP(result),2));
3227 emitpcode(POC_CLRF, popGet(AOP(result),3));
3231 pic14_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3233 pic14_emitcode("mov","a,b");
3235 /* adjust the MSB if left or right neg */
3237 /* if one literal */
3238 if (AOP_TYPE(right) == AOP_LIT){
3239 pic14_emitcode("multiply ","right is a lit");
3240 /* AND literal negative */
3241 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3242 /* adjust MSB (c==0 after mul) */
3243 pic14_emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3247 genSMult8X8_16 (left, right, result, NULL);
3251 pic14_emitcode("multiply ","size is greater than 2, so propogate sign");
3253 pic14_emitcode("rlc","a");
3254 pic14_emitcode("subb","a,acc");
3262 pic14_emitcode("multiply ","size is way greater than 2, so propogate sign");
3263 //aopPut(AOP(result),"a",offset++);
3267 /*-----------------------------------------------------------------*/
3268 /* genMult - generates code for multiplication */
3269 /*-----------------------------------------------------------------*/
3270 static void genMult (iCode *ic)
3272 operand *left = IC_LEFT(ic);
3273 operand *right = IC_RIGHT(ic);
3274 operand *result= IC_RESULT(ic);
3278 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3279 /* assign the amsops */
3280 aopOp (left,ic,FALSE);
3281 aopOp (right,ic,FALSE);
3282 aopOp (result,ic,TRUE);
3284 DEBUGpic14_AopType(__LINE__,left,right,result);
3286 /* special cases first */
3288 if (AOP_TYPE(left) == AOP_CRY &&
3289 AOP_TYPE(right)== AOP_CRY) {
3290 genMultbits(left,right,result);
3294 /* if both are of size == 1 */
3295 if (AOP_SIZE(left) == 1 &&
3296 AOP_SIZE(right) == 1 ) {
3297 genMultOneByte(left,right,result);
3301 pic14_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3303 /* should have been converted to function call */
3307 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3308 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3309 freeAsmop(result,NULL,ic,TRUE);
3312 /*-----------------------------------------------------------------*/
3313 /* genDivbits :- division of bits */
3314 /*-----------------------------------------------------------------*/
3315 static void genDivbits (operand *left,
3324 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3325 /* the result must be bit */
3326 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3327 l = aopGet(AOP(left),0,FALSE,FALSE);
3331 pic14_emitcode("div","ab");
3332 pic14_emitcode("rrc","a");
3333 aopPut(AOP(result),"c",0);
3336 /*-----------------------------------------------------------------*/
3337 /* genDivOneByte : 8 bit division */
3338 /*-----------------------------------------------------------------*/
3339 static void genDivOneByte (operand *left,
3343 sym_link *opetype = operandType(result);
3349 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3350 size = AOP_SIZE(result) - 1;
3352 /* signed or unsigned */
3353 if (SPEC_USIGN(opetype)) {
3354 /* unsigned is easy */
3355 pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3356 l = aopGet(AOP(left),0,FALSE,FALSE);
3358 pic14_emitcode("div","ab");
3359 aopPut(AOP(result),"a",0);
3361 aopPut(AOP(result),zero,offset++);
3365 /* signed is a little bit more difficult */
3367 /* save the signs of the operands */
3368 l = aopGet(AOP(left),0,FALSE,FALSE);
3370 pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3371 pic14_emitcode("push","acc"); /* save it on the stack */
3373 /* now sign adjust for both left & right */
3374 l = aopGet(AOP(right),0,FALSE,FALSE);
3376 lbl = newiTempLabel(NULL);
3377 pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3378 pic14_emitcode("cpl","a");
3379 pic14_emitcode("inc","a");
3380 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3381 pic14_emitcode("mov","b,a");
3383 /* sign adjust left side */
3384 l = aopGet(AOP(left),0,FALSE,FALSE);
3387 lbl = newiTempLabel(NULL);
3388 pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3389 pic14_emitcode("cpl","a");
3390 pic14_emitcode("inc","a");
3391 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3393 /* now the division */
3394 pic14_emitcode("div","ab");
3395 /* we are interested in the lower order
3397 pic14_emitcode("mov","b,a");
3398 lbl = newiTempLabel(NULL);
3399 pic14_emitcode("pop","acc");
3400 /* if there was an over flow we don't
3401 adjust the sign of the result */
3402 pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3403 pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3405 pic14_emitcode("clr","a");
3406 pic14_emitcode("subb","a,b");
3407 pic14_emitcode("mov","b,a");
3408 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3410 /* now we are done */
3411 aopPut(AOP(result),"b",0);
3413 pic14_emitcode("mov","c,b.7");
3414 pic14_emitcode("subb","a,acc");
3417 aopPut(AOP(result),"a",offset++);
3421 /*-----------------------------------------------------------------*/
3422 /* genDiv - generates code for division */
3423 /*-----------------------------------------------------------------*/
3424 static void genDiv (iCode *ic)
3426 operand *left = IC_LEFT(ic);
3427 operand *right = IC_RIGHT(ic);
3428 operand *result= IC_RESULT(ic);
3431 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3432 /* assign the amsops */
3433 aopOp (left,ic,FALSE);
3434 aopOp (right,ic,FALSE);
3435 aopOp (result,ic,TRUE);
3437 /* special cases first */
3439 if (AOP_TYPE(left) == AOP_CRY &&
3440 AOP_TYPE(right)== AOP_CRY) {
3441 genDivbits(left,right,result);
3445 /* if both are of size == 1 */
3446 if (AOP_SIZE(left) == 1 &&
3447 AOP_SIZE(right) == 1 ) {
3448 genDivOneByte(left,right,result);
3452 /* should have been converted to function call */
3455 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3456 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3457 freeAsmop(result,NULL,ic,TRUE);
3460 /*-----------------------------------------------------------------*/
3461 /* genModbits :- modulus of bits */
3462 /*-----------------------------------------------------------------*/
3463 static void genModbits (operand *left,
3471 /* the result must be bit */
3472 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3473 l = aopGet(AOP(left),0,FALSE,FALSE);
3477 pic14_emitcode("div","ab");
3478 pic14_emitcode("mov","a,b");
3479 pic14_emitcode("rrc","a");
3480 aopPut(AOP(result),"c",0);
3483 /*-----------------------------------------------------------------*/
3484 /* genModOneByte : 8 bit modulus */
3485 /*-----------------------------------------------------------------*/
3486 static void genModOneByte (operand *left,
3490 sym_link *opetype = operandType(result);
3495 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3496 /* signed or unsigned */
3497 if (SPEC_USIGN(opetype)) {
3498 /* unsigned is easy */
3499 pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3500 l = aopGet(AOP(left),0,FALSE,FALSE);
3502 pic14_emitcode("div","ab");
3503 aopPut(AOP(result),"b",0);
3507 /* signed is a little bit more difficult */
3509 /* save the signs of the operands */
3510 l = aopGet(AOP(left),0,FALSE,FALSE);
3513 pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3514 pic14_emitcode("push","acc"); /* save it on the stack */
3516 /* now sign adjust for both left & right */
3517 l = aopGet(AOP(right),0,FALSE,FALSE);
3520 lbl = newiTempLabel(NULL);
3521 pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3522 pic14_emitcode("cpl","a");
3523 pic14_emitcode("inc","a");
3524 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3525 pic14_emitcode("mov","b,a");
3527 /* sign adjust left side */
3528 l = aopGet(AOP(left),0,FALSE,FALSE);
3531 lbl = newiTempLabel(NULL);
3532 pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3533 pic14_emitcode("cpl","a");
3534 pic14_emitcode("inc","a");
3535 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3537 /* now the multiplication */
3538 pic14_emitcode("div","ab");
3539 /* we are interested in the lower order
3541 lbl = newiTempLabel(NULL);
3542 pic14_emitcode("pop","acc");
3543 /* if there was an over flow we don't
3544 adjust the sign of the result */
3545 pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3546 pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3548 pic14_emitcode("clr","a");
3549 pic14_emitcode("subb","a,b");
3550 pic14_emitcode("mov","b,a");
3551 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3553 /* now we are done */
3554 aopPut(AOP(result),"b",0);
3558 /*-----------------------------------------------------------------*/
3559 /* genMod - generates code for division */
3560 /*-----------------------------------------------------------------*/
3561 static void genMod (iCode *ic)
3563 operand *left = IC_LEFT(ic);
3564 operand *right = IC_RIGHT(ic);
3565 operand *result= IC_RESULT(ic);
3568 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3569 /* assign the amsops */
3570 aopOp (left,ic,FALSE);
3571 aopOp (right,ic,FALSE);
3572 aopOp (result,ic,TRUE);
3574 /* special cases first */
3576 if (AOP_TYPE(left) == AOP_CRY &&
3577 AOP_TYPE(right)== AOP_CRY) {
3578 genModbits(left,right,result);
3582 /* if both are of size == 1 */
3583 if (AOP_SIZE(left) == 1 &&
3584 AOP_SIZE(right) == 1 ) {
3585 genModOneByte(left,right,result);
3589 /* should have been converted to function call */
3593 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3594 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3595 freeAsmop(result,NULL,ic,TRUE);
3598 /*-----------------------------------------------------------------*/
3599 /* genIfxJump :- will create a jump depending on the ifx */
3600 /*-----------------------------------------------------------------*/
3602 note: May need to add parameter to indicate when a variable is in bit space.
3604 static void genIfxJump (iCode *ic, char *jval)
3608 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3609 /* if true label then we jump if condition
3611 if ( IC_TRUE(ic) ) {
3613 if(strcmp(jval,"a") == 0)
3615 else if (strcmp(jval,"c") == 0)
3618 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3619 emitpcode(POC_BTFSC, newpCodeOpBit(jval,-1,1));
3622 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3623 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3627 /* false label is present */
3628 if(strcmp(jval,"a") == 0)
3630 else if (strcmp(jval,"c") == 0)
3633 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3634 emitpcode(POC_BTFSS, newpCodeOpBit(jval,-1,1));
3637 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3638 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3643 /* mark the icode as generated */
3647 /*-----------------------------------------------------------------*/
3649 /*-----------------------------------------------------------------*/
3650 static void genSkip(iCode *ifx,int status_bit)
3656 if ( IC_TRUE(ifx) ) {
3657 switch(status_bit) {
3672 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3673 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3677 switch(status_bit) {
3691 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3692 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3698 /*-----------------------------------------------------------------*/
3700 /*-----------------------------------------------------------------*/
3701 static void genSkipc(resolvedIfx *rifx)
3712 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3713 emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3714 rifx->generated = 1;
3717 /*-----------------------------------------------------------------*/
3719 /*-----------------------------------------------------------------*/
3720 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3726 if( (rifx->condition ^ invert_condition) & 1)
3731 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3732 rifx->generated = 1;
3735 /*-----------------------------------------------------------------*/
3737 /*-----------------------------------------------------------------*/
3738 static void genSkipz(iCode *ifx, int condition)
3750 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3752 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3755 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3757 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3762 /*-----------------------------------------------------------------*/
3764 /*-----------------------------------------------------------------*/
3765 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3772 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3774 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3777 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3778 rifx->generated = 1;
3783 /*-----------------------------------------------------------------*/
3784 /* genChkZeroes :- greater or less than comparison */
3785 /* For each byte in a literal that is zero, inclusive or the */
3786 /* the corresponding byte in the operand with W */
3787 /* returns true if any of the bytes are zero */
3788 /*-----------------------------------------------------------------*/
3789 static int genChkZeroes(operand *op, int lit, int size)
3796 i = (lit >> (size*8)) & 0xff;
3800 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3802 emitpcode(POC_IORFW, popGet(AOP(op),size));
3812 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3813 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
3814 #define DEBUGpc emitpComment
3816 /*-----------------------------------------------------------------*/
3817 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
3818 /* aop (if it's NOT a literal) or from lit (if */
3819 /* aop is a literal) */
3820 /*-----------------------------------------------------------------*/
3821 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3822 if (aop->type == AOP_LIT) {
3823 emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3825 emitpcode (POC_MOVFW, popGet (aop, offset));
3829 /* genCmp performs a left < right comparison, stores
3830 * the outcome in result (if != NULL) and generates
3831 * control flow code for the ifx (if != NULL).
3833 * This version leaves in sequences like
3834 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3835 * which should be optmized by the peephole
3836 * optimizer - RN 2005-01-01 */
3837 static void genCmp (operand *left,operand *right,
3838 operand *result, iCode *ifx, int sign)
3848 int invert_result = 0;
3852 assert (AOP_SIZE(left) == AOP_SIZE(right));
3853 assert (left && right);
3855 size = AOP_SIZE(right) - 1;
3856 mask = (0x100UL << (size*8)) - 1;
3857 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3862 resolveIfx (&rIfx, ifx);
3864 /**********************************************************************
3865 * handle bits - bit compares are promoted to int compares seemingly! *
3866 **********************************************************************/
3868 // THIS IS COMPLETELY UNTESTED!
3869 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3870 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3871 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3872 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3875 // 1 < {0,1} is false --> clear C by skipping the next instruction
3876 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3877 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3878 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3879 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3880 emitCLRC; // only skipped for left=0 && right=1
3882 goto correct_result_in_carry;
3886 /*************************************************
3887 * make sure that left is register (or the like) *
3888 *************************************************/
3889 if (!isAOP_REGlike(left)) {
3890 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
3891 assert (isAOP_LIT(left));
3892 assert (isAOP_REGlike(right));
3893 // swap left and right
3894 // left < right <==> right > left <==> (right >= left + 1)
3895 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3897 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
3898 // MAXVALUE < right? always false
3899 if (performedLt) emitCLRC; else emitSETC;
3900 goto correct_result_in_carry;
3903 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
3904 // that's why we handled it above.
3911 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
3912 } else if (isAOP_LIT(right)) {
3913 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3916 assert (isAOP_REGlike(left)); // left must be register or the like
3917 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
3919 /*************************************************
3920 * special cases go here *
3921 *************************************************/
3923 if (isAOP_LIT(right)) {
3925 // unsigned comparison to a literal
3926 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
3928 // unsigned left < 0? always false
3929 if (performedLt) emitCLRC; else emitSETC;
3930 goto correct_result_in_carry;
3933 // signed comparison to a literal
3934 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
3935 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
3936 // signed left < 0x80000000? always false
3937 if (performedLt) emitCLRC; else emitSETC;
3938 goto correct_result_in_carry;
3939 } else if (lit == 0) {
3940 // compare left < 0; set CARRY if SIGNBIT(left) is set
3941 if (performedLt) emitSETC; else emitCLRC;
3942 emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
3943 if (performedLt) emitCLRC; else emitSETC;
3944 goto correct_result_in_carry;
3947 } // right is literal
3949 /*************************************************
3950 * perform a general case comparison *
3951 * make sure we get CARRY==1 <==> left >= right *
3952 *************************************************/
3953 // compare most significant bytes
3954 //DEBUGpc ("comparing bytes at offset %d", size);
3956 // unsigned comparison
3957 pic14_mov2w_regOrLit (AOP(right), lit, size);
3958 emitpcode (POC_SUBFW, popGet (AOP(left), size));
3960 // signed comparison
3961 // (add 2^n to both operands then perform an unsigned comparison)
3962 if (isAOP_LIT(right)) {
3963 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
3964 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
3966 if (litbyte == 0x80) {
3967 // left >= 0x80 -- always true, but more bytes to come
3968 mov2w (AOP(left), size);
3969 emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
3972 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
3973 mov2w (AOP(left), size);
3974 emitpcode (POC_ADDLW, popGetLit (0x80));
3975 emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
3978 pCodeOp *pctemp = popGetTempReg();
3979 mov2w (AOP(left), size);
3980 emitpcode (POC_ADDLW, popGetLit (0x80));
3981 emitpcode (POC_MOVWF, pctemp);
3982 mov2w (AOP(right), size);
3983 emitpcode (POC_ADDLW, popGetLit (0x80));
3984 emitpcode (POC_SUBFW, pctemp);
3985 popReleaseTempReg(pctemp);
3989 // compare remaining bytes (treat as unsigned case from above)
3990 templbl = newiTempLabel ( NULL );
3993 //DEBUGpc ("comparing bytes at offset %d", offs);
3995 emitpcode (POC_GOTO, popGetLabel (templbl->key));
3996 pic14_mov2w_regOrLit (AOP(right), lit, offs);
3997 emitpcode (POC_SUBFW, popGet (AOP(left), offs));
3999 emitpLabel (templbl->key);
4000 goto result_in_carry;
4004 /****************************************************
4005 * now CARRY contains the result of the comparison: *
4006 * SUBWF sets CARRY iff *
4007 * F-W >= 0 <==> F >= W <==> !(F < W) *
4008 * (F=left, W=right) *
4009 ****************************************************/
4013 // value will be used in the following genSkipc()
4014 rIfx.condition ^= 1;
4017 correct_result_in_carry:
4019 // assign result to variable (if neccessary)
4020 if (result && AOP_TYPE(result) != AOP_CRY) {
4021 //DEBUGpc ("assign result");
4022 size = AOP_SIZE(result);
4024 emitpcode (POC_CLRF, popGet (AOP(result), size));
4026 if (invert_result) {
4028 emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4030 emitpcode (POC_RLF, popGet (AOP(result), 0));
4034 // perform conditional jump
4036 //DEBUGpc ("generate control flow");
4044 /* OLD VERSION -- BUGGY, DO NOT USE */
4046 /*-----------------------------------------------------------------*/
4047 /* genCmp :- greater or less than comparison */
4048 /*-----------------------------------------------------------------*/
4049 static void genCmp (operand *left,operand *right,
4050 operand *result, iCode *ifx, int sign)
4052 int size; //, offset = 0 ;
4053 unsigned long lit = 0L,i = 0;
4054 resolvedIfx rFalseIfx;
4055 // resolvedIfx rTrueIfx;
4059 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4062 DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4063 DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4067 resolveIfx(&rFalseIfx,ifx);
4068 truelbl = newiTempLabel(NULL);
4069 size = max(AOP_SIZE(left),AOP_SIZE(right));
4071 DEBUGpic14_AopType(__LINE__,left,right,result);
4075 /* if literal is on the right then swap with left */
4076 if ((AOP_TYPE(right) == AOP_LIT)) {
4077 operand *tmp = right ;
4078 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4079 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4082 lit = (lit - 1) & mask;
4085 rFalseIfx.condition ^= 1;
4088 } else if ((AOP_TYPE(left) == AOP_LIT)) {
4089 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4093 //if(IC_TRUE(ifx) == NULL)
4094 /* if left & right are bit variables */
4095 if (AOP_TYPE(left) == AOP_CRY &&
4096 AOP_TYPE(right) == AOP_CRY ) {
4097 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4098 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4100 /* subtract right from left if at the
4101 end the carry flag is set then we know that
4102 left is greater than right */
4104 symbol *lbl = newiTempLabel(NULL);
4107 if(AOP_TYPE(right) == AOP_LIT) {
4109 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4111 DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4118 genSkipCond(&rFalseIfx,left,size-1,7);
4120 /* no need to compare to 0...*/
4121 /* NOTE: this is a de-generate compare that most certainly
4122 * creates some dead code. */
4123 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4125 if(ifx) ifx->generated = 1;
4132 //i = (lit >> (size*8)) & 0xff;
4133 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4135 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4137 i = ((0-lit) & 0xff);
4140 /* lit is 0x7f, all signed chars are less than
4141 * this except for 0x7f itself */
4142 emitpcode(POC_XORLW, popGetLit(0x7f));
4143 genSkipz2(&rFalseIfx,0);
4145 emitpcode(POC_ADDLW, popGetLit(0x80));
4146 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4147 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4152 genSkipz2(&rFalseIfx,1);
4154 emitpcode(POC_ADDLW, popGetLit(i));
4155 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4159 if(ifx) ifx->generated = 1;
4163 /* chars are out of the way. now do ints and longs */
4166 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4173 genSkipCond(&rFalseIfx,left,size,7);
4174 if(ifx) ifx->generated = 1;
4179 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4181 //rFalseIfx.condition ^= 1;
4182 //genSkipCond(&rFalseIfx,left,size,7);
4183 //rFalseIfx.condition ^= 1;
4185 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4186 if(rFalseIfx.condition)
4187 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4189 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4191 emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4192 emitpcode(POC_ADDFW, popGet(AOP(left),0));
4193 emitpcode(POC_MOVFW, popGet(AOP(left),1));
4196 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4198 if(rFalseIfx.condition) {
4200 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4206 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4207 emitpLabel(truelbl->key);
4208 if(ifx) ifx->generated = 1;
4215 if( (lit & 0xff) == 0) {
4216 /* lower byte is zero */
4217 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4218 i = ((lit >> 8) & 0xff) ^0x80;
4219 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4220 emitpcode(POC_ADDLW, popGetLit( 0x80));
4221 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4222 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4225 if(ifx) ifx->generated = 1;
4230 /* Special cases for signed longs */
4231 if( (lit & 0xffffff) == 0) {
4232 /* lower byte is zero */
4233 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4234 i = ((lit >> 8*3) & 0xff) ^0x80;
4235 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4236 emitpcode(POC_ADDLW, popGetLit( 0x80));
4237 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4238 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4241 if(ifx) ifx->generated = 1;
4249 if(lit & (0x80 << (size*8))) {
4250 /* lit is negative */
4251 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4253 //genSkipCond(&rFalseIfx,left,size,7);
4255 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4257 if(rFalseIfx.condition)
4258 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4260 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4264 /* lit is positive */
4265 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4266 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4267 if(rFalseIfx.condition)
4268 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4270 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4274 /* There are no more special cases, so perform a general compare */
4276 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4277 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4281 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4283 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4285 //rFalseIfx.condition ^= 1;
4286 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4288 emitpLabel(truelbl->key);
4290 if(ifx) ifx->generated = 1;
4297 /* sign is out of the way. So now do an unsigned compare */
4298 DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4301 /* General case - compare to an unsigned literal on the right.*/
4303 i = (lit >> (size*8)) & 0xff;
4304 emitpcode(POC_MOVLW, popGetLit(i));
4305 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4307 i = (lit >> (size*8)) & 0xff;
4310 emitpcode(POC_MOVLW, popGetLit(i));
4312 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4314 /* this byte of the lit is zero,
4315 *if it's not the last then OR in the variable */
4317 emitpcode(POC_IORFW, popGet(AOP(left),size));
4322 emitpLabel(lbl->key);
4323 //if(emitFinalCheck)
4324 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4326 emitpLabel(truelbl->key);
4328 if(ifx) ifx->generated = 1;
4335 if(AOP_TYPE(left) == AOP_LIT) {
4336 //symbol *lbl = newiTempLabel(NULL);
4338 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4341 DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4344 if((lit == 0) && (sign == 0)){
4347 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4349 emitpcode(POC_IORFW, popGet(AOP(right),--size));
4351 genSkipz2(&rFalseIfx,0);
4352 if(ifx) ifx->generated = 1;
4359 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4360 /* degenerate compare can never be true */
4361 if(rFalseIfx.condition == 0)
4362 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4364 if(ifx) ifx->generated = 1;
4369 /* signed comparisons to a literal byte */
4371 int lp1 = (lit+1) & 0xff;
4373 DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4376 rFalseIfx.condition ^= 1;
4377 genSkipCond(&rFalseIfx,right,0,7);
4380 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4381 emitpcode(POC_XORLW, popGetLit(0x7f));
4382 genSkipz2(&rFalseIfx,1);
4385 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4386 emitpcode(POC_ADDLW, popGetLit(0x80));
4387 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4388 rFalseIfx.condition ^= 1;
4389 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4392 if(ifx) ifx->generated = 1;
4394 /* unsigned comparisons to a literal byte */
4396 switch(lit & 0xff ) {
4398 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4399 genSkipz2(&rFalseIfx,0);
4400 if(ifx) ifx->generated = 1;
4403 genSkipCond(&rFalseIfx,right,0,7);
4404 if(ifx) ifx->generated = 1;
4408 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4409 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4410 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4411 rFalseIfx.condition ^= 1;
4412 if (AOP_TYPE(result) == AOP_CRY) {
4413 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4414 if(ifx) ifx->generated = 1;
4416 DEBUGpic14_emitcode ("; ***","%s %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4417 emitpcode(POC_CLRF, popGet(AOP(result),0));
4418 emitpcode(POC_RLF, popGet(AOP(result),0));
4419 emitpcode(POC_MOVLW, popGetLit(0x01));
4420 emitpcode(POC_XORWF, popGet(AOP(result),0));
4431 /* Size is greater than 1 */
4439 /* this means lit = 0xffffffff, or -1 */
4442 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4443 rFalseIfx.condition ^= 1;
4444 genSkipCond(&rFalseIfx,right,size,7);
4445 if(ifx) ifx->generated = 1;
4452 if(rFalseIfx.condition) {
4453 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4454 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4457 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4459 emitpcode(POC_IORFW, popGet(AOP(right),size));
4463 if(rFalseIfx.condition) {
4464 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4465 emitpLabel(truelbl->key);
4467 rFalseIfx.condition ^= 1;
4468 genSkipCond(&rFalseIfx,right,s,7);
4471 if(ifx) ifx->generated = 1;
4475 if((size == 1) && (0 == (lp1&0xff))) {
4476 /* lower byte of signed word is zero */
4477 DEBUGpic14_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
4478 i = ((lp1 >> 8) & 0xff) ^0x80;
4479 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4480 emitpcode(POC_ADDLW, popGetLit( 0x80));
4481 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4482 rFalseIfx.condition ^= 1;
4483 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4486 if(ifx) ifx->generated = 1;
4490 if(lit & (0x80 << (size*8))) {
4491 /* Lit is less than zero */
4492 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
4493 //rFalseIfx.condition ^= 1;
4494 //genSkipCond(&rFalseIfx,left,size,7);
4495 //rFalseIfx.condition ^= 1;
4496 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4497 //emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4499 if(rFalseIfx.condition)
4500 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4502 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4506 /* Lit is greater than or equal to zero */
4507 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
4508 //rFalseIfx.condition ^= 1;
4509 //genSkipCond(&rFalseIfx,right,size,7);
4510 //rFalseIfx.condition ^= 1;
4512 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4513 //emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4515 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4516 if(rFalseIfx.condition)
4517 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4519 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4524 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4525 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4529 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4531 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4533 rFalseIfx.condition ^= 1;
4534 //rFalseIfx.condition = 1;
4535 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4537 emitpLabel(truelbl->key);
4539 if(ifx) ifx->generated = 1;
4544 /* compare word or long to an unsigned literal on the right.*/
4549 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4552 break; /* handled above */
4555 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4557 emitpcode(POC_IORFW, popGet(AOP(right),size));
4558 genSkipz2(&rFalseIfx,0);
4562 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4564 emitpcode(POC_IORFW, popGet(AOP(right),size));
4567 if(rFalseIfx.condition)
4568 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4570 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4573 emitpcode(POC_MOVLW, popGetLit(lit+1));
4574 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4576 rFalseIfx.condition ^= 1;
4577 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4580 emitpLabel(truelbl->key);
4582 if(ifx) ifx->generated = 1;
4588 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4589 i = (lit >> (size*8)) & 0xff;
4591 emitpcode(POC_MOVLW, popGetLit(i));
4592 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4595 i = (lit >> (size*8)) & 0xff;
4598 emitpcode(POC_MOVLW, popGetLit(i));
4600 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4602 /* this byte of the lit is zero,
4603 *if it's not the last then OR in the variable */
4605 emitpcode(POC_IORFW, popGet(AOP(right),size));
4610 emitpLabel(lbl->key);
4612 rFalseIfx.condition ^= 1;
4613 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4617 emitpLabel(truelbl->key);
4618 if(ifx) ifx->generated = 1;
4622 /* Compare two variables */
4624 DEBUGpic14_emitcode(";sign","%d",sign);
4628 /* Sigh. thus sucks... */
4630 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4631 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4632 emitpcode(POC_MOVLW, popGetLit(0x80));
4633 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4634 emitpcode(POC_XORFW, popGet(AOP(right),size));
4635 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4637 /* Signed char comparison */
4638 /* Special thanks to Nikolai Golovchenko for this snippet */
4639 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4640 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4641 emitpcode(POC_RRFW, popGet(AOP(left),0)); /* could be any register */
4642 emitpcode(POC_XORFW, popGet(AOP(left),0));
4643 emitpcode(POC_XORFW, popGet(AOP(right),0));
4644 emitpcode(POC_ADDLW, popGetLit(0x80));
4646 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4647 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4649 if(ifx) ifx->generated = 1;
4655 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4656 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4660 /* The rest of the bytes of a multi-byte compare */
4664 emitpcode(POC_GOTO, popGetLabel(lbl->key));
4667 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4668 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4673 emitpLabel(lbl->key);
4675 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4676 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
4677 (AOP_TYPE(result) == AOP_REG)) {
4678 emitpcode(POC_CLRF, popGet(AOP(result),0));
4679 emitpcode(POC_RLF, popGet(AOP(result),0));
4681 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4683 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4684 if(ifx) ifx->generated = 1;
4691 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4692 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4693 pic14_outBitC(result);
4695 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4696 /* if the result is used in the next
4697 ifx conditional branch then generate
4698 code a little differently */
4700 genIfxJump (ifx,"c");
4702 pic14_outBitC(result);
4703 /* leave the result in acc */
4709 /*-----------------------------------------------------------------*/
4710 /* genCmpGt :- greater than comparison */
4711 /*-----------------------------------------------------------------*/
4712 static void genCmpGt (iCode *ic, iCode *ifx)
4714 operand *left, *right, *result;
4715 sym_link *letype , *retype;
4719 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4721 right= IC_RIGHT(ic);
4722 result = IC_RESULT(ic);
4724 letype = getSpec(operandType(left));
4725 retype =getSpec(operandType(right));
4726 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4727 /* assign the amsops */
4728 aopOp (left,ic,FALSE);
4729 aopOp (right,ic,FALSE);
4730 aopOp (result,ic,TRUE);
4732 genCmp(right, left, result, ifx, sign);
4734 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4735 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4736 freeAsmop(result,NULL,ic,TRUE);
4739 /*-----------------------------------------------------------------*/
4740 /* genCmpLt - less than comparisons */
4741 /*-----------------------------------------------------------------*/
4742 static void genCmpLt (iCode *ic, iCode *ifx)
4744 operand *left, *right, *result;
4745 sym_link *letype , *retype;
4749 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4751 right= IC_RIGHT(ic);
4752 result = IC_RESULT(ic);
4754 letype = getSpec(operandType(left));
4755 retype =getSpec(operandType(right));
4756 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4758 /* assign the amsops */
4759 aopOp (left,ic,FALSE);
4760 aopOp (right,ic,FALSE);
4761 aopOp (result,ic,TRUE);
4763 genCmp(left, right, result, ifx, sign);
4765 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4766 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4767 freeAsmop(result,NULL,ic,TRUE);
4770 /*-----------------------------------------------------------------*/
4771 /* genc16bit2lit - compare a 16 bit value to a literal */
4772 /*-----------------------------------------------------------------*/
4773 static void genc16bit2lit(operand *op, int lit, int offset)
4778 DEBUGpic14_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
4779 if( (lit&0xff) == 0)
4784 switch( BYTEofLONG(lit,i)) {
4786 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4789 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4792 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4795 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4796 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4801 switch( BYTEofLONG(lit,i)) {
4803 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4807 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4811 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4814 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4816 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4822 /*-----------------------------------------------------------------*/
4823 /* gencjneshort - compare and jump if not equal */
4824 /*-----------------------------------------------------------------*/
4825 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4827 int size = max(AOP_SIZE(left),AOP_SIZE(right));
4829 int res_offset = 0; /* the result may be a different size then left or right */
4830 int res_size = AOP_SIZE(result);
4834 unsigned long lit = 0L;
4836 if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4837 emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4840 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4841 DEBUGpic14_AopType(__LINE__,left,right,result);
4843 DEBUGpic14_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
4844 resolveIfx(&rIfx,ifx);
4845 lbl = newiTempLabel(NULL);
4848 /* if the left side is a literal or
4849 if the right is in a pointer register and left
4851 if ((AOP_TYPE(left) == AOP_LIT) ||
4852 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4857 if(AOP_TYPE(right) == AOP_LIT)
4858 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4860 /* if the right side is a literal then anything goes */
4861 if (AOP_TYPE(right) == AOP_LIT &&
4862 AOP_TYPE(left) != AOP_DIR ) {
4865 genc16bit2lit(left, lit, 0);
4867 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4872 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4873 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4875 emitpcode(POC_MOVF,popGet(AOP(left),offset));
4879 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4881 if(res_offset < res_size-1)
4889 /* if the right side is in a register or in direct space or
4890 if the left is a pointer register & right is not */
4891 else if (AOP_TYPE(right) == AOP_REG ||
4892 AOP_TYPE(right) == AOP_DIR ||
4893 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4894 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4895 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4896 int lbl_key = lbl->key;
4899 if (AOP_TYPE(result) != AOP_CRY)
4900 emitpcode(POC_CLRF,popGet(AOP(result),res_offset));
4901 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4903 DEBUGpic14_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
4904 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
4905 __FUNCTION__,__LINE__);
4909 /* switch(size) { */
4911 /* genc16bit2lit(left, lit, 0); */
4913 /* emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
4918 if((AOP_TYPE(left) == AOP_DIR) &&
4919 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4921 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4922 emitpcode(POC_XORFW,popGet(AOP(right),offset));
4924 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4926 switch (lit & 0xff) {
4928 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4931 emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4932 emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4933 //emitpcode(POC_GOTO,popGetLabel(lbl->key));
4937 emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4938 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4939 //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4940 emitpcode(POC_GOTO,popGetLabel(lbl_key));
4944 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4945 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4950 emitpcode(POC_MOVF,popGet(AOP(left),offset));
4953 if(AOP_TYPE(result) == AOP_CRY) {
4954 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
4959 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4961 /* fix me. probably need to check result size too */
4962 //emitpcode(POC_CLRF,popGet(AOP(result),0));
4967 emitpcode(POC_GOTO,popGetLabel(lbl_key));
4968 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4975 if(res_offset < res_size-1)
4980 } else if(AOP_TYPE(right) == AOP_REG &&
4981 AOP_TYPE(left) != AOP_DIR){
4984 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4985 emitpcode(POC_XORFW,popGet(AOP(right),offset));
4986 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
4991 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4993 if(res_offset < res_size-1)
4998 /* right is a pointer reg need both a & b */
5000 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5002 pic14_emitcode("mov","b,%s",l);
5003 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5004 pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
5009 emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5011 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5013 emitpLabel(lbl->key);
5015 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5022 /*-----------------------------------------------------------------*/
5023 /* gencjne - compare and jump if not equal */
5024 /*-----------------------------------------------------------------*/
5025 static void gencjne(operand *left, operand *right, iCode *ifx)
5027 symbol *tlbl = newiTempLabel(NULL);
5029 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5030 gencjneshort(left, right, lbl);
5032 pic14_emitcode("mov","a,%s",one);
5033 pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5034 pic14_emitcode("","%05d_DS_:",lbl->key+100);
5035 pic14_emitcode("clr","a");
5036 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5038 emitpLabel(lbl->key);
5039 emitpLabel(tlbl->key);
5044 /*-----------------------------------------------------------------*/
5045 /* genCmpEq - generates code for equal to */
5046 /*-----------------------------------------------------------------*/
5047 static void genCmpEq (iCode *ic, iCode *ifx)
5049 operand *left, *right, *result;
5050 unsigned long lit = 0L;
5054 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5057 DEBUGpic14_emitcode ("; ifx is non-null","");
5059 DEBUGpic14_emitcode ("; ifx is null","");
5061 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5062 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5063 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5065 size = max(AOP_SIZE(left),AOP_SIZE(right));
5067 DEBUGpic14_AopType(__LINE__,left,right,result);
5069 /* if literal, literal on the right or
5070 if the right is in a pointer register and left
5072 if (aop_isLitLike (AOP(IC_LEFT(ic)))
5073 || (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5074 operand *tmp = right ;
5080 if(ifx && !AOP_SIZE(result)){
5082 /* if they are both bit variables */
5083 if (AOP_TYPE(left) == AOP_CRY &&
5084 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5085 if(AOP_TYPE(right) == AOP_LIT){
5086 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5088 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5089 pic14_emitcode("cpl","c");
5090 } else if(lit == 1L) {
5091 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5093 pic14_emitcode("clr","c");
5095 /* AOP_TYPE(right) == AOP_CRY */
5097 symbol *lbl = newiTempLabel(NULL);
5098 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5099 pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5100 pic14_emitcode("cpl","c");
5101 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
5103 /* if true label then we jump if condition
5105 tlbl = newiTempLabel(NULL);
5106 if ( IC_TRUE(ifx) ) {
5107 pic14_emitcode("jnc","%05d_DS_",tlbl->key+100);
5108 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5110 pic14_emitcode("jc","%05d_DS_",tlbl->key+100);
5111 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5113 pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5116 /* left and right are both bit variables, result is carry */
5119 resolveIfx(&rIfx,ifx);
5121 emitpcode(POC_MOVLW,popGet(AOP(left),0));
5122 emitpcode(POC_ANDFW,popGet(AOP(left),0));
5123 emitpcode(POC_BTFSC,popGet(AOP(right),0));
5124 emitpcode(POC_ANDLW,popGet(AOP(left),0));
5129 /* They're not both bit variables. Is the right a literal? */
5130 if(AOP_TYPE(right) == AOP_LIT) {
5131 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5136 switch(lit & 0xff) {
5138 if ( IC_TRUE(ifx) ) {
5139 emitpcode(POC_DECFW,popGet(AOP(left),offset));
5141 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5143 emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
5144 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
5148 if ( IC_TRUE(ifx) ) {
5149 emitpcode(POC_INCFW,popGet(AOP(left),offset));
5151 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5153 emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5154 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
5158 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5160 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5165 /* end of size == 1 */
5169 genc16bit2lit(left,lit,offset);
5172 /* end of size == 2 */
5177 emitpcode(POC_MOVFW,popGet(AOP(left),0));
5178 emitpcode(POC_IORFW,popGet(AOP(left),1));
5179 emitpcode(POC_IORFW,popGet(AOP(left),2));
5180 emitpcode(POC_IORFW,popGet(AOP(left),3));
5184 /* search for patterns that can be optimized */
5186 genc16bit2lit(left,lit,0);
5189 genSkipz(ifx,IC_TRUE(ifx) == NULL);
5191 genc16bit2lit(left,lit,2);
5193 emitpcode(POC_IORFW,popGet(AOP(left),2));
5194 emitpcode(POC_IORFW,popGet(AOP(left),3));
5207 } else if(AOP_TYPE(right) == AOP_CRY ) {
5208 /* we know the left is not a bit, but that the right is */
5209 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5210 emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
5211 popGet(AOP(right),offset));
5212 emitpcode(POC_XORLW,popGetLit(1));
5214 /* if the two are equal, then W will be 0 and the Z bit is set
5215 * we could test Z now, or go ahead and check the high order bytes if
5216 * the variable we're comparing is larger than a byte. */
5219 emitpcode(POC_IORFW,popGet(AOP(left),offset));
5221 if ( IC_TRUE(ifx) ) {
5223 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5224 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5227 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
5228 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5232 /* They're both variables that are larger than bits */
5235 tlbl = newiTempLabel(NULL);
5238 mov2w (AOP(right),offset); /* right might be litLike() */
5239 emitpcode(POC_XORFW,popGet(AOP(left),offset));
5241 if ( IC_TRUE(ifx) ) {
5244 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
5245 pic14_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
5248 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5249 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5253 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
5254 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5258 if(s>1 && IC_TRUE(ifx)) {
5259 emitpLabel(tlbl->key);
5260 pic14_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);
5264 /* mark the icode as generated */
5269 /* if they are both bit variables */
5270 if (AOP_TYPE(left) == AOP_CRY &&
5271 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5272 if(AOP_TYPE(right) == AOP_LIT){
5273 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5275 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5276 pic14_emitcode("cpl","c");
5277 } else if(lit == 1L) {
5278 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5280 pic14_emitcode("clr","c");
5282 /* AOP_TYPE(right) == AOP_CRY */
5284 symbol *lbl = newiTempLabel(NULL);
5285 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5286 pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5287 pic14_emitcode("cpl","c");
5288 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
5291 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5292 pic14_outBitC(result);
5296 genIfxJump (ifx,"c");
5299 /* if the result is used in an arithmetic operation
5300 then put the result in place */
5301 pic14_outBitC(result);
5304 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5305 gencjne(left,right,result,ifx);
5308 gencjne(left,right,newiTempLabel(NULL));
5310 if(IC_TRUE(ifx)->key)
5311 gencjne(left,right,IC_TRUE(ifx)->key);
5313 gencjne(left,right,IC_FALSE(ifx)->key);
5317 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5318 aopPut(AOP(result),"a",0);
5323 genIfxJump (ifx,"a");
5327 /* if the result is used in an arithmetic operation
5328 then put the result in place */
5330 if (AOP_TYPE(result) != AOP_CRY)
5331 pic14_outAcc(result);
5333 /* leave the result in acc */
5337 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5338 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5339 freeAsmop(result,NULL,ic,TRUE);
5342 /*-----------------------------------------------------------------*/
5343 /* ifxForOp - returns the icode containing the ifx for operand */
5344 /*-----------------------------------------------------------------*/
5345 static iCode *ifxForOp ( operand *op, iCode *ic )
5348 /* if true symbol then needs to be assigned */
5349 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5350 if (IS_TRUE_SYMOP(op))
5353 /* if this has register type condition and
5354 the next instruction is ifx with the same operand
5355 and live to of the operand is upto the ifx only then */
5357 ic->next->op == IFX &&
5358 IC_COND(ic->next)->key == op->key &&
5359 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5363 ic->next->op == IFX &&
5364 IC_COND(ic->next)->key == op->key) {
5365 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5369 DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5371 ic->next->op == IFX)
5372 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5375 ic->next->op == IFX &&
5376 IC_COND(ic->next)->key == op->key) {
5377 DEBUGpic14_emitcode ("; "," key is okay");
5378 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5379 OP_SYMBOL(op)->liveTo,
5386 /*-----------------------------------------------------------------*/
5387 /* genAndOp - for && operation */
5388 /*-----------------------------------------------------------------*/
5389 static void genAndOp (iCode *ic)
5391 operand *left,*right, *result;
5395 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5396 /* note here that && operations that are in an
5397 if statement are taken away by backPatchLabels
5398 only those used in arthmetic operations remain */
5399 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5400 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5401 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5403 DEBUGpic14_AopType(__LINE__,left,right,result);
5405 emitpcode(POC_MOVFW,popGet(AOP(left),0));
5406 emitpcode(POC_ANDFW,popGet(AOP(right),0));
5407 emitpcode(POC_MOVWF,popGet(AOP(result),0));
5409 /* if both are bit variables */
5410 /* if (AOP_TYPE(left) == AOP_CRY && */
5411 /* AOP_TYPE(right) == AOP_CRY ) { */
5412 /* pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5413 /* pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5414 /* pic14_outBitC(result); */
5416 /* tlbl = newiTempLabel(NULL); */
5417 /* pic14_toBoolean(left); */
5418 /* pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5419 /* pic14_toBoolean(right); */
5420 /* pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5421 /* pic14_outBitAcc(result); */
5424 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5425 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5426 freeAsmop(result,NULL,ic,TRUE);
5430 /*-----------------------------------------------------------------*/
5431 /* genOrOp - for || operation */
5432 /*-----------------------------------------------------------------*/
5435 modified this code, but it doesn't appear to ever get called
5438 static void genOrOp (iCode *ic)
5440 operand *left,*right, *result;
5443 /* note here that || operations that are in an
5444 if statement are taken away by backPatchLabels
5445 only those used in arthmetic operations remain */
5447 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5448 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5449 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5450 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5452 DEBUGpic14_AopType(__LINE__,left,right,result);
5454 /* if both are bit variables */
5455 if (AOP_TYPE(left) == AOP_CRY &&
5456 AOP_TYPE(right) == AOP_CRY ) {
5457 pic14_emitcode("clrc","");
5458 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5459 AOP(left)->aopu.aop_dir,
5460 AOP(left)->aopu.aop_dir);
5461 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5462 AOP(right)->aopu.aop_dir,
5463 AOP(right)->aopu.aop_dir);
5464 pic14_emitcode("setc","");
5467 tlbl = newiTempLabel(NULL);
5468 pic14_toBoolean(left);
5470 pic14_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5471 pic14_toBoolean(right);
5472 pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5474 pic14_outBitAcc(result);
5477 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5478 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5479 freeAsmop(result,NULL,ic,TRUE);
5482 /*-----------------------------------------------------------------*/
5483 /* isLiteralBit - test if lit == 2^n */
5484 /*-----------------------------------------------------------------*/
5485 static int isLiteralBit(unsigned long lit)
5487 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5488 0x100L,0x200L,0x400L,0x800L,
5489 0x1000L,0x2000L,0x4000L,0x8000L,
5490 0x10000L,0x20000L,0x40000L,0x80000L,
5491 0x100000L,0x200000L,0x400000L,0x800000L,
5492 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5493 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5497 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5498 for(idx = 0; idx < 32; idx++)
5504 /*-----------------------------------------------------------------*/
5505 /* continueIfTrue - */
5506 /*-----------------------------------------------------------------*/
5507 static void continueIfTrue (iCode *ic)
5510 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5512 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5516 /*-----------------------------------------------------------------*/
5518 /*-----------------------------------------------------------------*/
5519 static void jumpIfTrue (iCode *ic)
5522 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5524 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5528 /*-----------------------------------------------------------------*/
5529 /* jmpTrueOrFalse - */
5530 /*-----------------------------------------------------------------*/
5531 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5534 // ugly but optimized by peephole
5535 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5537 symbol *nlbl = newiTempLabel(NULL);
5538 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5539 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5540 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5541 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5544 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5545 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5550 /*-----------------------------------------------------------------*/
5551 /* genAnd - code for and */
5552 /*-----------------------------------------------------------------*/
5553 static void genAnd (iCode *ic, iCode *ifx)
5555 operand *left, *right, *result;
5557 unsigned long lit = 0L;
5562 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5563 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5564 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5565 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5567 resolveIfx(&rIfx,ifx);
5569 /* if left is a literal & right is not then exchange them */
5570 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5571 AOP_NEEDSACC(left)) {
5572 operand *tmp = right ;
5577 /* if result = right then exchange them */
5578 if(pic14_sameRegs(AOP(result),AOP(right))){
5579 operand *tmp = right ;
5584 /* if right is bit then exchange them */
5585 if (AOP_TYPE(right) == AOP_CRY &&
5586 AOP_TYPE(left) != AOP_CRY){
5587 operand *tmp = right ;
5591 if(AOP_TYPE(right) == AOP_LIT)
5592 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5594 size = AOP_SIZE(result);
5596 DEBUGpic14_AopType(__LINE__,left,right,result);
5599 // result = bit & yy;
5600 if (AOP_TYPE(left) == AOP_CRY){
5601 // c = bit & literal;
5602 if(AOP_TYPE(right) == AOP_LIT){
5604 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5607 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5610 if(size && (AOP_TYPE(result) == AOP_CRY)){
5611 pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5614 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5618 pic14_emitcode("clr","c");
5621 if (AOP_TYPE(right) == AOP_CRY){
5623 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5624 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5627 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5629 pic14_emitcode("rrc","a");
5630 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5636 pic14_outBitC(result);
5638 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5639 genIfxJump(ifx, "c");
5643 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5644 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5645 if((AOP_TYPE(right) == AOP_LIT) &&
5646 (AOP_TYPE(result) == AOP_CRY) &&
5647 (AOP_TYPE(left) != AOP_CRY)){
5648 int posbit = isLiteralBit(lit);
5652 //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5655 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5660 while (posbit > 7) {
5664 emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5665 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5666 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5673 symbol *tlbl = newiTempLabel(NULL);
5674 int sizel = AOP_SIZE(left);
5676 pic14_emitcode("setb","c");
5678 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5679 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5681 if((posbit = isLiteralBit(bytelit)) != 0)
5682 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5684 if(bytelit != 0x0FFL)
5685 pic14_emitcode("anl","a,%s",
5686 aopGet(AOP(right),offset,FALSE,TRUE));
5687 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5692 // bit = left & literal
5694 pic14_emitcode("clr","c");
5695 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5697 // if(left & literal)
5700 jmpTrueOrFalse(ifx, tlbl);
5704 pic14_outBitC(result);
5708 /* if left is same as result */
5709 if(pic14_sameRegs(AOP(result),AOP(left))){
5711 for(;size--; offset++,lit>>=8) {
5712 if(AOP_TYPE(right) == AOP_LIT){
5713 switch(lit & 0xff) {
5715 /* and'ing with 0 has clears the result */
5716 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5719 /* and'ing with 0xff is a nop when the result and left are the same */
5724 int p = my_powof2( (~lit) & 0xff );
5726 /* only one bit is set in the literal, so use a bcf instruction */
5727 emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5730 if(know_W != (int)(lit&0xff))
5731 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5733 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5738 if (AOP_TYPE(left) == AOP_ACC) {
5739 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5741 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5742 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5749 // left & result in different registers
5750 if(AOP_TYPE(result) == AOP_CRY){
5752 // if(size), result in bit
5753 // if(!size && ifx), conditional oper: if(left & right)
5754 symbol *tlbl = newiTempLabel(NULL);
5755 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5757 pic14_emitcode("setb","c");
5759 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5760 pic14_emitcode("anl","a,%s",
5761 aopGet(AOP(left),offset,FALSE,FALSE));
5762 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5767 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5768 pic14_outBitC(result);
5770 jmpTrueOrFalse(ifx, tlbl);
5772 for(;(size--);offset++) {
5774 // result = left & right
5775 if(AOP_TYPE(right) == AOP_LIT){
5776 int t = (lit >> (offset*8)) & 0x0FFL;
5779 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5782 if(AOP_TYPE(left) != AOP_ACC) {
5783 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5785 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5788 if(AOP_TYPE(left) == AOP_ACC) {
5789 emitpcode(POC_ANDLW, popGetLit(t));
5791 emitpcode(POC_MOVLW, popGetLit(t));
5792 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5794 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5799 if (AOP_TYPE(left) == AOP_ACC) {
5800 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5802 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5803 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5805 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5811 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5812 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5813 freeAsmop(result,NULL,ic,TRUE);
5816 /*-----------------------------------------------------------------*/
5817 /* genOr - code for or */
5818 /*-----------------------------------------------------------------*/
5819 static void genOr (iCode *ic, iCode *ifx)
5821 operand *left, *right, *result;
5823 unsigned long lit = 0L;
5826 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5828 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5829 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5830 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5832 DEBUGpic14_AopType(__LINE__,left,right,result);
5834 /* if left is a literal & right is not then exchange them */
5835 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5836 AOP_NEEDSACC(left)) {
5837 operand *tmp = right ;
5842 /* if result = right then exchange them */
5843 if(pic14_sameRegs(AOP(result),AOP(right))){
5844 operand *tmp = right ;
5849 /* if right is bit then exchange them */
5850 if (AOP_TYPE(right) == AOP_CRY &&
5851 AOP_TYPE(left) != AOP_CRY){
5852 operand *tmp = right ;
5857 DEBUGpic14_AopType(__LINE__,left,right,result);
5859 if(AOP_TYPE(right) == AOP_LIT)
5860 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5862 size = AOP_SIZE(result);
5866 if (AOP_TYPE(left) == AOP_CRY){
5867 if(AOP_TYPE(right) == AOP_LIT){
5868 // c = bit & literal;
5870 // lit != 0 => result = 1
5871 if(AOP_TYPE(result) == AOP_CRY){
5873 emitpcode(POC_BSF, popGet(AOP(result),0));
5874 //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5875 // AOP(result)->aopu.aop_dir,
5876 // AOP(result)->aopu.aop_dir);
5878 continueIfTrue(ifx);
5882 // lit == 0 => result = left
5883 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5885 pic14_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5888 if (AOP_TYPE(right) == AOP_CRY){
5889 if(pic14_sameRegs(AOP(result),AOP(left))){
5891 emitpcode(POC_BCF, popGet(AOP(result),0));
5892 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5893 emitpcode(POC_BSF, popGet(AOP(result),0));
5895 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5896 AOP(result)->aopu.aop_dir,
5897 AOP(result)->aopu.aop_dir);
5898 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5899 AOP(right)->aopu.aop_dir,
5900 AOP(right)->aopu.aop_dir);
5901 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5902 AOP(result)->aopu.aop_dir,
5903 AOP(result)->aopu.aop_dir);
5905 if( AOP_TYPE(result) == AOP_ACC) {
5906 emitpcode(POC_MOVLW, popGetLit(0));
5907 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5908 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5909 emitpcode(POC_MOVLW, popGetLit(1));
5913 emitpcode(POC_BCF, popGet(AOP(result),0));
5914 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5915 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5916 emitpcode(POC_BSF, popGet(AOP(result),0));
5918 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5919 AOP(result)->aopu.aop_dir,
5920 AOP(result)->aopu.aop_dir);
5921 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5922 AOP(right)->aopu.aop_dir,
5923 AOP(right)->aopu.aop_dir);
5924 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5925 AOP(left)->aopu.aop_dir,
5926 AOP(left)->aopu.aop_dir);
5927 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5928 AOP(result)->aopu.aop_dir,
5929 AOP(result)->aopu.aop_dir);
5934 symbol *tlbl = newiTempLabel(NULL);
5935 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5938 emitpcode(POC_BCF, popGet(AOP(result),0));
5939 if( AOP_TYPE(right) == AOP_ACC) {
5940 emitpcode(POC_IORLW, popGetLit(0));
5942 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5943 emitpcode(POC_BSF, popGet(AOP(result),0));
5948 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5949 pic14_emitcode(";XXX setb","c");
5950 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5951 AOP(left)->aopu.aop_dir,tlbl->key+100);
5952 pic14_toBoolean(right);
5953 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5954 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5955 jmpTrueOrFalse(ifx, tlbl);
5959 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5966 pic14_outBitC(result);
5968 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5969 genIfxJump(ifx, "c");
5973 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5974 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5975 if((AOP_TYPE(right) == AOP_LIT) &&
5976 (AOP_TYPE(result) == AOP_CRY) &&
5977 (AOP_TYPE(left) != AOP_CRY)){
5979 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5982 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5984 continueIfTrue(ifx);
5987 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5988 // lit = 0, result = boolean(left)
5990 pic14_emitcode(";XXX setb","c");
5991 pic14_toBoolean(right);
5993 symbol *tlbl = newiTempLabel(NULL);
5994 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5996 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5998 genIfxJump (ifx,"a");
6002 pic14_outBitC(result);
6006 /* if left is same as result */
6007 if(pic14_sameRegs(AOP(result),AOP(left))){
6009 for(;size--; offset++,lit>>=8) {
6010 if(AOP_TYPE(right) == AOP_LIT){
6011 if((lit & 0xff) == 0)
6012 /* or'ing with 0 has no effect */
6015 int p = my_powof2(lit & 0xff);
6017 /* only one bit is set in the literal, so use a bsf instruction */
6019 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6021 if(know_W != (int)(lit & 0xff))
6022 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
6023 know_W = lit & 0xff;
6024 emitpcode(POC_IORWF, popGet(AOP(left),offset));
6029 if (AOP_TYPE(left) == AOP_ACC) {
6030 emitpcode(POC_IORFW, popGet(AOP(right),offset));
6031 pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6033 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
6034 emitpcode(POC_IORWF, popGet(AOP(left),offset));
6036 pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6037 pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
6043 // left & result in different registers
6044 if(AOP_TYPE(result) == AOP_CRY){
6046 // if(size), result in bit
6047 // if(!size && ifx), conditional oper: if(left | right)
6048 symbol *tlbl = newiTempLabel(NULL);
6049 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6050 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6054 pic14_emitcode(";XXX setb","c");
6056 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6057 pic14_emitcode(";XXX orl","a,%s",
6058 aopGet(AOP(left),offset,FALSE,FALSE));
6059 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6064 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6065 pic14_outBitC(result);
6067 jmpTrueOrFalse(ifx, tlbl);
6068 } else for(;(size--);offset++){
6070 // result = left | right
6071 if(AOP_TYPE(right) == AOP_LIT){
6072 int t = (lit >> (offset*8)) & 0x0FFL;
6075 if (AOP_TYPE(left) != AOP_ACC) {
6076 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
6078 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6082 if (AOP_TYPE(left) == AOP_ACC) {
6083 emitpcode(POC_IORLW, popGetLit(t));
6085 emitpcode(POC_MOVLW, popGetLit(t));
6086 emitpcode(POC_IORFW, popGet(AOP(left),offset));
6088 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6093 // faster than result <- left, anl result,right
6094 // and better if result is SFR
6095 if (AOP_TYPE(left) == AOP_ACC) {
6096 emitpcode(POC_IORFW,popGet(AOP(right),offset));
6098 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6099 emitpcode(POC_IORFW,popGet(AOP(left),offset));
6101 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6106 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6107 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6108 freeAsmop(result,NULL,ic,TRUE);
6111 /*-----------------------------------------------------------------*/
6112 /* genXor - code for xclusive or */
6113 /*-----------------------------------------------------------------*/
6114 static void genXor (iCode *ic, iCode *ifx)
6116 operand *left, *right, *result;
6118 unsigned long lit = 0L;
6121 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6123 aopOp((left = IC_LEFT(ic)),ic,FALSE);
6124 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6125 aopOp((result=IC_RESULT(ic)),ic,TRUE);
6127 /* if left is a literal & right is not ||
6128 if left needs acc & right does not */
6129 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6130 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6131 operand *tmp = right ;
6136 /* if result = right then exchange them */
6137 if(pic14_sameRegs(AOP(result),AOP(right))){
6138 operand *tmp = right ;
6143 /* if right is bit then exchange them */
6144 if (AOP_TYPE(right) == AOP_CRY &&
6145 AOP_TYPE(left) != AOP_CRY){
6146 operand *tmp = right ;
6150 if(AOP_TYPE(right) == AOP_LIT)
6151 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6153 size = AOP_SIZE(result);
6157 if (AOP_TYPE(left) == AOP_CRY){
6158 if(AOP_TYPE(right) == AOP_LIT){
6159 // c = bit & literal;
6161 // lit>>1 != 0 => result = 1
6162 if(AOP_TYPE(result) == AOP_CRY){
6164 {emitpcode(POC_BSF, popGet(AOP(result),offset));
6165 pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6167 continueIfTrue(ifx);
6170 pic14_emitcode("setb","c");
6174 // lit == 0, result = left
6175 if(size && pic14_sameRegs(AOP(result),AOP(left)))
6177 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6179 // lit == 1, result = not(left)
6180 if(size && pic14_sameRegs(AOP(result),AOP(left))){
6181 emitpcode(POC_MOVLW, popGet(AOP(result),offset));
6182 emitpcode(POC_XORWF, popGet(AOP(result),offset));
6183 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6186 assert ( !"incomplete genXor" );
6187 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6188 pic14_emitcode("cpl","c");
6195 symbol *tlbl = newiTempLabel(NULL);
6196 if (AOP_TYPE(right) == AOP_CRY){
6198 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6201 int sizer = AOP_SIZE(right);
6203 // if val>>1 != 0, result = 1
6204 pic14_emitcode("setb","c");
6206 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6208 // test the msb of the lsb
6209 pic14_emitcode("anl","a,#0xfe");
6210 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6214 pic14_emitcode("rrc","a");
6216 pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6217 pic14_emitcode("cpl","c");
6218 pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6223 pic14_outBitC(result);
6225 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6226 genIfxJump(ifx, "c");
6230 if(pic14_sameRegs(AOP(result),AOP(left))){
6231 /* if left is same as result */
6232 for(;size--; offset++) {
6233 if(AOP_TYPE(right) == AOP_LIT){
6234 int t = (lit >> (offset*8)) & 0x0FFL;
6238 if (IS_AOP_PREG(left)) {
6239 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6240 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6241 aopPut(AOP(result),"a",offset);
6243 emitpcode(POC_MOVLW, popGetLit(t));
6244 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6245 pic14_emitcode("xrl","%s,%s",
6246 aopGet(AOP(left),offset,FALSE,TRUE),
6247 aopGet(AOP(right),offset,FALSE,FALSE));
6250 if (AOP_TYPE(left) == AOP_ACC)
6251 pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6253 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6254 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6256 if (IS_AOP_PREG(left)) {
6257 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6258 aopPut(AOP(result),"a",offset);
6260 pic14_emitcode("xrl","%s,a",
6261 aopGet(AOP(left),offset,FALSE,TRUE));
6267 // left & result in different registers
6268 if(AOP_TYPE(result) == AOP_CRY){
6270 // if(size), result in bit
6271 // if(!size && ifx), conditional oper: if(left ^ right)
6272 symbol *tlbl = newiTempLabel(NULL);
6273 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6275 pic14_emitcode("setb","c");
6277 if((AOP_TYPE(right) == AOP_LIT) &&
6278 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6279 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6281 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6282 pic14_emitcode("xrl","a,%s",
6283 aopGet(AOP(left),offset,FALSE,FALSE));
6285 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6290 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6291 pic14_outBitC(result);
6293 jmpTrueOrFalse(ifx, tlbl);
6294 } else for(;(size--);offset++){
6296 // result = left & right
6297 if(AOP_TYPE(right) == AOP_LIT){
6298 int t = (lit >> (offset*8)) & 0x0FFL;
6301 if (AOP_TYPE(left) != AOP_ACC) {
6302 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6304 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6305 pic14_emitcode("movf","%s,w",
6306 aopGet(AOP(left),offset,FALSE,FALSE));
6307 pic14_emitcode("movwf","%s",
6308 aopGet(AOP(result),offset,FALSE,FALSE));
6311 if (AOP_TYPE(left) == AOP_ACC) {
6312 emitpcode(POC_XORLW, popGetLit(t));
6314 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6316 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6319 if (AOP_TYPE(left) == AOP_ACC) {
6320 emitpcode(POC_XORLW, popGetLit(t));
6322 emitpcode(POC_MOVLW, popGetLit(t));
6323 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6325 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6326 pic14_emitcode("movlw","0x%x",t);
6327 pic14_emitcode("xorwf","%s,w",
6328 aopGet(AOP(left),offset,FALSE,FALSE));
6329 pic14_emitcode("movwf","%s",
6330 aopGet(AOP(result),offset,FALSE,FALSE));
6336 // faster than result <- left, anl result,right
6337 // and better if result is SFR
6338 if (AOP_TYPE(left) == AOP_ACC) {
6339 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6341 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6342 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6344 if ( AOP_TYPE(result) != AOP_ACC){
6345 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6351 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6352 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6353 freeAsmop(result,NULL,ic,TRUE);
6356 /*-----------------------------------------------------------------*/
6357 /* genInline - write the inline code out */
6358 /*-----------------------------------------------------------------*/
6359 static void genInline (iCode *ic)
6361 char *buffer, *bp, *bp1;
6364 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6366 _G.inLine += (!options.asmpeep);
6368 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6369 strcpy(buffer,IC_INLINE(ic));
6371 /* emit each line as a code */
6377 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6385 /* print label, use this special format with NULL directive
6386 * to denote that the argument should not be indented with tab */
6387 addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6394 if ((bp1 != bp) && *bp1)
6395 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6399 _G.inLine -= (!options.asmpeep);
6402 /*-----------------------------------------------------------------*/
6403 /* genRRC - rotate right with carry */
6404 /*-----------------------------------------------------------------*/
6405 static void genRRC (iCode *ic)
6407 operand *left , *result ;
6408 int size, offset = 0, same;
6411 /* rotate right with carry */
6413 result=IC_RESULT(ic);
6414 aopOp (left,ic,FALSE);
6415 aopOp (result,ic,FALSE);
6417 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6419 same = pic14_sameRegs(AOP(result),AOP(left));
6421 size = AOP_SIZE(result);
6423 /* get the lsb and put it into the carry */
6424 emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6431 emitpcode(POC_RRF, popGet(AOP(left),offset));
6433 emitpcode(POC_RRFW, popGet(AOP(left),offset));
6434 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6440 freeAsmop(left,NULL,ic,TRUE);
6441 freeAsmop(result,NULL,ic,TRUE);
6444 /*-----------------------------------------------------------------*/
6445 /* genRLC - generate code for rotate left with carry */
6446 /*-----------------------------------------------------------------*/
6447 static void genRLC (iCode *ic)
6449 operand *left , *result ;
6450 int size, offset = 0;
6454 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6455 /* rotate right with carry */
6457 result=IC_RESULT(ic);
6458 aopOp (left,ic,FALSE);
6459 aopOp (result,ic,FALSE);
6461 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6463 same = pic14_sameRegs(AOP(result),AOP(left));
6465 /* move it to the result */
6466 size = AOP_SIZE(result);
6468 /* get the msb and put it into the carry */
6469 emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6476 emitpcode(POC_RLF, popGet(AOP(left),offset));
6478 emitpcode(POC_RLFW, popGet(AOP(left),offset));
6479 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6486 freeAsmop(left,NULL,ic,TRUE);
6487 freeAsmop(result,NULL,ic,TRUE);
6490 /*-----------------------------------------------------------------*/
6491 /* genGetHbit - generates code get highest order bit */
6492 /*-----------------------------------------------------------------*/
6493 static void genGetHbit (iCode *ic)
6495 operand *left, *result;
6497 result=IC_RESULT(ic);
6498 aopOp (left,ic,FALSE);
6499 aopOp (result,ic,FALSE);
6502 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6503 /* get the highest order byte into a */
6504 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6505 if(AOP_TYPE(result) == AOP_CRY){
6506 pic14_emitcode("rlc","a");
6507 pic14_outBitC(result);
6510 pic14_emitcode("rl","a");
6511 pic14_emitcode("anl","a,#0x01");
6512 pic14_outAcc(result);
6516 freeAsmop(left,NULL,ic,TRUE);
6517 freeAsmop(result,NULL,ic,TRUE);
6520 /*-----------------------------------------------------------------*/
6521 /* AccRol - rotate left accumulator by known count */
6522 /*-----------------------------------------------------------------*/
6523 static void AccRol (operand *op,int offset,int shCount)
6526 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6527 shCount &= 0x0007; // shCount : 0..7
6532 pic14_emitcode("rl","a");
6533 emitpcode(POC_RLF,popGet(AOP(op),offset));
6536 pic14_emitcode("rl","a");
6537 pic14_emitcode("rl","a");
6538 emitpcode(POC_RLF,popGet(AOP(op),offset));
6539 emitpcode(POC_RLF,popGet(AOP(op),offset));
6542 pic14_emitcode("swap","a");
6543 pic14_emitcode("rr","a");
6544 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6545 emitpcode(POC_RRF,popGet(AOP(op),offset));
6548 pic14_emitcode("swap","a");
6549 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6552 pic14_emitcode("swap","a");
6553 pic14_emitcode("rl","a");
6554 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6555 emitpcode(POC_RLF,popGet(AOP(op),offset));
6558 pic14_emitcode("rr","a");
6559 pic14_emitcode("rr","a");
6560 emitpcode(POC_RRF,popGet(AOP(op),offset));
6561 emitpcode(POC_RRF,popGet(AOP(op),offset));
6564 pic14_emitcode("rr","a");
6565 emitpcode(POC_RRF,popGet(AOP(op),offset));
6570 /*-----------------------------------------------------------------*/
6571 /* AccLsh - left shift accumulator by known count */
6572 /*-----------------------------------------------------------------*/
6573 static void AccLsh (operand *op,int offset,int shCount)
6576 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6581 emitpcode (POC_RLF, popGet (AOP(op), 0));
6583 /* rotate left accumulator */
6584 AccRol(op,offset,shCount);
6585 /* and kill the lower order bits */
6586 emitpcode(POC_MOVLW,popGetLit(SLMask[shCount]));
6587 emitpcode (POC_ANDWF, popGet (AOP(op),0));
6592 /*-----------------------------------------------------------------*/
6593 /* AccRsh - right shift accumulator by known count */
6594 /*-----------------------------------------------------------------*/
6595 static void AccRsh (operand *op,int offset,int shCount)
6598 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6602 emitpcode (POC_RRF, popGet (AOP(op), 0));
6604 /* rotate right accumulator */
6605 AccRol(op,offset,8 - shCount);
6606 /* and kill the higher order bits */
6607 emitpcode (POC_MOVLW, popGetLit (SRMask[shCount]));
6608 emitpcode (POC_ANDWF, popGet (AOP(op),0));
6614 /*-----------------------------------------------------------------*/
6615 /* AccSRsh - signed right shift accumulator by known count */
6616 /*-----------------------------------------------------------------*/
6617 static void AccSRsh (int shCount)
6620 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6623 pic14_emitcode("mov","c,acc.7");
6624 pic14_emitcode("rrc","a");
6625 } else if(shCount == 2){
6626 pic14_emitcode("mov","c,acc.7");
6627 pic14_emitcode("rrc","a");
6628 pic14_emitcode("mov","c,acc.7");
6629 pic14_emitcode("rrc","a");
6631 tlbl = newiTempLabel(NULL);
6632 /* rotate right accumulator */
6633 AccRol(8 - shCount);
6634 /* and kill the higher order bits */
6635 pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6636 pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6637 pic14_emitcode("orl","a,#0x%02x",
6638 (unsigned char)~SRMask[shCount]);
6639 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6644 /*-----------------------------------------------------------------*/
6645 /* shiftR1Left2Result - shift right one byte from left to result */
6646 /*-----------------------------------------------------------------*/
6647 static void shiftR1Left2ResultSigned (operand *left, int offl,
6648 operand *result, int offr,
6654 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6656 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6660 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6662 emitpcode(POC_RRF, popGet(AOP(result),offr));
6664 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6665 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6671 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6673 emitpcode(POC_RRF, popGet(AOP(result),offr));
6675 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6676 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6678 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6679 emitpcode(POC_RRF, popGet(AOP(result),offr));
6685 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6687 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6688 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6691 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6692 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6693 emitpcode(POC_ANDLW, popGetLit(0x1f));
6695 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6696 emitpcode(POC_IORLW, popGetLit(0xe0));
6698 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6702 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6703 emitpcode(POC_ANDLW, popGetLit(0x0f));
6704 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6705 emitpcode(POC_IORLW, popGetLit(0xf0));
6706 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6710 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6712 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6713 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6715 emitpcode(POC_RRFW, popGet(AOP(result),offr));
6716 emitpcode(POC_ANDLW, popGetLit(0x07));
6717 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6718 emitpcode(POC_IORLW, popGetLit(0xf8));
6719 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6724 emitpcode(POC_MOVLW, popGetLit(0x00));
6725 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6726 emitpcode(POC_MOVLW, popGetLit(0xfe));
6727 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6728 emitpcode(POC_IORLW, popGetLit(0x01));
6729 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6731 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6732 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6733 emitpcode(POC_DECF, popGet(AOP(result),offr));
6734 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6735 emitpcode(POC_BCF, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6741 emitpcode(POC_MOVLW, popGetLit(0x00));
6742 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6743 emitpcode(POC_MOVLW, popGetLit(0xff));
6744 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6746 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6747 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6748 emitpcode(POC_DECF, popGet(AOP(result),offr));
6756 /*-----------------------------------------------------------------*/
6757 /* shiftR1Left2Result - shift right one byte from left to result */
6758 /*-----------------------------------------------------------------*/
6759 static void shiftR1Left2Result (operand *left, int offl,
6760 operand *result, int offr,
6761 int shCount, int sign)
6766 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6768 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6770 /* Copy the msb into the carry if signed. */
6772 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6782 emitpcode(POC_RRF, popGet(AOP(result),offr));
6784 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6785 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6791 emitpcode(POC_RRF, popGet(AOP(result),offr));
6793 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6794 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6797 emitpcode(POC_RRF, popGet(AOP(result),offr));
6802 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6804 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6805 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6808 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6809 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6810 emitpcode(POC_ANDLW, popGetLit(0x1f));
6811 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6815 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6816 emitpcode(POC_ANDLW, popGetLit(0x0f));
6817 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6821 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6822 emitpcode(POC_ANDLW, popGetLit(0x0f));
6823 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6825 emitpcode(POC_RRF, popGet(AOP(result),offr));
6830 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6831 emitpcode(POC_ANDLW, popGetLit(0x80));
6832 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6833 emitpcode(POC_RLF, popGet(AOP(result),offr));
6834 emitpcode(POC_RLF, popGet(AOP(result),offr));
6839 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6840 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6841 emitpcode(POC_RLF, popGet(AOP(result),offr));
6850 /*-----------------------------------------------------------------*/
6851 /* shiftL1Left2Result - shift left one byte from left to result */
6852 /*-----------------------------------------------------------------*/
6853 static void shiftL1Left2Result (operand *left, int offl,
6854 operand *result, int offr, int shCount)
6860 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6862 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6863 DEBUGpic14_emitcode ("; ***","same = %d",same);
6864 // l = aopGet(AOP(left),offl,FALSE,FALSE);
6866 /* shift left accumulator */
6867 //AccLsh(shCount); // don't comment out just yet...
6868 // aopPut(AOP(result),"a",offr);
6872 /* Shift left 1 bit position */
6873 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6875 emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6877 emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6878 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6882 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6883 emitpcode(POC_ANDLW,popGetLit(0x7e));
6884 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6885 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6888 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6889 emitpcode(POC_ANDLW,popGetLit(0x3e));
6890 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6891 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6892 emitpcode(POC_RLF, popGet(AOP(result),offr));
6895 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6896 emitpcode(POC_ANDLW, popGetLit(0xf0));
6897 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6900 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6901 emitpcode(POC_ANDLW, popGetLit(0xf0));
6902 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6903 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6906 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6907 emitpcode(POC_ANDLW, popGetLit(0x30));
6908 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6909 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6910 emitpcode(POC_RLF, popGet(AOP(result),offr));
6913 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6914 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6915 emitpcode(POC_RRF, popGet(AOP(result),offr));
6919 DEBUGpic14_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6925 /*-----------------------------------------------------------------*/
6926 /* movLeft2Result - move byte from left to result */
6927 /*-----------------------------------------------------------------*/
6928 static void movLeft2Result (operand *left, int offl,
6929 operand *result, int offr)
6933 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6934 if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6935 l = aopGet(AOP(left),offl,FALSE,FALSE);
6937 if (*l == '@' && (IS_AOP_PREG(result))) {
6938 pic14_emitcode("mov","a,%s",l);
6939 aopPut(AOP(result),"a",offr);
6941 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6942 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6947 /*-----------------------------------------------------------------*/
6948 /* shiftLeft_Left2ResultLit - shift left by known count */
6949 /*-----------------------------------------------------------------*/
6951 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6953 int size, same, offr, i;
6955 size = AOP_SIZE(left);
6956 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6958 same = pic14_sameRegs (AOP(left), AOP(result));
6961 shCount = shCount & 0x07;
6967 case 0: /* takes 0 or 2N cycles (for offr==0) */
6968 if (!same || offr) {
6969 for (i=size-1; i >= 0; i--)
6970 movLeft2Result (left, i, result, offr + i);
6974 case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6976 shiftLeft_Left2ResultLit (left, result, 8 * offr);
6977 shiftLeft_Left2ResultLit (result, result, shCount);
6978 return; /* prevent clearing result again */
6981 for (i=0; i < size; i++) {
6982 if (same && !offr) {
6983 emitpcode (POC_RLF, popGet (AOP(left), i));
6985 emitpcode (POC_RLFW, popGet (AOP(left), i));
6986 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6992 case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
6993 /* works in-place/with offr as well */
6994 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
6995 emitpcode (POC_ANDLW, popGetLit (0xF0));
6996 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
6998 for (i = size - 2; i >= 0; i--)
7000 emitpcode (POC_SWAPFW, popGet (AOP(left), i));
7001 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7002 emitpcode (POC_ANDLW, popGetLit (0x0F));
7003 emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
7004 emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
7008 case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
7009 /* works in-place/with offr as well */
7010 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
7011 for (i = size-2; i >= 0; i--) {
7012 emitpcode (POC_RRFW, popGet (AOP(left), i));
7013 emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
7015 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7016 emitpcode (POC_RRF, popGet (AOP(result), offr));
7020 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
7021 shiftLeft_Left2ResultLit (result, result, 1);
7022 return; /* prevent clearing result again */
7028 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7032 /*-----------------------------------------------------------------*/
7033 /* shiftRight_Left2ResultLit - shift right by known count */
7034 /*-----------------------------------------------------------------*/
7036 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
7038 int size, same, offr, i;
7040 size = AOP_SIZE(left);
7041 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7043 same = pic14_sameRegs (AOP(left), AOP(result));
7046 shCount = shCount & 0x07;
7054 case 0: /* takes 0 or 2N cycles (for offr==0) */
7055 if (!same || offr) {
7056 for (i=0; i < size; i++)
7057 movLeft2Result (left, i + offr, result, i);
7061 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7062 emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7064 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7065 shiftRight_Left2ResultLit (result, result, shCount, sign);
7066 return; /* prevent sign-extending result again */
7070 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7073 for (i = size-1; i >= 0; i--) {
7074 if (same && !offr) {
7075 emitpcode (POC_RRF, popGet (AOP(left), i));
7077 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7078 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7084 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7085 /* works in-place/with offr as well */
7086 emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7087 emitpcode (POC_ANDLW, popGetLit (0x0F));
7088 emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7090 for (i = 1; i < size; i++)
7092 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7093 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7094 emitpcode (POC_ANDLW, popGetLit (0xF0));
7095 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7096 emitpcode (POC_XORWF, popGet (AOP(result), i));
7101 emitpcode (POC_MOVLW, popGetLit (0xF0));
7102 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7103 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7107 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7108 /* works in-place/with offr as well */
7109 emitpcode (POC_RLFW, popGet (AOP(left), offr));
7110 for (i = 0; i < size-1; i++) {
7111 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7112 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7114 emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7116 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7119 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7124 shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7125 shiftRight_Left2ResultLit (result, result, 1, sign);
7126 return; /* prevent sign extending result again */
7131 addSign (result, size, sign);
7135 /*-----------------------------------------------------------------*/
7136 /* shiftL2Left2Result - shift left two bytes from left to result */
7137 /*-----------------------------------------------------------------*/
7138 static void shiftL2Left2Result (operand *left, int offl,
7139 operand *result, int offr, int shCount)
7143 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7145 if(pic14_sameRegs(AOP(result), AOP(left))) {
7153 emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7154 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7155 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7159 emitpcode(POC_RLF, popGet(AOP(result),offr));
7160 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7166 emitpcode(POC_MOVLW, popGetLit(0x0f));
7167 emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7168 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7169 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7170 emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7171 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7172 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7174 emitpcode(POC_RLF, popGet(AOP(result),offr));
7175 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7179 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7180 emitpcode(POC_RRF, popGet(AOP(result),offr));
7181 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7182 emitpcode(POC_RRF, popGet(AOP(result),offr));
7183 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7184 emitpcode(POC_ANDLW,popGetLit(0xc0));
7185 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7186 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7187 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7188 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7191 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7192 emitpcode(POC_RRFW, popGet(AOP(result),offr));
7193 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7194 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7195 emitpcode(POC_RRF, popGet(AOP(result),offr));
7205 /* note, use a mov/add for the shift since the mov has a
7206 chance of getting optimized out */
7207 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7208 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7209 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7210 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7211 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7215 emitpcode(POC_RLF, popGet(AOP(result),offr));
7216 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7222 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7223 emitpcode(POC_ANDLW, popGetLit(0xF0));
7224 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7225 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7226 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7227 emitpcode(POC_ANDLW, popGetLit(0xF0));
7228 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7229 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7233 emitpcode(POC_RLF, popGet(AOP(result),offr));
7234 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7238 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7239 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7240 emitpcode(POC_RRFW, popGet(AOP(result),offl));
7241 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7243 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7244 emitpcode(POC_RRF, popGet(AOP(result),offr));
7245 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7246 emitpcode(POC_ANDLW,popGetLit(0xc0));
7247 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7248 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7249 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7250 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7253 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7254 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7255 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7256 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7257 emitpcode(POC_RRF, popGet(AOP(result),offr));
7263 /*-----------------------------------------------------------------*/
7264 /* shiftR2Left2Result - shift right two bytes from left to result */
7265 /*-----------------------------------------------------------------*/
7266 static void shiftR2Left2Result (operand *left, int offl,
7267 operand *result, int offr,
7268 int shCount, int sign)
7273 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7274 same = pic14_sameRegs(AOP(result), AOP(left));
7276 if(same && ((offl + MSB16) == offr)){
7278 /* don't crash result[offr] */
7279 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7280 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7283 movLeft2Result(left,offl, result, offr);
7284 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7287 /* a:x >> shCount (x = lsb(result))*/
7290 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7292 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7301 emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7306 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7307 emitpcode(POC_RRF,popGet(AOP(result),offr));
7309 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7310 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7311 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7312 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7317 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7320 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7321 emitpcode(POC_RRF,popGet(AOP(result),offr));
7328 emitpcode(POC_MOVLW, popGetLit(0xf0));
7329 emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7330 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7332 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7333 emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7334 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7335 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7337 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7338 emitpcode(POC_ANDLW, popGetLit(0x0f));
7339 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7341 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7342 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7343 emitpcode(POC_ANDLW, popGetLit(0xf0));
7344 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7345 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7349 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7350 emitpcode(POC_RRF, popGet(AOP(result),offr));
7354 emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7355 emitpcode(POC_BTFSC,
7356 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7357 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7365 emitpcode(POC_RLF, popGet(AOP(result),offr));
7366 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7368 emitpcode(POC_RLF, popGet(AOP(result),offr));
7369 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7370 emitpcode(POC_RLFW, popGet(AOP(result),offr));
7371 emitpcode(POC_ANDLW,popGetLit(0x03));
7373 emitpcode(POC_BTFSC,
7374 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7375 emitpcode(POC_IORLW,popGetLit(0xfc));
7377 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7378 emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7379 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7380 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7382 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7383 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7384 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7385 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7386 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7387 emitpcode(POC_RLF, popGet(AOP(result),offr));
7388 emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7389 emitpcode(POC_ANDLW,popGetLit(0x03));
7391 emitpcode(POC_BTFSC,
7392 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7393 emitpcode(POC_IORLW,popGetLit(0xfc));
7395 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7396 //emitpcode(POC_RLF, popGet(AOP(result),offr));
7403 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7404 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7405 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7406 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7409 emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7411 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7415 /*-----------------------------------------------------------------*/
7416 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7417 /*-----------------------------------------------------------------*/
7418 static void shiftLLeftOrResult (operand *left, int offl,
7419 operand *result, int offr, int shCount)
7422 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7424 /* shift left accumulator */
7425 AccLsh(left,offl,shCount);
7426 /* or with result */
7427 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7428 assert ( !"broken (modifies left, fails for left==result))" );
7431 /*-----------------------------------------------------------------*/
7432 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7433 /*-----------------------------------------------------------------*/
7434 static void shiftRLeftOrResult (operand *left, int offl,
7435 operand *result, int offr, int shCount)
7438 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7440 /* shift right accumulator */
7441 AccRsh(left,offl,shCount);
7442 /* or with result */
7443 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7444 assert ( !"broken (modifies left, fails for left==result))" );
7447 /*-----------------------------------------------------------------*/
7448 /* genlshOne - left shift a one byte quantity by known count */
7449 /*-----------------------------------------------------------------*/
7450 static void genlshOne (operand *result, operand *left, int shCount)
7453 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7454 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7457 /*-----------------------------------------------------------------*/
7458 /* genlshTwo - left shift two bytes by known amount != 0 */
7459 /*-----------------------------------------------------------------*/
7460 static void genlshTwo (operand *result,operand *left, int shCount)
7465 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7466 size = pic14_getDataSize(result);
7468 /* if shCount >= 8 */
7474 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7476 movLeft2Result(left, LSB, result, MSB16);
7478 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7481 /* 1 <= shCount <= 7 */
7484 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7486 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7490 /*-----------------------------------------------------------------*/
7491 /* shiftLLong - shift left one long from left to result */
7492 /* offl = LSB or MSB16 */
7493 /*-----------------------------------------------------------------*/
7494 static void shiftLLong (operand *left, operand *result, int offr )
7497 int size = AOP_SIZE(result);
7500 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7501 if(size >= LSB+offr){
7502 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7504 pic14_emitcode("add","a,acc");
7505 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7506 size >= MSB16+offr && offr != LSB )
7507 pic14_emitcode("xch","a,%s",
7508 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7510 aopPut(AOP(result),"a",LSB+offr);
7513 if(size >= MSB16+offr){
7514 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7515 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7518 pic14_emitcode("rlc","a");
7519 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7520 size >= MSB24+offr && offr != LSB)
7521 pic14_emitcode("xch","a,%s",
7522 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7524 aopPut(AOP(result),"a",MSB16+offr);
7527 if(size >= MSB24+offr){
7528 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7529 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7532 pic14_emitcode("rlc","a");
7533 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7534 size >= MSB32+offr && offr != LSB )
7535 pic14_emitcode("xch","a,%s",
7536 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7538 aopPut(AOP(result),"a",MSB24+offr);
7541 if(size > MSB32+offr){
7542 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7543 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7546 pic14_emitcode("rlc","a");
7547 aopPut(AOP(result),"a",MSB32+offr);
7550 aopPut(AOP(result),zero,LSB);
7553 /*-----------------------------------------------------------------*/
7554 /* genlshFour - shift four byte by a known amount != 0 */
7555 /*-----------------------------------------------------------------*/
7556 static void genlshFour (operand *result, operand *left, int shCount)
7561 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7562 size = AOP_SIZE(result);
7564 /* if shifting more that 3 bytes */
7565 if (shCount >= 24 ) {
7568 /* lowest order of left goes to the highest
7569 order of the destination */
7570 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7572 movLeft2Result(left, LSB, result, MSB32);
7573 aopPut(AOP(result),zero,LSB);
7574 aopPut(AOP(result),zero,MSB16);
7575 aopPut(AOP(result),zero,MSB32);
7579 /* more than two bytes */
7580 else if ( shCount >= 16 ) {
7581 /* lower order two bytes goes to higher order two bytes */
7583 /* if some more remaining */
7585 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7587 movLeft2Result(left, MSB16, result, MSB32);
7588 movLeft2Result(left, LSB, result, MSB24);
7590 aopPut(AOP(result),zero,MSB16);
7591 aopPut(AOP(result),zero,LSB);
7595 /* if more than 1 byte */
7596 else if ( shCount >= 8 ) {
7597 /* lower order three bytes goes to higher order three bytes */
7601 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7603 movLeft2Result(left, LSB, result, MSB16);
7605 else{ /* size = 4 */
7607 movLeft2Result(left, MSB24, result, MSB32);
7608 movLeft2Result(left, MSB16, result, MSB24);
7609 movLeft2Result(left, LSB, result, MSB16);
7610 aopPut(AOP(result),zero,LSB);
7612 else if(shCount == 1)
7613 shiftLLong(left, result, MSB16);
7615 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7616 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7617 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7618 aopPut(AOP(result),zero,LSB);
7623 /* 1 <= shCount <= 7 */
7624 else if(shCount <= 2){
7625 shiftLLong(left, result, LSB);
7627 shiftLLong(result, result, LSB);
7629 /* 3 <= shCount <= 7, optimize */
7631 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7632 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7633 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7639 /*-----------------------------------------------------------------*/
7640 /* genLeftShiftLiteral - left shifting by known count */
7641 /*-----------------------------------------------------------------*/
7642 static void genLeftShiftLiteral (operand *left,
7647 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7651 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7652 freeAsmop(right,NULL,ic,TRUE);
7654 aopOp(left,ic,FALSE);
7655 aopOp(result,ic,FALSE);
7657 size = getSize(operandType(result));
7660 pic14_emitcode("; shift left ","result %d, left %d",size,
7664 /* I suppose that the left size >= result size */
7667 movLeft2Result(left, size, result, size);
7671 else if(shCount >= (size * 8))
7673 aopPut(AOP(result),zero,size);
7677 genlshOne (result,left,shCount);
7682 genlshTwo (result,left,shCount);
7686 genlshFour (result,left,shCount);
7690 freeAsmop(left,NULL,ic,TRUE);
7691 freeAsmop(result,NULL,ic,TRUE);
7695 /*-----------------------------------------------------------------*
7696 * genMultiAsm - repeat assembly instruction for size of register.
7697 * if endian == 1, then the high byte (i.e base address + size of
7698 * register) is used first else the low byte is used first;
7699 *-----------------------------------------------------------------*/
7700 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7706 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7719 emitpcode(poc, popGet(AOP(reg),offset));
7724 /*-----------------------------------------------------------------*/
7725 /* genLeftShift - generates code for left shifting */
7726 /*-----------------------------------------------------------------*/
7727 static void genLeftShift (iCode *ic)
7729 operand *left,*right, *result;
7731 unsigned long lit = 0L;
7733 symbol *tlbl , *tlbl1;
7737 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7739 right = IC_RIGHT(ic);
7741 result = IC_RESULT(ic);
7743 aopOp(right,ic,FALSE);
7744 aopOp(left,ic,FALSE);
7745 aopOp(result,ic,FALSE);
7748 /* if the shift count is known then do it
7749 as efficiently as possible */
7750 if (AOP_TYPE(right) == AOP_LIT) {
7751 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7755 /* shift count is unknown then we have to form
7756 a loop get the loop count in B : Note: we take
7757 only the lower order byte since shifting
7758 more that 32 bits make no sense anyway, ( the
7759 largest size of an object can be only 32 bits ) */
7761 /* this code fails for RIGHT == RESULT */
7762 assert (!pic14_sameRegs (AOP(right), AOP(result)));
7764 /* now move the left to the result if they are not the
7766 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
7767 AOP_SIZE(result) > 1) {
7769 size = AOP_SIZE(result);
7772 l = aopGet(AOP(left),offset,FALSE,TRUE);
7773 if (*l == '@' && (IS_AOP_PREG(result))) {
7775 pic14_emitcode("mov","a,%s",l);
7776 aopPut(AOP(result),"a",offset);
7778 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
7779 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7780 //aopPut(AOP(result),l,offset);
7786 if(AOP_TYPE(left) == AOP_LIT)
7787 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7789 size = AOP_SIZE(result);
7791 /* if it is only one byte then */
7793 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7794 emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7795 emitpcode(POC_ANDLW, popGetLit(0xf0));
7796 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7797 emitpcode(POC_MOVFW, popGet(AOP(left),0));
7798 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7799 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7800 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7801 emitpcode(POC_RLFW, popGet(AOP(result),0));
7802 emitpcode(POC_ANDLW, popGetLit(0xfe));
7803 emitpcode(POC_ADDFW, popGet(AOP(result),0));
7804 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7805 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7808 tlbl = newiTempLabel(NULL);
7809 if (!pic14_sameRegs(AOP(left),AOP(result))) {
7810 mov2w (AOP(left), 0);
7811 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7814 emitpcode(POC_COMFW, popGet(AOP(right),0));
7815 emitpcode(POC_RRF, popGet(AOP(result),0));
7816 emitpLabel(tlbl->key);
7817 emitpcode(POC_RLF, popGet(AOP(result),0));
7818 emitpcode(POC_ADDLW, popGetLit(1));
7820 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7825 if (pic14_sameRegs(AOP(left),AOP(result))) {
7827 tlbl = newiTempLabel(NULL);
7828 emitpcode(POC_COMFW, popGet(AOP(right),0));
7829 genMultiAsm(POC_RRF, result, size,1);
7830 emitpLabel(tlbl->key);
7831 genMultiAsm(POC_RLF, result, size,0);
7832 emitpcode(POC_ADDLW, popGetLit(1));
7834 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7838 //tlbl = newiTempLabel(NULL);
7840 //tlbl1 = newiTempLabel(NULL);
7842 //reAdjustPreg(AOP(result));
7844 //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7845 //pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7846 //l = aopGet(AOP(result),offset,FALSE,FALSE);
7848 //pic14_emitcode("add","a,acc");
7849 //aopPut(AOP(result),"a",offset++);
7851 // l = aopGet(AOP(result),offset,FALSE,FALSE);
7853 // pic14_emitcode("rlc","a");
7854 // aopPut(AOP(result),"a",offset++);
7856 //reAdjustPreg(AOP(result));
7858 //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7859 //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7862 tlbl = newiTempLabel(NULL);
7863 tlbl1= newiTempLabel(NULL);
7865 size = AOP_SIZE(result);
7868 pctemp = popGetTempReg(); /* grab a temporary working register. */
7870 emitpcode(POC_MOVFW, popGet(AOP(right),0));
7872 /* offset should be 0, 1 or 3 */
7873 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7875 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
7877 emitpcode(POC_MOVWF, pctemp);
7880 emitpLabel(tlbl->key);
7883 emitpcode(POC_RLF, popGet(AOP(result),0));
7885 emitpcode(POC_RLF, popGet(AOP(result),offset++));
7887 emitpcode(POC_DECFSZ, pctemp);
7888 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7889 emitpLabel(tlbl1->key);
7891 popReleaseTempReg(pctemp);
7895 freeAsmop (right,NULL,ic,TRUE);
7896 freeAsmop(left,NULL,ic,TRUE);
7897 freeAsmop(result,NULL,ic,TRUE);
7901 /*-----------------------------------------------------------------*/
7902 /* genrshOne - right shift a one byte quantity by known count */
7903 /*-----------------------------------------------------------------*/
7904 static void genrshOne (operand *result, operand *left,
7905 int shCount, int sign)
7908 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7909 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7912 /*-----------------------------------------------------------------*/
7913 /* genrshTwo - right shift two bytes by known amount != 0 */
7914 /*-----------------------------------------------------------------*/
7915 static void genrshTwo (operand *result,operand *left,
7916 int shCount, int sign)
7919 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7920 /* if shCount >= 8 */
7924 shiftR1Left2Result(left, MSB16, result, LSB,
7927 movLeft2Result(left, MSB16, result, LSB);
7929 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7932 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7933 emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7937 /* 1 <= shCount <= 7 */
7939 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
7942 /*-----------------------------------------------------------------*/
7943 /* shiftRLong - shift right one long from left to result */
7944 /* offl = LSB or MSB16 */
7945 /*-----------------------------------------------------------------*/
7946 static void shiftRLong (operand *left, int offl,
7947 operand *result, int sign)
7952 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7954 size = AOP_SIZE(left);
7955 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7958 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7962 assert (offl >= 0 && offl < size);
7964 same = pic14_sameRegs (AOP(left), AOP(result));
7966 /* perform the shift */
7969 if (same && !offl) {
7970 emitpcode (POC_RRF, popGet (AOP(result), size));
7972 emitpcode (POC_RRFW, popGet (AOP(left), size));
7973 emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7977 addSign (result, AOP_SIZE(left) - offl, sign);
7980 /*-----------------------------------------------------------------*/
7981 /* genrshFour - shift four byte by a known amount != 0 */
7982 /*-----------------------------------------------------------------*/
7983 static void genrshFour (operand *result, operand *left,
7984 int shCount, int sign)
7987 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7988 /* if shifting more that 3 bytes */
7989 if(shCount >= 24 ) {
7992 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7994 movLeft2Result(left, MSB32, result, LSB);
7996 addSign(result, MSB16, sign);
7998 else if(shCount >= 16){
8001 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8003 movLeft2Result(left, MSB24, result, LSB);
8004 movLeft2Result(left, MSB32, result, MSB16);
8006 addSign(result, MSB24, sign);
8008 else if(shCount >= 8){
8011 shiftRLong(left, MSB16, result, sign);
8012 else if(shCount == 0){
8013 movLeft2Result(left, MSB16, result, LSB);
8014 movLeft2Result(left, MSB24, result, MSB16);
8015 movLeft2Result(left, MSB32, result, MSB24);
8016 addSign(result, MSB32, sign);
8019 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8020 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8021 /* the last shift is signed */
8022 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8023 addSign(result, MSB32, sign);
8026 else{ /* 1 <= shCount <= 7 */
8028 shiftRLong(left, LSB, result, sign);
8030 shiftRLong(result, LSB, result, sign);
8033 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8034 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8035 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8040 /*-----------------------------------------------------------------*/
8041 /* genRightShiftLiteral - right shifting by known count */
8042 /*-----------------------------------------------------------------*/
8043 static void genRightShiftLiteral (operand *left,
8049 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8053 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8054 freeAsmop(right,NULL,ic,TRUE);
8056 aopOp(left,ic,FALSE);
8057 aopOp(result,ic,FALSE);
8060 pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8064 lsize = pic14_getDataSize(left);
8065 res_size = pic14_getDataSize(result);
8066 /* test the LEFT size !!! */
8068 /* I suppose that the left size >= result size */
8071 movLeft2Result(left, res_size, result, res_size);
8074 else if(shCount >= (lsize * 8)){
8077 emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8079 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8080 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8085 emitpcode(POC_MOVLW, popGetLit(0));
8086 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8087 emitpcode(POC_MOVLW, popGetLit(0xff));
8089 emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8094 emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8101 genrshOne (result,left,shCount,sign);
8105 genrshTwo (result,left,shCount,sign);
8109 genrshFour (result,left,shCount,sign);
8117 freeAsmop(left,NULL,ic,TRUE);
8118 freeAsmop(result,NULL,ic,TRUE);
8122 /*-----------------------------------------------------------------*/
8123 /* genSignedRightShift - right shift of signed number */
8124 /*-----------------------------------------------------------------*/
8125 static void genSignedRightShift (iCode *ic)
8127 operand *right, *left, *result;
8130 symbol *tlbl, *tlbl1 ;
8133 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8135 /* we do it the hard way put the shift count in b
8136 and loop thru preserving the sign */
8138 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8140 right = IC_RIGHT(ic);
8142 result = IC_RESULT(ic);
8144 aopOp(right,ic,FALSE);
8145 aopOp(left,ic,FALSE);
8146 aopOp(result,ic,FALSE);
8149 if ( AOP_TYPE(right) == AOP_LIT) {
8150 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8151 //genRightShiftLiteral (left,right,result,ic,1);
8154 /* shift count is unknown then we have to form
8155 a loop get the loop count in B : Note: we take
8156 only the lower order byte since shifting
8157 more that 32 bits make no sense anyway, ( the
8158 largest size of an object can be only 32 bits ) */
8160 //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8161 //pic14_emitcode("inc","b");
8162 //freeAsmop (right,NULL,ic,TRUE);
8163 //aopOp(left,ic,FALSE);
8164 //aopOp(result,ic,FALSE);
8166 /* now move the left to the result if they are not the
8168 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
8169 AOP_SIZE(result) > 1) {
8171 size = AOP_SIZE(result);
8175 l = aopGet(AOP(left),offset,FALSE,TRUE);
8176 if (*l == '@' && IS_AOP_PREG(result)) {
8177 pic14_emitcode("mov","a,%s",l);
8178 aopPut(AOP(result),"a",offset);
8180 aopPut(AOP(result),l,offset);
8182 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8183 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8189 /* mov the highest order bit to OVR */
8190 tlbl = newiTempLabel(NULL);
8191 tlbl1= newiTempLabel(NULL);
8193 size = AOP_SIZE(result);
8196 pctemp = popGetTempReg(); /* grab a temporary working register. */
8198 emitpcode(POC_MOVFW, popGet(AOP(right),0));
8200 /* offset should be 0, 1 or 3 */
8201 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8203 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8205 emitpcode(POC_MOVWF, pctemp);
8208 emitpLabel(tlbl->key);
8210 emitpcode(POC_RLFW, popGet(AOP(result),offset));
8211 emitpcode(POC_RRF, popGet(AOP(result),offset));
8214 emitpcode(POC_RRF, popGet(AOP(result),--offset));
8217 emitpcode(POC_DECFSZ, pctemp);
8218 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8219 emitpLabel(tlbl1->key);
8221 popReleaseTempReg(pctemp);
8223 size = AOP_SIZE(result);
8225 pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8226 pic14_emitcode("rlc","a");
8227 pic14_emitcode("mov","ov,c");
8228 /* if it is only one byte then */
8230 l = aopGet(AOP(left),0,FALSE,FALSE);
8232 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8233 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8234 pic14_emitcode("mov","c,ov");
8235 pic14_emitcode("rrc","a");
8236 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8237 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8238 aopPut(AOP(result),"a",0);
8242 reAdjustPreg(AOP(result));
8243 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8244 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8245 pic14_emitcode("mov","c,ov");
8247 l = aopGet(AOP(result),offset,FALSE,FALSE);
8249 pic14_emitcode("rrc","a");
8250 aopPut(AOP(result),"a",offset--);
8252 reAdjustPreg(AOP(result));
8253 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8254 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8259 freeAsmop(left,NULL,ic,TRUE);
8260 freeAsmop(result,NULL,ic,TRUE);
8261 freeAsmop(right,NULL,ic,TRUE);
8264 /*-----------------------------------------------------------------*/
8265 /* genRightShift - generate code for right shifting */
8266 /*-----------------------------------------------------------------*/
8267 static void genRightShift (iCode *ic)
8269 operand *right, *left, *result;
8273 symbol *tlbl, *tlbl1 ;
8276 /* if signed then we do it the hard way preserve the
8277 sign bit moving it inwards */
8278 retype = getSpec(operandType(IC_RESULT(ic)));
8279 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8281 if (!SPEC_USIGN(retype)) {
8282 genSignedRightShift (ic);
8286 /* signed & unsigned types are treated the same : i.e. the
8287 signed is NOT propagated inwards : quoting from the
8288 ANSI - standard : "for E1 >> E2, is equivalent to division
8289 by 2**E2 if unsigned or if it has a non-negative value,
8290 otherwise the result is implementation defined ", MY definition
8291 is that the sign does not get propagated */
8293 right = IC_RIGHT(ic);
8295 result = IC_RESULT(ic);
8297 aopOp(right,ic,FALSE);
8298 aopOp(left,ic,FALSE);
8299 aopOp(result,ic,FALSE);
8301 /* if the shift count is known then do it
8302 as efficiently as possible */
8303 if (AOP_TYPE(right) == AOP_LIT) {
8304 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 0);
8305 //genRightShiftLiteral (left,right,result,ic, 0);
8309 /* shift count is unknown then we have to form
8310 a loop get the loop count in B : Note: we take
8311 only the lower order byte since shifting
8312 more that 32 bits make no sense anyway, ( the
8313 largest size of an object can be only 32 bits ) */
8315 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8316 pic14_emitcode("inc","b");
8318 /* now move the left to the result if they are not the
8320 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
8321 AOP_SIZE(result) > 1) {
8323 size = AOP_SIZE(result);
8326 l = aopGet(AOP(left),offset,FALSE,TRUE);
8327 if (*l == '@' && IS_AOP_PREG(result)) {
8329 pic14_emitcode("mov","a,%s",l);
8330 aopPut(AOP(result),"a",offset);
8332 aopPut(AOP(result),l,offset);
8337 tlbl = newiTempLabel(NULL);
8338 tlbl1= newiTempLabel(NULL);
8339 size = AOP_SIZE(result);
8342 /* if it is only one byte then */
8345 tlbl = newiTempLabel(NULL);
8346 if (!pic14_sameRegs(AOP(left),AOP(result))) {
8347 emitpcode(POC_MOVFW, popGet(AOP(left),0));
8348 emitpcode(POC_MOVWF, popGet(AOP(result),0));
8351 emitpcode(POC_COMFW, popGet(AOP(right),0));
8352 emitpcode(POC_RLF, popGet(AOP(result),0));
8353 emitpLabel(tlbl->key);
8354 emitpcode(POC_RRF, popGet(AOP(result),0));
8355 emitpcode(POC_ADDLW, popGetLit(1));
8357 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8362 reAdjustPreg(AOP(result));
8363 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8364 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8367 l = aopGet(AOP(result),offset,FALSE,FALSE);
8369 pic14_emitcode("rrc","a");
8370 aopPut(AOP(result),"a",offset--);
8372 reAdjustPreg(AOP(result));
8374 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8375 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8378 freeAsmop(left,NULL,ic,TRUE);
8379 freeAsmop (right,NULL,ic,TRUE);
8380 freeAsmop(result,NULL,ic,TRUE);
8383 /*-----------------------------------------------------------------*/
8384 /* genUnpackBits - generates code for unpacking bits */
8385 /*-----------------------------------------------------------------*/
8386 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype, iCode *ifx)
8389 int offset = 0; /* result byte offset */
8390 int rsize; /* result size */
8391 int rlen = 0; /* remaining bitfield length */
8392 sym_link *etype; /* bitfield type information */
8393 int blen; /* bitfield length */
8394 int bstr; /* bitfield starting bit within byte */
8397 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8398 etype = getSpec(operandType(result));
8399 rsize = getSize (operandType (result));
8400 blen = SPEC_BLEN (etype);
8401 bstr = SPEC_BSTR (etype);
8403 /* single bit field case */
8405 if (ifx) { /* that is for an if statement */
8408 resolveIfx(&rIfx,ifx);
8409 if (ptype == -1) /* direct */
8410 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8412 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8413 emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8414 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8419 if (ptype == -1) /* direct */
8420 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8422 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8423 emitpcode(POC_BTFSC,pcop);
8424 emitpcode(POC_BSF,newpCodeOpBit(aopGet(AOP(result), 0,FALSE,FALSE),bstr,0));
8425 if (ptype == -1) /* direct */
8426 pcop = newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),bstr,0);
8428 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8429 emitpcode(POC_BTFSS,pcop);
8430 emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0));
8436 static int has_warned=0;
8439 fprintf (stderr, "%s: bitfields with more than 1 bit are probably broken...", __FUNCTION__);
8444 /* read the first byte */
8449 // pic14_emitcode("mov","a,@%s",rname);
8450 emitpcode(POC_MOVFW, popCopyReg(&pc_indf));
8454 pic14_emitcode("movx","a,@%s",rname);
8458 pic14_emitcode("movx","a,@dptr");
8462 pic14_emitcode("clr","a");
8463 pic14_emitcode("movc","a","@a+dptr");
8467 pic14_emitcode("lcall","__gptrget");
8471 /* if we have bitdisplacement then it fits */
8472 /* into this byte completely or if length is */
8473 /* less than a byte */
8474 if ((shCnt = SPEC_BSTR(etype)) || blen <= 8) {
8476 /* shift right acc */
8477 AccRsh(left,0,shCnt);
8479 pic14_emitcode("anl","a,#0x%02x",
8480 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
8481 aopPut(AOP(result),"a",offset);
8485 /* bit field did not fit in a byte */
8486 rlen = SPEC_BLEN(etype) - 8;
8487 aopPut(AOP(result),"a",offset++);
8494 pic14_emitcode("inc","%s",rname);
8495 pic14_emitcode("mov","a,@%s",rname);
8499 pic14_emitcode("inc","%s",rname);
8500 pic14_emitcode("movx","a,@%s",rname);
8504 pic14_emitcode("inc","dptr");
8505 pic14_emitcode("movx","a,@dptr");
8509 pic14_emitcode("clr","a");
8510 pic14_emitcode("inc","dptr");
8511 pic14_emitcode("movc","a","@a+dptr");
8515 pic14_emitcode("inc","dptr");
8516 pic14_emitcode("lcall","__gptrget");
8521 /* if we are done */
8525 aopPut(AOP(result),"a",offset++);
8530 pic14_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
8531 aopPut(AOP(result),"a",offset);
8538 /*-----------------------------------------------------------------*/
8539 /* genDataPointerGet - generates code when ptr offset is known */
8540 /*-----------------------------------------------------------------*/
8541 static void genDataPointerGet (operand *left,
8545 int size , offset = 0;
8548 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8551 /* optimization - most of the time, left and result are the same
8552 * address, but different types. for the pic code, we could omit
8555 aopOp(result,ic,TRUE);
8557 if (pic14_sameRegs (AOP(left), AOP(result)))
8560 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8562 //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8564 size = AOP_SIZE(result);
8565 if (size > AOP_SIZE(left)) size = AOP_SIZE(left);
8568 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8569 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8573 freeAsmop(left,NULL,ic,TRUE);
8574 freeAsmop(result,NULL,ic,TRUE);
8577 /*-----------------------------------------------------------------*/
8578 /* genNearPointerGet - pic14_emitcode for near pointer fetch */
8579 /*-----------------------------------------------------------------*/
8580 static void genNearPointerGet (operand *left,
8585 sym_link *ltype = operandType(left);
8586 sym_link *rtype = operandType(result);
8587 sym_link *retype= getSpec(rtype); /* bitfield type information */
8591 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8594 aopOp(left,ic,FALSE);
8596 /* if left is rematerialisable and
8597 result is not bit variable type and
8598 the left is pointer to data space i.e
8599 lower 128 bytes of space */
8600 if (AOP_TYPE(left) == AOP_PCODE && //AOP_TYPE(left) == AOP_IMMD &&
8601 !IS_BITVAR(retype) &&
8602 DCL_TYPE(ltype) == POINTER) {
8603 genDataPointerGet (left,result,ic);
8607 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8608 aopOp (result,ic,FALSE);
8610 /* Check if can access directly instead of via a pointer */
8611 if (PCOP(AOP(left))->type == PO_LITERAL && AOP_SIZE(result) == 1) {
8615 /* If the pointer value is not in a the FSR then need to put it in */
8616 if (!AOP_INPREG(AOP(left)) && !direct) {
8617 /* otherwise get a free pointer register */
8618 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8619 if (PCOP(AOP(result))->type == PO_LITERAL) /* XXX: check me */
8620 emitpcode(POC_MOVLW, popGet(AOP(left),0));
8622 emitpcode(POC_MOVFW, popGet(AOP(left),0));
8623 emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
8628 /* if bitfield then unpack the bits */
8629 if (IS_BITFIELD(retype))
8630 genUnpackBits (result,left,"indf",direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8632 /* we have can just get the values */
8633 int size = AOP_SIZE(result);
8636 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8640 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8642 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8643 if (AOP_TYPE(result) == AOP_LIT) {
8644 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8646 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8648 if (size && !direct)
8649 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8654 /* now some housekeeping stuff */
8656 /* we had to allocate for this iCode */
8657 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8658 freeAsmop(NULL,aop,ic,TRUE);
8660 /* we did not allocate which means left
8661 already in a pointer register, then
8662 if size > 0 && this could be used again
8663 we have to point it back to where it
8665 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8666 if (AOP_SIZE(result) > 1 &&
8667 !OP_SYMBOL(left)->remat &&
8668 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8670 int size = AOP_SIZE(result) - 1;
8672 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8677 freeAsmop(left,NULL,ic,TRUE);
8678 freeAsmop(result,NULL,ic,TRUE);
8682 /*-----------------------------------------------------------------*/
8683 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch */
8684 /*-----------------------------------------------------------------*/
8685 static void genPagedPointerGet (operand *left,
8692 sym_link *rtype, *retype;
8695 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8697 rtype = operandType(result);
8698 retype= getSpec(rtype);
8700 aopOp(left,ic,FALSE);
8702 /* if the value is already in a pointer register
8703 then don't need anything more */
8704 if (!AOP_INPREG(AOP(left))) {
8705 /* otherwise get a free pointer register */
8707 preg = getFreePtr(ic,&aop,FALSE);
8708 pic14_emitcode("mov","%s,%s",
8710 aopGet(AOP(left),0,FALSE,TRUE));
8711 rname = preg->name ;
8713 rname = aopGet(AOP(left),0,FALSE,FALSE);
8715 freeAsmop(left,NULL,ic,TRUE);
8716 aopOp (result,ic,FALSE);
8718 /* if bitfield then unpack the bits */
8719 if (IS_BITFIELD(retype))
8720 genUnpackBits (result,left,rname,PPOINTER,0);
8722 /* we have can just get the values */
8723 int size = AOP_SIZE(result);
8728 pic14_emitcode("movx","a,@%s",rname);
8729 aopPut(AOP(result),"a",offset);
8734 pic14_emitcode("inc","%s",rname);
8738 /* now some housekeeping stuff */
8740 /* we had to allocate for this iCode */
8741 freeAsmop(NULL,aop,ic,TRUE);
8743 /* we did not allocate which means left
8744 already in a pointer register, then
8745 if size > 0 && this could be used again
8746 we have to point it back to where it
8748 if (AOP_SIZE(result) > 1 &&
8749 !OP_SYMBOL(left)->remat &&
8750 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8752 int size = AOP_SIZE(result) - 1;
8754 pic14_emitcode("dec","%s",rname);
8759 freeAsmop(result,NULL,ic,TRUE);
8764 /*-----------------------------------------------------------------*/
8765 /* genFarPointerGet - gget value from far space */
8766 /*-----------------------------------------------------------------*/
8767 static void genFarPointerGet (operand *left,
8768 operand *result, iCode *ic)
8771 sym_link *retype = getSpec(operandType(result));
8774 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8776 aopOp(left,ic,FALSE);
8778 /* if the operand is already in dptr
8779 then we do nothing else we move the value to dptr */
8780 if (AOP_TYPE(left) != AOP_STR) {
8781 /* if this is remateriazable */
8782 if (AOP_TYPE(left) == AOP_IMMD)
8783 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8784 else { /* we need to get it byte by byte */
8785 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8786 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8787 if (options.model == MODEL_FLAT24)
8789 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8793 /* so dptr know contains the address */
8794 freeAsmop(left,NULL,ic,TRUE);
8795 aopOp(result,ic,FALSE);
8797 /* if bit then unpack */
8798 if (IS_BITFIELD(retype))
8799 genUnpackBits(result,left,"dptr",FPOINTER,0);
8801 size = AOP_SIZE(result);
8805 pic14_emitcode("movx","a,@dptr");
8806 aopPut(AOP(result),"a",offset++);
8808 pic14_emitcode("inc","dptr");
8812 freeAsmop(result,NULL,ic,TRUE);
8815 /*-----------------------------------------------------------------*/
8816 /* genCodePointerGet - get value from code space */
8817 /*-----------------------------------------------------------------*/
8818 static void genCodePointerGet (operand *left,
8819 operand *result, iCode *ic)
8822 sym_link *retype = getSpec(operandType(result));
8824 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8826 aopOp(left,ic,FALSE);
8828 /* if the operand is already in dptr
8829 then we do nothing else we move the value to dptr */
8830 if (AOP_TYPE(left) != AOP_STR) {
8831 /* if this is remateriazable */
8832 if (AOP_TYPE(left) == AOP_IMMD)
8833 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8834 else { /* we need to get it byte by byte */
8835 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8836 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8837 if (options.model == MODEL_FLAT24)
8839 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8843 /* so dptr know contains the address */
8844 freeAsmop(left,NULL,ic,TRUE);
8845 aopOp(result,ic,FALSE);
8847 /* if bit then unpack */
8848 if (IS_BITFIELD(retype))
8849 genUnpackBits(result,left,"dptr",CPOINTER,0);
8851 size = AOP_SIZE(result);
8855 pic14_emitcode("clr","a");
8856 pic14_emitcode("movc","a,@a+dptr");
8857 aopPut(AOP(result),"a",offset++);
8859 pic14_emitcode("inc","dptr");
8863 freeAsmop(result,NULL,ic,TRUE);
8866 /*-----------------------------------------------------------------*/
8867 /* genGenPointerGet - gget value from generic pointer space */
8868 /*-----------------------------------------------------------------*/
8869 static void genGenPointerGet (operand *left,
8870 operand *result, iCode *ic)
8873 sym_link *retype = getSpec(operandType(result));
8876 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8877 aopOp(left,ic,FALSE);
8878 aopOp(result,ic,FALSE);
8881 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8883 /* if the operand is already in dptr
8884 then we do nothing else we move the value to dptr */
8885 // if (AOP_TYPE(left) != AOP_STR) {
8886 /* if this is remateriazable */
8887 if (AOP_TYPE(left) == AOP_IMMD) {
8888 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8889 pic14_emitcode("mov","b,#%d",pointerCode(retype));
8891 else { /* we need to get it byte by byte */
8893 emitpcode(POC_MOVFW,popGet(AOP(left),0));
8894 emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8896 size = AOP_SIZE(result);
8900 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8901 emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
8903 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8908 /* so dptr know contains the address */
8910 /* if bit then unpack */
8911 //if (IS_BITFIELD(retype))
8912 // genUnpackBits(result,"dptr",GPOINTER);
8915 freeAsmop(left,NULL,ic,TRUE);
8916 freeAsmop(result,NULL,ic,TRUE);
8920 /*-----------------------------------------------------------------*/
8921 /* genConstPointerGet - get value from const generic pointer space */
8922 /*-----------------------------------------------------------------*/
8923 static void genConstPointerGet (operand *left,
8924 operand *result, iCode *ic)
8926 //sym_link *retype = getSpec(operandType(result));
8927 symbol *albl, *blbl;//, *clbl;
8933 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8934 aopOp(left,ic,FALSE);
8935 aopOp(result,ic,FALSE);
8937 size = AOP_SIZE(result);
8939 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8941 DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
8943 lit = aop_isLitLike (AOP(left));
8944 poc = lit ? POC_MOVLW : POC_MOVFW;
8948 for (i = 0; i < size; i++)
8950 albl = newiTempLabel(NULL);
8951 blbl = newiTempLabel(NULL);
8953 emitpcode(POC_CALL,popGetLabel(albl->key));
8954 pcop = popGetLabel(blbl->key);
8955 emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
8956 emitpcode(POC_GOTO,pcop);
8958 emitpLabel(albl->key);
8959 emitpcode(poc,popGetAddr(AOP(left),1,i));
8960 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
8961 emitpcode(poc,popGetAddr(AOP(left),0,i));
8962 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
8964 emitpLabel(blbl->key);
8965 emitpcode(POC_MOVWF,popGet(AOP(result),i));
8968 albl = newiTempLabel(NULL);
8969 blbl = newiTempLabel(NULL);
8970 //clbl = newiTempLabel(NULL);
8972 emitpcode (POC_GOTO, popGetLabel (blbl->key));
8974 emitpLabel(albl->key);
8975 emitpcode(poc,popGet(AOP(left),1));
8976 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
8977 emitpcode(poc,popGet(AOP(left),0));
8978 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
8980 emitpLabel(blbl->key);
8982 for (i = 0; i < size; i++)
8984 emitpcode(POC_CALL,popGetLabel(albl->key));
8985 /* the next two instructions (plus clbl) might be useless... */
8986 //pcop = popGetLabel(clbl->key);
8987 //emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
8988 //emitpcode(POC_GOTO,pcop);
8989 //emitpLabel(clbl->key);
8992 emitpcode (POC_INCF, popGet (AOP(left), 0));
8994 emitpcode (POC_INCF, popGet (AOP(left), 1));
8996 emitpcode(POC_MOVWF,popGet(AOP(result),i));
8999 /* restore left's value */
9000 emitpcode (POC_MOVLW, popGetLit (size-1));
9001 emitpcode (POC_SUBWF, popGet (AOP(left), 0));
9003 emitpcode (POC_DECF, popGet (AOP(left), 1));
9007 freeAsmop(left,NULL,ic,TRUE);
9008 freeAsmop(result,NULL,ic,TRUE);
9011 /*-----------------------------------------------------------------*/
9012 /* genPointerGet - generate code for pointer get */
9013 /*-----------------------------------------------------------------*/
9014 static void genPointerGet (iCode *ic)
9016 operand *left, *result ;
9017 sym_link *type, *etype;
9021 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9024 result = IC_RESULT(ic) ;
9026 /* depending on the type of pointer we need to
9027 move it to the correct pointer register */
9028 type = operandType(left);
9029 etype = getSpec(type);
9031 if (IS_PTR_CONST(type))
9032 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9034 /* if left is of type of pointer then it is simple */
9035 if (IS_PTR(type) && !IS_FUNC(type->next))
9036 p_type = DCL_TYPE(type);
9038 /* we have to go by the storage class */
9039 p_type = PTR_TYPE(SPEC_OCLS(etype));
9041 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9043 if (SPEC_OCLS(etype)->codesp ) {
9044 DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9045 //p_type = CPOINTER ;
9048 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9049 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9050 /*p_type = FPOINTER ;*/
9052 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9053 DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9054 /* p_type = PPOINTER; */
9056 if (SPEC_OCLS(etype) == idata )
9057 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9058 /* p_type = IPOINTER; */
9060 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9061 /* p_type = POINTER ; */
9064 /* now that we have the pointer type we assign
9065 the pointer values */
9070 genNearPointerGet (left,result,ic);
9074 genPagedPointerGet(left,result,ic);
9078 genFarPointerGet (left,result,ic);
9082 genConstPointerGet (left,result,ic);
9083 //pic14_emitcodePointerGet (left,result,ic);
9087 if (IS_CODEPTR(type) || IS_PTR_CONST(type) || SPEC_CONST(etype))
9088 genConstPointerGet (left,result,ic);
9090 genGenPointerGet (left,result,ic);
9093 assert ( !"unhandled pointer type" );
9099 /*-----------------------------------------------------------------*/
9100 /* emitPtrByteGet - for legacy 8051 emits code to get a byte into */
9101 /* A through a pointer register (R0, R1, or DPTR). The original */
9102 /* value of A can be preserved in B. */
9103 /* PIC has to use INDF register. */
9104 /*-----------------------------------------------------------------*/
9106 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9114 pic14_emitcode ("mov", "b,a");
9115 // pic14_emitcode ("mov", "a,@%s", rname);
9116 emitpcode(POC_MOVFW, popCopyReg(&pc_indf));
9121 pic14_emitcode ("mov", "b,a");
9122 pic14_emitcode ("movx", "a,@%s", rname);
9127 pic14_emitcode ("mov", "b,a");
9128 pic14_emitcode ("movx", "a,@dptr");
9133 pic14_emitcode ("mov", "b,a");
9134 pic14_emitcode ("clr", "a");
9135 pic14_emitcode ("movc", "a,@a+dptr");
9141 pic14_emitcode ("push", "b");
9142 pic14_emitcode ("push", "acc");
9144 pic14_emitcode ("lcall", "__gptrget");
9146 pic14_emitcode ("pop", "b");
9151 /*-----------------------------------------------------------------*/
9152 /* emitPtrByteSet - emits code to set a byte from src through a */
9153 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR). */
9154 /*-----------------------------------------------------------------*/
9156 emitPtrByteSet (char *rname, int p_type, char *src)
9166 pic14_emitcode ("mov", "@%s,a", rname);
9169 // pic14_emitcode ("mov", "@%s,%s", rname, src);
9170 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9175 pic14_emitcode ("movx", "@%s,a", rname);
9180 pic14_emitcode ("movx", "@dptr,a");
9185 pic14_emitcode ("lcall", "__gptrput");
9190 /*-----------------------------------------------------------------*/
9191 /* genPackBits - generates code for packed bit storage */
9192 /*-----------------------------------------------------------------*/
9193 static void genPackBits(sym_link *etype,operand *result,operand *right,char *rname,int p_type)
9195 int offset = 0; /* source byte offset */
9196 int rlen = 0; /* remaining bitfield length */
9197 int blen; /* bitfield length */
9198 int bstr; /* bitfield starting bit within byte */
9199 int litval; /* source literal value (if AOP_LIT) */
9200 unsigned char mask; /* bitmask within current byte */
9203 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9205 blen = SPEC_BLEN (etype);
9206 bstr = SPEC_BSTR (etype);
9208 /* If the bitfield length is less than a byte */
9211 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9212 (unsigned char) (0xFF >> (8 - bstr)));
9214 if (AOP_TYPE (right) == AOP_LIT)
9216 /* Case with a bitfield length <8 and literal source
9218 int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9222 if (AOP(result)->type == AOP_PCODE)
9223 pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9225 pcop = popGet(AOP(result),0);
9226 emitpcode(lit?POC_BSF:POC_BCF,pcop);
9228 emitpcode(lit?POC_BSF:POC_BCF,popCopyReg(&pc_indf));
9232 litval = lit << bstr;
9233 litval &= (~mask) & 0xff;
9235 emitpcode(POC_MOVFW,popGet(AOP(result),0));
9237 emitPtrByteGet (rname, p_type, FALSE);
9238 if ((mask|litval)!=0xff)
9239 emitpcode(POC_ANDLW,popGetLit(mask));
9241 emitpcode(POC_IORLW,popGetLit(litval));
9248 /* 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 */
9249 emitpcode(POC_RLF,popGet(AOP(right),0));
9251 emitpcode(POC_BCF,popGet(AOP(result),0));
9253 emitpcode(POC_BSF,popGet(AOP(result),0));
9254 } else if (p_type!=GPOINTER) {
9255 /* Case with a bitfield length == 1 and no generic pointer
9257 if (AOP_TYPE (right) == AOP_CRY)
9258 pic14_emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9261 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
9262 pic14_emitcode ("rrc","a");
9264 emitPtrByteGet (rname, p_type, FALSE);
9265 pic14_emitcode ("mov","acc.%d,c",bstr);
9271 /* Case with a bitfield length < 8 and arbitrary source
9273 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
9274 /* shift and mask source value */
9275 AccLsh (right,0,bstr);
9276 pic14_emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9277 emitpcode(POC_ANDLW, popGetLit((~mask) & 0xff));
9279 //pushedB = pushB ();
9281 emitpcode(POC_MOVFW,popGet(AOP(result),0));
9283 emitPtrByteGet (rname, p_type, TRUE);
9285 pic14_emitcode ("anl", "a,#0x%02x", mask);
9286 pic14_emitcode ("orl", "a,b");
9287 emitpcode(POC_ANDLW,popGetLit(mask));
9288 emitpcode(POC_IORFW,popGet(AOP(right),0));
9289 if (p_type == GPOINTER)
9290 pic14_emitcode ("pop", "b");
9297 emitpcode(POC_MOVWF,popGet(AOP(result),0));
9299 emitPtrByteSet (rname, p_type, "a");
9303 /* Bit length is greater than 7 bits. In this case, copy */
9304 /* all except the partial byte at the end */
9305 for (rlen=blen;rlen>=8;rlen-=8)
9307 emitPtrByteSet (rname, p_type,
9308 aopGet (AOP (right), offset++, FALSE, TRUE) );
9310 pic14_emitcode ("inc", "%s", rname);
9313 /* If there was a partial byte at the end */
9316 mask = (((unsigned char) -1 << rlen) & 0xff);
9318 if (AOP_TYPE (right) == AOP_LIT)
9320 /* Case with partial byte and literal source
9322 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9323 litval >>= (blen-rlen);
9324 litval &= (~mask) & 0xff;
9325 emitPtrByteGet (rname, p_type, FALSE);
9326 if ((mask|litval)!=0xff)
9327 pic14_emitcode ("anl","a,#0x%02x", mask);
9329 pic14_emitcode ("orl","a,#0x%02x", litval);
9334 /* Case with partial byte and arbitrary source
9336 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
9337 pic14_emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9339 //pushedB = pushB ();
9340 /* transfer A to B and get next byte */
9341 emitPtrByteGet (rname, p_type, TRUE);
9343 pic14_emitcode ("anl", "a,#0x%02x", mask);
9344 pic14_emitcode ("orl", "a,b");
9345 if (p_type == GPOINTER)
9346 pic14_emitcode ("pop", "b");
9350 emitPtrByteSet (rname, p_type, "a");
9355 /*-----------------------------------------------------------------*/
9356 /* SetIrp - Set IRP bit */
9357 /*-----------------------------------------------------------------*/
9358 void SetIrp(operand *result) {
9360 if (AOP_TYPE(result) == AOP_LIT) {
9361 unsigned lit = (unsigned)operandLitValue(result);
9362 emitpcode((lit&0x100)?POC_BSF:POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
9364 if (PCOP(AOP(result))->type == PO_LITERAL) {
9365 int addrs = PCOL(AOP(result))->lit;
9366 emitpcode((addrs&0x100)?POC_BSF:POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
9368 emitpcode(POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT)); /* always ensure this is clear as it may have previouly been set */
9369 if(AOP_SIZE(result) > 1) {
9370 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
9371 emitpcode(POC_BSF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
9377 /*-----------------------------------------------------------------*/
9378 /* genDataPointerSet - remat pointer to data space */
9379 /*-----------------------------------------------------------------*/
9380 static void genDataPointerSet(operand *right,
9384 int size, offset = 0 ;
9387 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9388 aopOp(right,ic,FALSE);
9389 aopOp(result,ic,FALSE);
9391 size = AOP_SIZE(right);
9393 if ( AOP_TYPE(result) == AOP_PCODE) {
9394 fprintf(stderr,"genDataPointerSet %s, %d\n",
9395 AOP(result)->aopu.pcop->name,
9396 PCOI(AOP(result)->aopu.pcop)->offset);
9400 // tsd, was l+1 - the underline `_' prefix was being stripped
9402 emitpComment ("%s:%u: size=%i, offset=%i", __FILE__,__LINE__, size, offset);
9404 if (AOP_TYPE(right) == AOP_LIT) {
9405 unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9406 lit = lit >> (8*offset);
9408 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9409 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9411 emitpcode(POC_CLRF, popGet(AOP(result),offset));
9414 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9415 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9421 freeAsmop(right,NULL,ic,TRUE);
9422 freeAsmop(result,NULL,ic,TRUE);
9425 /*-----------------------------------------------------------------*/
9426 /* genNearPointerSet - pic14_emitcode for near pointer put */
9427 /*-----------------------------------------------------------------*/
9428 static void genNearPointerSet (operand *right,
9433 sym_link *ptype = operandType(result);
9434 sym_link *retype = getSpec(operandType(right));
9435 sym_link *letype = getSpec(ptype);
9440 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9441 aopOp(result,ic,FALSE);
9444 /* if the result is rematerializable &
9445 in data space & not a bit variable */
9446 //if (AOP_TYPE(result) == AOP_IMMD &&
9447 if (AOP_TYPE(result) == AOP_PCODE &&
9448 DCL_TYPE(ptype) == POINTER &&
9449 !IS_BITVAR (retype) &&
9450 !IS_BITVAR (letype)) {
9451 genDataPointerSet (right,result,ic);
9452 freeAsmop(result,NULL,ic,TRUE);
9456 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9457 aopOp(right,ic,FALSE);
9458 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9460 /* Check if can access directly instead of via a pointer */
9461 if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9465 /* If the pointer value is not in a the FSR then need to put it in */
9466 if (!AOP_INPREG(AOP(result)) && !direct) {
9467 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9468 if (PCOP(AOP(result))->type == PO_LITERAL)
9469 emitpcode(POC_MOVLW, popGet(AOP(result),0));
9471 emitpcode(POC_MOVFW, popGet(AOP(result),0));
9472 emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
9475 /* Must set/reset IRP bit for use with FSR. */
9476 /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9480 /* if bitfield then unpack the bits */
9481 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9482 genPackBits ((IS_BITFIELD (retype) ? retype : letype), result, right, "indf", direct?-1:POINTER);
9484 /* we have can just get the values */
9485 int size = AOP_SIZE(right);
9488 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9490 char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9492 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9494 if (AOP_TYPE(right) == AOP_LIT) {
9495 emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9497 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9500 emitpcode(POC_MOVWF,popGet(AOP(result),0));
9502 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9504 if (size && !direct)
9505 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9510 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9511 /* now some housekeeping stuff */
9513 /* we had to allocate for this iCode */
9514 freeAsmop(NULL,aop,ic,TRUE);
9516 /* we did not allocate which means left
9517 already in a pointer register, then
9518 if size > 0 && this could be used again
9519 we have to point it back to where it
9521 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9522 if (AOP_SIZE(right) > 1 &&
9523 !OP_SYMBOL(result)->remat &&
9524 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9526 int size = AOP_SIZE(right) - 1;
9528 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9532 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9535 freeAsmop(right,NULL,ic,TRUE);
9536 freeAsmop(result,NULL,ic,TRUE);
9539 /*-----------------------------------------------------------------*/
9540 /* genPagedPointerSet - pic14_emitcode for Paged pointer put */
9541 /*-----------------------------------------------------------------*/
9542 static void genPagedPointerSet (operand *right,
9552 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9554 retype= getSpec(operandType(right));
9556 aopOp(result,ic,FALSE);
9558 /* if the value is already in a pointer register
9559 then don't need anything more */
9560 if (!AOP_INPREG(AOP(result))) {
9561 /* otherwise get a free pointer register */
9563 preg = getFreePtr(ic,&aop,FALSE);
9564 pic14_emitcode("mov","%s,%s",
9566 aopGet(AOP(result),0,FALSE,TRUE));
9567 rname = preg->name ;
9569 rname = aopGet(AOP(result),0,FALSE,FALSE);
9571 freeAsmop(result,NULL,ic,TRUE);
9572 aopOp (right,ic,FALSE);
9574 /* if bitfield then unpack the bits */
9575 if (IS_BITFIELD(retype))
9576 genPackBits (retype,result,right,rname,PPOINTER);
9578 /* we have can just get the values */
9579 int size = AOP_SIZE(right);
9583 l = aopGet(AOP(right),offset,FALSE,TRUE);
9586 pic14_emitcode("movx","@%s,a",rname);
9589 pic14_emitcode("inc","%s",rname);
9595 /* now some housekeeping stuff */
9597 /* we had to allocate for this iCode */
9598 freeAsmop(NULL,aop,ic,TRUE);
9600 /* we did not allocate which means left
9601 already in a pointer register, then
9602 if size > 0 && this could be used again
9603 we have to point it back to where it
9605 if (AOP_SIZE(right) > 1 &&
9606 !OP_SYMBOL(result)->remat &&
9607 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9609 int size = AOP_SIZE(right) - 1;
9611 pic14_emitcode("dec","%s",rname);
9616 freeAsmop(right,NULL,ic,TRUE);
9621 /*-----------------------------------------------------------------*/
9622 /* genFarPointerSet - set value from far space */
9623 /*-----------------------------------------------------------------*/
9624 static void genFarPointerSet (operand *right,
9625 operand *result, iCode *ic)
9628 sym_link *retype = getSpec(operandType(right));
9631 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9632 aopOp(result,ic,FALSE);
9634 /* if the operand is already in dptr
9635 then we do nothing else we move the value to dptr */
9636 if (AOP_TYPE(result) != AOP_STR) {
9637 /* if this is remateriazable */
9638 if (AOP_TYPE(result) == AOP_IMMD)
9639 pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9640 else { /* we need to get it byte by byte */
9641 pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9642 pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9643 if (options.model == MODEL_FLAT24)
9645 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9649 /* so dptr know contains the address */
9650 freeAsmop(result,NULL,ic,TRUE);
9651 aopOp(right,ic,FALSE);
9653 /* if bit then unpack */
9654 if (IS_BITFIELD(retype))
9655 genPackBits(retype,result,right,"dptr",FPOINTER);
9657 size = AOP_SIZE(right);
9661 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9663 pic14_emitcode("movx","@dptr,a");
9665 pic14_emitcode("inc","dptr");
9669 freeAsmop(right,NULL,ic,TRUE);
9672 /*-----------------------------------------------------------------*/
9673 /* genGenPointerSet - set value from generic pointer space */
9674 /*-----------------------------------------------------------------*/
9675 static void genGenPointerSet (operand *right,
9676 operand *result, iCode *ic)
9678 sym_link *ptype = operandType(result);
9679 sym_link *retype = getSpec(operandType(right));
9680 sym_link *letype = getSpec (ptype);
9683 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9685 aopOp(result,ic,FALSE);
9686 aopOp(right,ic,FALSE);
9688 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9690 /* if the operand is already in dptr
9691 then we do nothing else we move the value to dptr */
9692 if (AOP_TYPE(result) != AOP_STR) {
9693 /* if this is remateriazable */
9694 if (AOP_TYPE(result) == AOP_IMMD) {
9695 pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9696 pic14_emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
9699 emitpcode(POC_MOVFW,popGet(AOP(result),0));
9700 emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
9702 /* Must set/reset IRP bit for use with FSR. */
9703 /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9708 /* if bitfield then unpack the bits */
9709 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9710 genPackBits ((IS_BITFIELD (retype) ? retype : letype),result, right, "indf", POINTER);
9712 /* we have can just get the values */
9713 int size = AOP_SIZE(right);
9716 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9718 char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9720 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9722 if (AOP_TYPE(right) == AOP_LIT) {
9723 emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9725 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9727 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9730 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9735 freeAsmop(right,NULL,ic,TRUE);
9736 freeAsmop(result,NULL,ic,TRUE);
9739 /*-----------------------------------------------------------------*/
9740 /* genPointerSet - stores the value into a pointer location */
9741 /*-----------------------------------------------------------------*/
9742 static void genPointerSet (iCode *ic)
9744 operand *right, *result ;
9745 sym_link *type, *etype;
9749 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9751 right = IC_RIGHT(ic);
9752 result = IC_RESULT(ic) ;
9754 /* depending on the type of pointer we need to
9755 move it to the correct pointer register */
9756 type = operandType(result);
9757 etype = getSpec(type);
9758 /* if left is of type of pointer then it is simple */
9759 if (IS_PTR(type) && !IS_FUNC(type->next)) {
9760 p_type = DCL_TYPE(type);
9763 /* we have to go by the storage class */
9764 p_type = PTR_TYPE(SPEC_OCLS(etype));
9766 /* if (SPEC_OCLS(etype)->codesp ) { */
9767 /* p_type = CPOINTER ; */
9770 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9771 /* p_type = FPOINTER ; */
9773 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9774 /* p_type = PPOINTER ; */
9776 /* if (SPEC_OCLS(etype) == idata ) */
9777 /* p_type = IPOINTER ; */
9779 /* p_type = POINTER ; */
9782 /* now that we have the pointer type we assign
9783 the pointer values */
9788 genNearPointerSet (right,result,ic);
9792 genPagedPointerSet (right,result,ic);
9796 genFarPointerSet (right,result,ic);
9800 genGenPointerSet (right,result,ic);
9804 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9805 "genPointerSet: illegal pointer type");
9809 /*-----------------------------------------------------------------*/
9810 /* genIfx - generate code for Ifx statement */
9811 /*-----------------------------------------------------------------*/
9812 static void genIfx (iCode *ic, iCode *popIc)
9814 operand *cond = IC_COND(ic);
9818 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9820 aopOp(cond,ic,FALSE);
9822 /* get the value into acc */
9823 if (AOP_TYPE(cond) != AOP_CRY)
9824 pic14_toBoolean(cond);
9827 /* the result is now in the accumulator */
9828 freeAsmop(cond,NULL,ic,TRUE);
9830 /* if there was something to be popped then do it */
9834 /* if the condition is a bit variable */
9835 if (isbit && IS_ITEMP(cond) &&
9837 genIfxJump(ic,SPIL_LOC(cond)->rname);
9838 DEBUGpic14_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9841 if (isbit && !IS_ITEMP(cond))
9842 genIfxJump(ic,OP_SYMBOL(cond)->rname);
9850 /*-----------------------------------------------------------------*/
9851 /* genAddrOf - generates code for address of */
9852 /*-----------------------------------------------------------------*/
9853 static void genAddrOf (iCode *ic)
9855 operand *right, *result, *left;
9859 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9862 //aopOp(IC_RESULT(ic),ic,FALSE);
9864 aopOp((left=IC_LEFT(ic)),ic,FALSE);
9865 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9866 aopOp((result=IC_RESULT(ic)),ic,TRUE);
9868 DEBUGpic14_AopType(__LINE__,left,right,result);
9869 assert (IS_SYMOP (left));
9871 /* sanity check: generic pointers to code space are not yet supported,
9872 * pionters to codespace must not be assigned addresses of __data values. */
9874 fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9875 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)));
9876 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)));
9877 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)));
9878 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)));
9881 if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9882 fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9883 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9884 OP_SYMBOL(left)->name);
9885 } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9886 fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9887 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9888 OP_SYMBOL(left)->name);
9891 size = AOP_SIZE(IC_RESULT(ic));
9895 /* fixing bug #863624, reported from (errolv) */
9896 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9897 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9900 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9901 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9906 freeAsmop(left,NULL,ic,FALSE);
9907 freeAsmop(result,NULL,ic,TRUE);
9912 /*-----------------------------------------------------------------*/
9913 /* genFarFarAssign - assignment when both are in far space */
9914 /*-----------------------------------------------------------------*/
9915 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9917 int size = AOP_SIZE(right);
9920 /* first push the right side on to the stack */
9922 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9924 pic14_emitcode ("push","acc");
9927 freeAsmop(right,NULL,ic,FALSE);
9928 /* now assign DPTR to result */
9929 aopOp(result,ic,FALSE);
9930 size = AOP_SIZE(result);
9932 pic14_emitcode ("pop","acc");
9933 aopPut(AOP(result),"a",--offset);
9935 freeAsmop(result,NULL,ic,FALSE);
9940 /*-----------------------------------------------------------------*/
9941 /* genAssign - generate code for assignment */
9942 /*-----------------------------------------------------------------*/
9943 static void genAssign (iCode *ic)
9945 operand *result, *right;
9946 int size, offset,know_W;
9947 unsigned long lit = 0L;
9949 result = IC_RESULT(ic);
9950 right = IC_RIGHT(ic) ;
9953 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9955 /* if they are the same */
9956 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9959 aopOp(right,ic,FALSE);
9960 aopOp(result,ic,TRUE);
9962 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9964 /* if they are the same registers */
9965 if (pic14_sameRegs(AOP(right),AOP(result)))
9968 /* special case: assign from __code */
9969 if (!IS_ITEMP(right) /* --> iTemps never reside in __code */
9970 && IS_SYMOP (right) /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
9971 && !IS_FUNC(OP_SYM_TYPE(right)) /* --> we would want its address instead of the first instruction */
9972 && !IS_CODEPTR(OP_SYM_TYPE(right)) /* --> get symbols address instread */
9973 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
9975 emitpComment ("genAssign from CODESPACE");
9976 genConstPointerGet (right, result, ic);
9980 /* just for symmetry reasons... */
9981 if (!IS_ITEMP(result)
9982 && IS_SYMOP (result)
9983 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
9985 assert ( !"cannot write to CODESPACE" );
9988 /* if the result is a bit */
9989 if (AOP_TYPE(result) == AOP_CRY) {
9991 /* if the right size is a literal then
9992 we know what the value is */
9993 if (AOP_TYPE(right) == AOP_LIT) {
9995 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9996 popGet(AOP(result),0));
9998 if (((int) operandLitValue(right)))
9999 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10000 AOP(result)->aopu.aop_dir,
10001 AOP(result)->aopu.aop_dir);
10003 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10004 AOP(result)->aopu.aop_dir,
10005 AOP(result)->aopu.aop_dir);
10009 /* the right is also a bit variable */
10010 if (AOP_TYPE(right) == AOP_CRY) {
10011 emitpcode(POC_BCF, popGet(AOP(result),0));
10012 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10013 emitpcode(POC_BSF, popGet(AOP(result),0));
10015 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10016 AOP(result)->aopu.aop_dir,
10017 AOP(result)->aopu.aop_dir);
10018 pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
10019 AOP(right)->aopu.aop_dir,
10020 AOP(right)->aopu.aop_dir);
10021 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10022 AOP(result)->aopu.aop_dir,
10023 AOP(result)->aopu.aop_dir);
10027 /* we need to or */
10028 emitpcode(POC_BCF, popGet(AOP(result),0));
10029 pic14_toBoolean(right);
10031 emitpcode(POC_BSF, popGet(AOP(result),0));
10032 //aopPut(AOP(result),"a",0);
10036 /* bit variables done */
10038 size = AOP_SIZE(result);
10040 if(AOP_TYPE(right) == AOP_LIT)
10041 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10043 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
10044 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10045 if(aopIdx(AOP(result),0) == 4) {
10046 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10047 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10048 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10051 DEBUGpic14_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
10056 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10057 if(AOP_TYPE(right) == AOP_LIT) {
10059 if(know_W != (int)(lit&0xff))
10060 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10062 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10064 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10068 } else if (AOP_TYPE(right) == AOP_CRY) {
10069 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10071 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10072 emitpcode(POC_INCF, popGet(AOP(result),0));
10075 mov2w (AOP(right), offset);
10076 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10084 freeAsmop (right,NULL,ic,FALSE);
10085 freeAsmop (result,NULL,ic,TRUE);
10088 /*-----------------------------------------------------------------*/
10089 /* genJumpTab - genrates code for jump table */
10090 /*-----------------------------------------------------------------*/
10091 static void genJumpTab (iCode *ic)
10097 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10099 aopOp(IC_JTCOND(ic),ic,FALSE);
10100 /* get the condition into accumulator */
10101 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10103 /* multiply by three */
10104 pic14_emitcode("add","a,acc");
10105 pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10107 jtab = newiTempLabel(NULL);
10108 pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10109 pic14_emitcode("jmp","@a+dptr");
10110 pic14_emitcode("","%05d_DS_:",jtab->key+100);
10112 emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10113 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10114 emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10115 emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10117 emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10118 emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10119 emitpLabel(jtab->key);
10121 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10123 /* now generate the jump labels */
10124 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10125 jtab = setNextItem(IC_JTLABELS(ic))) {
10126 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10127 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10133 /*-----------------------------------------------------------------*/
10134 /* genMixedOperation - gen code for operators between mixed types */
10135 /*-----------------------------------------------------------------*/
10137 TSD - Written for the PIC port - but this unfortunately is buggy.
10138 This routine is good in that it is able to efficiently promote
10139 types to different (larger) sizes. Unfortunately, the temporary
10140 variables that are optimized out by this routine are sometimes
10141 used in other places. So until I know how to really parse the
10142 iCode tree, I'm going to not be using this routine :(.
10144 static int genMixedOperation (iCode *ic)
10148 operand *result = IC_RESULT(ic);
10149 sym_link *ctype = operandType(IC_LEFT(ic));
10150 operand *right = IC_RIGHT(ic);
10156 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10158 pic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10164 nextright = IC_RIGHT(nextic);
10165 nextleft = IC_LEFT(nextic);
10166 nextresult = IC_RESULT(nextic);
10168 aopOp(right,ic,FALSE);
10169 aopOp(result,ic,FALSE);
10170 aopOp(nextright, nextic, FALSE);
10171 aopOp(nextleft, nextic, FALSE);
10172 aopOp(nextresult, nextic, FALSE);
10174 if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10176 operand *t = right;
10180 pic14_emitcode(";remove right +","");
10182 } else if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10184 operand *t = right;
10188 pic14_emitcode(";remove left +","");
10192 big = AOP_SIZE(nextleft);
10193 small = AOP_SIZE(nextright);
10195 switch(nextic->op) {
10198 pic14_emitcode(";optimize a +","");
10199 /* if unsigned or not an integral type */
10200 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10201 pic14_emitcode(";add a bit to something","");
10204 pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10206 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10207 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10208 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10210 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10218 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10219 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10220 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10223 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10225 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10226 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10227 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10228 pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10229 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10232 pic14_emitcode("rlf","known_zero,w");
10239 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10240 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10241 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10243 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10253 freeAsmop(right,NULL,ic,TRUE);
10254 freeAsmop(result,NULL,ic,TRUE);
10255 freeAsmop(nextright,NULL,ic,TRUE);
10256 freeAsmop(nextleft,NULL,ic,TRUE);
10258 nextic->generated = 1;
10265 /*-----------------------------------------------------------------*/
10266 /* genCast - gen code for casting */
10267 /*-----------------------------------------------------------------*/
10268 static void genCast (iCode *ic)
10270 operand *result = IC_RESULT(ic);
10271 sym_link *ctype = operandType(IC_LEFT(ic));
10272 sym_link *rtype = operandType(IC_RIGHT(ic));
10273 operand *right = IC_RIGHT(ic);
10277 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10278 /* if they are equivalent then do nothing */
10279 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10282 aopOp(right,ic,FALSE) ;
10283 aopOp(result,ic,FALSE);
10285 DEBUGpic14_AopType(__LINE__,NULL,right,result);
10287 /* if the result is a bit */
10288 if (AOP_TYPE(result) == AOP_CRY) {
10289 /* if the right size is a literal then
10290 we know what the value is */
10291 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10292 if (AOP_TYPE(right) == AOP_LIT) {
10294 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10295 popGet(AOP(result),0));
10297 if (((int) operandLitValue(right)))
10298 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
10299 AOP(result)->aopu.aop_dir,
10300 AOP(result)->aopu.aop_dir);
10302 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
10303 AOP(result)->aopu.aop_dir,
10304 AOP(result)->aopu.aop_dir);
10309 /* the right is also a bit variable */
10310 if (AOP_TYPE(right) == AOP_CRY) {
10313 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10315 pic14_emitcode("clrc","");
10316 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10317 AOP(right)->aopu.aop_dir,
10318 AOP(right)->aopu.aop_dir);
10319 aopPut(AOP(result),"c",0);
10323 /* we need to or */
10324 if (AOP_TYPE(right) == AOP_REG) {
10325 emitpcode(POC_BCF, popGet(AOP(result),0));
10326 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
10327 emitpcode(POC_BSF, popGet(AOP(result),0));
10329 pic14_toBoolean(right);
10330 aopPut(AOP(result),"a",0);
10334 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10336 size = AOP_SIZE(result);
10338 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10340 emitpcode(POC_CLRF, popGet(AOP(result),0));
10341 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10342 emitpcode(POC_INCF, popGet(AOP(result),0));
10345 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
10350 /* if they are the same size : or less */
10351 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10353 /* if they are in the same place */
10354 if (pic14_sameRegs(AOP(right),AOP(result)))
10357 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10358 if (IS_PTR_CONST(rtype))
10359 DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10360 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10361 DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10363 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10364 emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10365 emitpcode(POC_MOVWF, popGet(AOP(result),0));
10366 emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10367 emitpcode(POC_MOVWF, popGet(AOP(result),1));
10368 if(AOP_SIZE(result) <2)
10369 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10373 /* if they in different places then copy */
10374 size = AOP_SIZE(result);
10377 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10378 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10380 //aopPut(AOP(result),
10381 // aopGet(AOP(right),offset,FALSE,FALSE),
10391 /* if the result is of type pointer */
10392 if (IS_PTR(ctype)) {
10395 sym_link *type = operandType(right);
10396 sym_link *etype = getSpec(type);
10397 DEBUGpic14_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
10399 /* pointer to generic pointer */
10400 if (IS_GENPTR(ctype)) {
10404 p_type = DCL_TYPE(type);
10406 /* we have to go by the storage class */
10407 p_type = PTR_TYPE(SPEC_OCLS(etype));
10409 /* if (SPEC_OCLS(etype)->codesp ) */
10410 /* p_type = CPOINTER ; */
10412 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10413 /* p_type = FPOINTER ; */
10415 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10416 /* p_type = PPOINTER; */
10418 /* if (SPEC_OCLS(etype) == idata ) */
10419 /* p_type = IPOINTER ; */
10421 /* p_type = POINTER ; */
10424 /* the first two bytes are known */
10425 DEBUGpic14_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
10426 size = GPTRSIZE - 1;
10429 if(offset < AOP_SIZE(right)) {
10430 DEBUGpic14_emitcode("; ***","%s %d - pointer cast3",__FUNCTION__,__LINE__);
10431 if ((AOP_TYPE(right) == AOP_PCODE) &&
10432 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10433 emitpcode(POC_MOVLW, popGetAddr(AOP(right),offset,0));
10434 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10436 aopPut(AOP(result),
10437 aopGet(AOP(right),offset,FALSE,FALSE),
10441 emitpcode(POC_CLRF,popGet(AOP(result),offset));
10444 /* the last byte depending on type */
10448 emitpcode(POC_CLRF,popGet(AOP(result),GPTRSIZE - 1));
10451 pic14_emitcode(";BUG!? ","%d",__LINE__);
10455 pic14_emitcode(";BUG!? ","%d",__LINE__);
10459 pic14_emitcode(";BUG!? ","%d",__LINE__);
10464 /* this should never happen */
10465 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10466 "got unknown pointer type");
10469 //aopPut(AOP(result),l, GPTRSIZE - 1);
10473 /* just copy the pointers */
10474 size = AOP_SIZE(result);
10477 aopPut(AOP(result),
10478 aopGet(AOP(right),offset,FALSE,FALSE),
10487 /* so we now know that the size of destination is greater
10488 than the size of the source.
10489 Now, if the next iCode is an operator then we might be
10490 able to optimize the operation without performing a cast.
10492 if(genMixedOperation(ic))
10495 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10497 /* we move to result for the size of source */
10498 size = AOP_SIZE(right);
10501 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10502 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10506 /* now depending on the sign of the destination */
10507 size = AOP_SIZE(result) - AOP_SIZE(right);
10508 /* if unsigned or not an integral type */
10509 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
10511 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
10513 /* we need to extend the sign :{ */
10516 /* Save one instruction of casting char to int */
10517 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10518 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10519 emitpcode(POC_DECF, popGet(AOP(result),offset));
10521 emitpcodeNULLop(POC_CLRW);
10524 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10526 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),offset,FALSE,FALSE),7,0));
10528 emitpcode(POC_MOVLW, popGetLit(0xff));
10531 emitpcode(POC_MOVWF, popGet(AOP(result),offset++));
10536 freeAsmop(right,NULL,ic,TRUE);
10537 freeAsmop(result,NULL,ic,TRUE);
10541 /*-----------------------------------------------------------------*/
10542 /* genDjnz - generate decrement & jump if not zero instrucion */
10543 /*-----------------------------------------------------------------*/
10544 static int genDjnz (iCode *ic, iCode *ifx)
10546 symbol *lbl, *lbl1;
10548 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10553 /* if the if condition has a false label
10554 then we cannot save */
10558 /* if the minus is not of the form
10560 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10561 !IS_OP_LITERAL(IC_RIGHT(ic)))
10564 if (operandLitValue(IC_RIGHT(ic)) != 1)
10567 /* if the size of this greater than one then no
10569 if (getSize(operandType(IC_RESULT(ic))) > 1)
10572 /* otherwise we can save BIG */
10573 lbl = newiTempLabel(NULL);
10574 lbl1= newiTempLabel(NULL);
10576 aopOp(IC_RESULT(ic),ic,FALSE);
10578 if (IS_AOP_PREG(IC_RESULT(ic))) {
10579 pic14_emitcode("dec","%s",
10580 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10581 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10582 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10586 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10587 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10589 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10590 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10593 /* pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10594 /* pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10595 /* pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10596 /* pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10599 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10600 ifx->generated = 1;
10604 /*-----------------------------------------------------------------*/
10605 /* genReceive - generate code for a receive iCode */
10606 /*-----------------------------------------------------------------*/
10607 static void genReceive (iCode *ic)
10610 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10612 if (isOperandInFarSpace(IC_RESULT(ic)) &&
10613 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10614 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10616 int size = getSize(operandType(IC_RESULT(ic)));
10617 int offset = fReturnSizePic - size;
10619 pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10620 fReturn[fReturnSizePic - offset - 1] : "acc"));
10623 aopOp(IC_RESULT(ic),ic,FALSE);
10624 size = AOP_SIZE(IC_RESULT(ic));
10627 pic14_emitcode ("pop","acc");
10628 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10633 aopOp(IC_RESULT(ic),ic,FALSE);
10635 assignResultValue(IC_RESULT(ic));
10638 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10641 /*-----------------------------------------------------------------*/
10642 /* genDummyRead - generate code for dummy read of volatiles */
10643 /*-----------------------------------------------------------------*/
10645 genDummyRead (iCode * ic)
10648 pic14_emitcode ("; genDummyRead","");
10649 pic14_emitcode ("; not implemented","");
10654 /*-----------------------------------------------------------------*/
10655 /* genpic14Code - generate code for pic14 based controllers */
10656 /*-----------------------------------------------------------------*/
10658 * At this point, ralloc.c has gone through the iCode and attempted
10659 * to optimize in a way suitable for a PIC. Now we've got to generate
10660 * PIC instructions that correspond to the iCode.
10662 * Once the instructions are generated, we'll pass through both the
10663 * peep hole optimizer and the pCode optimizer.
10664 *-----------------------------------------------------------------*/
10666 void genpic14Code (iCode *lic)
10673 lineHead = lineCurr = NULL;
10675 pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10678 /* if debug information required */
10679 if (options.debug && currFunc) {
10681 debugFile->writeFunction (currFunc, lic);
10686 for (ic = lic ; ic ; ic = ic->next ) {
10688 //DEBUGpic14_emitcode(";ic","");
10689 //fprintf (stderr, "in ic loop\n");
10690 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10691 //ic->lineno, printCLine(ic->filename, ic->lineno));
10693 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10695 //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10696 cline = printCLine (ic->filename, ic->lineno);
10697 if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10698 addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10699 //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10702 if (options.iCodeInAsm) {
10703 emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10705 /* if the result is marked as
10706 spilt and rematerializable or code for
10707 this has already been generated then
10709 if (resultRemat(ic) || ic->generated )
10712 /* depending on the operation */
10731 /* IPOP happens only when trying to restore a
10732 spilt live range, if there is an ifx statement
10733 following this pop then the if statement might
10734 be using some of the registers being popped which
10735 would destory the contents of the register so
10736 we need to check for this condition and handle it */
10738 ic->next->op == IFX &&
10739 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10740 genIfx (ic->next,ic);
10758 genEndFunction (ic);
10778 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10795 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
10799 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10806 /* note these two are xlated by algebraic equivalence
10807 during parsing SDCC.y */
10808 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10809 "got '>=' or '<=' shouldn't have come here");
10813 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10825 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10829 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10833 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10857 genRightShift (ic);
10860 case GET_VALUE_AT_ADDRESS:
10865 if (POINTER_SET(ic))
10892 addSet(&_G.sendSet,ic);
10895 case DUMMY_READ_VOLATILE:
10905 /* now we are ready to call the
10906 peep hole optimizer */
10907 if (!options.nopeep) {
10908 peepHole (&lineHead);
10910 /* now do the actual printing */
10911 printLine (lineHead,codeOutFile);
10914 DFPRINTF((stderr,"printing pBlock\n\n"));
10915 printpBlock(stdout,pb);
10922 aop_isLitLike (asmop *aop)
10925 if (aop->type == AOP_LIT) return 1;
10926 if (aop->type == AOP_IMMD) return 1;
10927 if ((aop->type == AOP_PCODE) &&
10928 ((aop->aopu.pcop->type == PO_LITERAL) || (aop->aopu.pcop->type == PO_IMMEDIATE)))
10930 /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10931 * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10938 op_isLitLike (operand *op)
10941 if (aop_isLitLike (AOP(op))) return 1;