1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for pic
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 PIC port - Scott Dattalo scott@dattalo.com (2000)
9 This program is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 In other words, you are welcome to use, share and improve this program.
24 You are forbidden to forbid anyone else to use, share and improve
25 what you give them. Help stamp out software-hoarding!
28 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
29 Made everything static
30 -------------------------------------------------------------------------*/
36 #include "SDCCglobl.h"
40 #include "SDCCpeeph.h"
45 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
46 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
47 void genMult8X8_8 (operand *, operand *,operand *);
48 extern void printpBlock(FILE *of, pBlock *pb);
50 static int labelOffset=0;
51 extern int debug_verbose;
52 static int optimized_for_speed = 0;
54 /* max_key keeps track of the largest label number used in
55 a function. This is then used to adjust the label offset
56 for the next function.
59 static int GpsuedoStkPtr=0;
61 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
62 unsigned int pic14aopLiteral (value *val, int offset);
63 const char *AopType(short type);
65 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0x00ff)
67 /* this is the down and dirty file with all kinds of
68 kludgy & hacky stuff. This is what it is all about
69 CODE GENERATION for a specific MCU . some of the
70 routines may be reusable, will have to see */
72 static char *zero = "#0x00";
73 static char *one = "#0x01";
74 static char *spname = "sp";
76 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
77 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
78 static char **fReturn = fReturnpic14;
80 //static char *accUse[] = {"a","b"};
82 //static short rbank = -1;
94 /* Resolved ifx structure. This structure stores information
95 about an iCode ifx that makes it easier to generate code.
97 typedef struct resolvedIfx {
98 symbol *lbl; /* pointer to a label */
99 int condition; /* true or false ifx */
100 int generated; /* set true when the code associated with the ifx
104 extern int pic14_ptrRegReq ;
105 extern int pic14_nRegs;
106 extern FILE *codeOutFile;
107 static void saverbank (int, iCode *,bool);
109 static lineNode *lineHead = NULL;
110 static lineNode *lineCurr = NULL;
112 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
113 0xE0, 0xC0, 0x80, 0x00};
114 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
115 0x07, 0x03, 0x01, 0x00};
119 /*-----------------------------------------------------------------*/
120 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
121 /* exponent of 2 is returned, otherwise -1 is */
123 /* note that this is similar to the function `powof2' in SDCCsymt */
127 /*-----------------------------------------------------------------*/
128 static int my_powof2 (unsigned long num)
131 if( (num & (num-1)) == 0) {
144 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
147 DEBUGpic14_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
149 ((result) ? AopType(AOP_TYPE(result)) : "-"),
150 ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
151 ((left) ? AopType(AOP_TYPE(left)) : "-"),
152 ((left) ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
153 ((right) ? AopType(AOP_TYPE(right)) : "-"),
154 ((right) ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
155 ((result) ? AOP_SIZE(result) : 0));
159 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
162 DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
164 ((result) ? AopType(AOP_TYPE(result)) : "-"),
165 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
166 ((left) ? AopType(AOP_TYPE(left)) : "-"),
167 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
168 ((right) ? AopType(AOP_TYPE(right)) : "-"),
169 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
173 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
176 char lb[INITIAL_INLINEASM];
179 if(!debug_verbose && !options.debug)
186 sprintf(lb,"%s\t",inst);
188 sprintf(lb,"%s",inst);
189 vsprintf(lb+(strlen(lb)),fmt,ap);
193 while (isspace(*lbp)) lbp++;
196 lineCurr = (lineCurr ?
197 connectLine(lineCurr,newLineNode(lb)) :
198 (lineHead = newLineNode(lb)));
199 lineCurr->isInline = _G.inLine;
200 lineCurr->isDebug = _G.debugLine;
202 addpCode2pBlock(pb,newpCodeCharP(lb));
207 static void Safe_vsnprintf (char *buf, size_t size, const char *fmt, va_list ap)
209 #if defined (HAVE_VSNPRINTF)
210 vsnprintf (buf, size, fmt, ap);
211 #elif defined (HAVE_VSPRINTF)
212 vsprintf (buf, size, fmt, ap);
213 if (strlen (buf) >= size)
215 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
217 #elif defined (HAVE_SNPRINTF)
218 snprintf (buf, size, "vs(n)printf required");
219 #elif defined (HAVE_SRINTF)
220 sprintf (buf, "vs(n)printf required");
221 if (strlen (buf) >= size)
223 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
226 assert ( !"neither vsnprintf nor vsprintf is present -- unable to proceed" );
230 void emitpComment (const char *fmt, ...)
237 Safe_vsnprintf (buffer, 4096, fmt, va);
238 //fprintf (stderr, "%s\n" ,buffer);
239 addpCode2pBlock (pb, newpCodeCharP (buffer));
244 void emitpLabel(int key)
246 addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
249 void emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
252 addpCode2pBlock(pb,newpCode(poc,pcop));
254 DEBUGpic14_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
257 void emitpcodeNULLop(PIC_OPCODE poc)
260 addpCode2pBlock(pb,newpCode(poc,NULL));
265 /*-----------------------------------------------------------------*/
266 /* pic14_emitcode - writes the code into a file : for now it is simple */
267 /*-----------------------------------------------------------------*/
268 void pic14_emitcode (char *inst,char *fmt, ...)
271 char lb[INITIAL_INLINEASM];
278 sprintf(lb,"%s\t",inst);
280 sprintf(lb,"%s",inst);
281 vsprintf(lb+(strlen(lb)),fmt,ap);
285 while (isspace(*lbp)) lbp++;
288 lineCurr = (lineCurr ?
289 connectLine(lineCurr,newLineNode(lb)) :
290 (lineHead = newLineNode(lb)));
291 lineCurr->isInline = _G.inLine;
292 lineCurr->isDebug = _G.debugLine;
295 addpCode2pBlock(pb,newpCodeCharP(lb));
300 /*-----------------------------------------------------------------*/
301 /* pic14_emitDebuggerSymbol - associate the current code location */
302 /* with a debugger symbol */
303 /*-----------------------------------------------------------------*/
305 pic14_emitDebuggerSymbol (char * debugSym)
308 pic14_emitcode ("", ";%s ==.", debugSym);
313 /*-----------------------------------------------------------------*/
314 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
315 /*-----------------------------------------------------------------*/
316 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
318 bool r0iu = FALSE , r1iu = FALSE;
319 bool r0ou = FALSE , r1ou = FALSE;
321 /* the logic: if r0 & r1 used in the instruction
322 then we are in trouble otherwise */
324 /* first check if r0 & r1 are used by this
325 instruction, in which case we are in trouble */
326 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
327 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
332 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
333 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
335 /* if no usage of r0 then return it */
336 if (!r0iu && !r0ou) {
337 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
338 (*aopp)->type = AOP_R0;
340 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
343 /* if no usage of r1 then return it */
344 if (!r1iu && !r1ou) {
345 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
346 (*aopp)->type = AOP_R1;
348 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
351 /* now we know they both have usage */
352 /* if r0 not used in this instruction */
354 /* push it if not already pushed */
356 //pic14_emitcode ("push","%s",
357 // pic14_regWithIdx(R0_IDX)->dname);
361 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
362 (*aopp)->type = AOP_R0;
364 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
367 /* if r1 not used then */
370 /* push it if not already pushed */
372 //pic14_emitcode ("push","%s",
373 // pic14_regWithIdx(R1_IDX)->dname);
377 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
378 (*aopp)->type = AOP_R1;
379 return pic14_regWithIdx(R1_IDX);
383 /* I said end of world but not quite end of world yet */
384 /* if this is a result then we can push it on the stack*/
386 (*aopp)->type = AOP_STK;
390 /* other wise this is true end of the world */
391 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
392 "getFreePtr should never reach here");
396 /*-----------------------------------------------------------------*/
397 /* newAsmop - creates a new asmOp */
398 /*-----------------------------------------------------------------*/
399 asmop *newAsmop (short type)
403 aop = Safe_calloc(1,sizeof(asmop));
408 static void genSetDPTR(int n)
412 pic14_emitcode(";", "Select standard DPTR");
413 pic14_emitcode("mov", "dps, #0x00");
417 pic14_emitcode(";", "Select alternate DPTR");
418 pic14_emitcode("mov", "dps, #0x01");
422 /*-----------------------------------------------------------------*/
423 /* resolveIfx - converts an iCode ifx into a form more useful for */
424 /* generating code */
425 /*-----------------------------------------------------------------*/
426 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
431 // DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
433 resIfx->condition = 1; /* assume that the ifx is true */
434 resIfx->generated = 0; /* indicate that the ifx has not been used */
437 resIfx->lbl = newiTempLabel(NULL); /* oops, there is no ifx. so create a label */
439 DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
440 __FUNCTION__,__LINE__,resIfx->lbl->key);
444 resIfx->lbl = IC_TRUE(ifx);
446 resIfx->lbl = IC_FALSE(ifx);
447 resIfx->condition = 0;
451 DEBUGpic14_emitcode("; ***","ifx true is non-null");
453 DEBUGpic14_emitcode("; ***","ifx false is non-null");
457 // DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
460 /*-----------------------------------------------------------------*/
461 /* pointerCode - returns the code for a pointer type */
462 /*-----------------------------------------------------------------*/
463 static int pointerCode (sym_link *etype)
466 return PTR_TYPE(SPEC_OCLS(etype));
470 /*-----------------------------------------------------------------*/
471 /* aopForSym - for a true symbol */
472 /*-----------------------------------------------------------------*/
473 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
476 memmap *space= SPEC_OCLS(sym->etype);
478 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
479 /* if already has one */
483 /* assign depending on the storage class */
484 /* if it is on the stack or indirectly addressable */
485 /* space we need to assign either r0 or r1 to it */
486 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
487 sym->aop = aop = newAsmop(0);
488 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
489 aop->size = getSize(sym->type);
491 /* now assign the address of the variable to
492 the pointer register */
493 if (aop->type != AOP_STK) {
497 pic14_emitcode("push","acc");
499 pic14_emitcode("mov","a,_bp");
500 pic14_emitcode("add","a,#0x%02x",
502 ((char)(sym->stack - _G.nRegsSaved )) :
503 ((char)sym->stack)) & 0xff);
504 pic14_emitcode("mov","%s,a",
505 aop->aopu.aop_ptr->name);
508 pic14_emitcode("pop","acc");
510 pic14_emitcode("mov","%s,#%s",
511 aop->aopu.aop_ptr->name,
513 aop->paged = space->paged;
515 aop->aopu.aop_stk = sym->stack;
519 if (sym->onStack && options.stack10bit)
521 /* It's on the 10 bit stack, which is located in
525 //DEBUGpic14_emitcode(";","%d",__LINE__);
528 pic14_emitcode("push","acc");
530 pic14_emitcode("mov","a,_bp");
531 pic14_emitcode("add","a,#0x%02x",
533 ((char)(sym->stack - _G.nRegsSaved )) :
534 ((char)sym->stack)) & 0xff);
537 pic14_emitcode ("mov","dpx1,#0x40");
538 pic14_emitcode ("mov","dph1,#0x00");
539 pic14_emitcode ("mov","dpl1, a");
543 pic14_emitcode("pop","acc");
545 sym->aop = aop = newAsmop(AOP_DPTR2);
546 aop->size = getSize(sym->type);
550 //DEBUGpic14_emitcode(";","%d",__LINE__);
551 /* if in bit space */
552 if (IN_BITSPACE(space)) {
553 sym->aop = aop = newAsmop (AOP_CRY);
554 aop->aopu.aop_dir = sym->rname ;
555 aop->size = getSize(sym->type);
556 //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
559 /* if it is in direct space */
560 if (IN_DIRSPACE(space)) {
561 sym->aop = aop = newAsmop (AOP_DIR);
562 aop->aopu.aop_dir = sym->rname ;
563 aop->size = getSize(sym->type);
564 DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
568 /* special case for a function */
569 if (IS_FUNC(sym->type)) {
571 sym->aop = aop = newAsmop(AOP_PCODE);
572 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
573 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
574 PCOI(aop->aopu.pcop)->_function = 1;
575 PCOI(aop->aopu.pcop)->index = 0;
576 aop->size = FPTRSIZE;
578 sym->aop = aop = newAsmop(AOP_IMMD);
579 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
580 strcpy(aop->aopu.aop_immd,sym->rname);
581 aop->size = FPTRSIZE;
583 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
588 /* only remaining is far space */
589 /* in which case DPTR gets the address */
590 sym->aop = aop = newAsmop(AOP_PCODE);
592 aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
593 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
594 PCOI(aop->aopu.pcop)->index = 0;
596 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
597 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
599 allocDirReg (IC_LEFT(ic));
601 aop->size = FPTRSIZE;
603 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
604 sym->aop = aop = newAsmop(AOP_DPTR);
605 pic14_emitcode ("mov","dptr,#%s", sym->rname);
606 aop->size = getSize(sym->type);
608 DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
611 /* if it is in code space */
612 if (IN_CODESPACE(space))
618 /*-----------------------------------------------------------------*/
619 /* aopForRemat - rematerialzes an object */
620 /*-----------------------------------------------------------------*/
621 static asmop *aopForRemat (operand *op) // x symbol *sym)
623 symbol *sym = OP_SYMBOL(op);
625 asmop *aop = newAsmop(AOP_PCODE);
629 ic = sym->rematiCode;
631 DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
632 if(IS_OP_POINTER(op)) {
633 DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
637 val += (int) operandLitValue(IC_RIGHT(ic));
638 } else if (ic->op == '-') {
639 val -= (int) operandLitValue(IC_RIGHT(ic));
643 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
646 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
647 aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
648 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
649 PCOI(aop->aopu.pcop)->index = val;
651 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
652 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
653 val, IS_PTR_CONST(operandType(op)));
655 // DEBUGpic14_emitcode(";","aop type %s",AopType(AOP_TYPE(IC_LEFT(ic))));
657 allocDirReg (IC_LEFT(ic));
662 int aopIdx (asmop *aop, int offset)
667 if(aop->type != AOP_REG)
670 return aop->aopu.aop_reg[offset]->rIdx;
673 /*-----------------------------------------------------------------*/
674 /* regsInCommon - two operands have some registers in common */
675 /*-----------------------------------------------------------------*/
676 static bool regsInCommon (operand *op1, operand *op2)
681 /* if they have registers in common */
682 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
685 sym1 = OP_SYMBOL(op1);
686 sym2 = OP_SYMBOL(op2);
688 if (sym1->nRegs == 0 || sym2->nRegs == 0)
691 for (i = 0 ; i < sym1->nRegs ; i++) {
696 for (j = 0 ; j < sym2->nRegs ;j++ ) {
700 if (sym2->regs[j] == sym1->regs[i])
708 /*-----------------------------------------------------------------*/
709 /* operandsEqu - equivalent */
710 /*-----------------------------------------------------------------*/
711 static bool operandsEqu ( operand *op1, operand *op2)
715 /* if they not symbols */
716 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
719 sym1 = OP_SYMBOL(op1);
720 sym2 = OP_SYMBOL(op2);
722 /* if both are itemps & one is spilt
723 and the other is not then false */
724 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
725 sym1->isspilt != sym2->isspilt )
728 /* if they are the same */
732 if (sym1->rname[0] && sym2->rname[0]
733 && strcmp (sym1->rname, sym2->rname) == 0)
737 /* if left is a tmp & right is not */
741 (sym1->usl.spillLoc == sym2))
748 (sym2->usl.spillLoc == sym1))
754 /*-----------------------------------------------------------------*/
755 /* pic14_sameRegs - two asmops have the same registers */
756 /*-----------------------------------------------------------------*/
757 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
764 if (aop1->type != AOP_REG ||
765 aop2->type != AOP_REG )
768 if (aop1->size != aop2->size )
771 for (i = 0 ; i < aop1->size ; i++ )
772 if (aop1->aopu.aop_reg[i] !=
773 aop2->aopu.aop_reg[i] )
779 /*-----------------------------------------------------------------*/
780 /* aopOp - allocates an asmop for an operand : */
781 /*-----------------------------------------------------------------*/
782 void aopOp (operand *op, iCode *ic, bool result)
791 /* if this a literal */
792 if (IS_OP_LITERAL(op)) {
793 op->aop = aop = newAsmop(AOP_LIT);
794 aop->aopu.aop_lit = op->operand.valOperand;
795 aop->size = getSize(operandType(op));
800 sym_link *type = operandType(op);
801 if(IS_PTR_CONST(type))
802 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
805 /* if already has a asmop then continue */
809 /* if the underlying symbol has a aop */
810 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
811 DEBUGpic14_emitcode(";","%d",__LINE__);
812 op->aop = OP_SYMBOL(op)->aop;
816 /* if this is a true symbol */
817 if (IS_TRUE_SYMOP(op)) {
818 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
819 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
823 /* this is a temporary : this has
829 e) can be a return use only */
834 /* if the type is a conditional */
835 if (sym->regType == REG_CND) {
836 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
841 /* if it is spilt then two situations
843 b) has a spill location */
844 if (sym->isspilt || sym->nRegs == 0) {
846 DEBUGpic14_emitcode(";","%d",__LINE__);
847 /* rematerialize it NOW */
850 sym->aop = op->aop = aop = aopForRemat (op);
851 aop->size = getSize(sym->type);
852 //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
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 rifx->generated = 1;
3716 /*-----------------------------------------------------------------*/
3718 /*-----------------------------------------------------------------*/
3719 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3725 if( (rifx->condition ^ invert_condition) & 1)
3730 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3731 rifx->generated = 1;
3734 /*-----------------------------------------------------------------*/
3736 /*-----------------------------------------------------------------*/
3737 static void genSkipz(iCode *ifx, int condition)
3749 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3751 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3754 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3756 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3759 /*-----------------------------------------------------------------*/
3761 /*-----------------------------------------------------------------*/
3762 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3769 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3771 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3774 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3775 rifx->generated = 1;
3779 /*-----------------------------------------------------------------*/
3780 /* genChkZeroes :- greater or less than comparison */
3781 /* For each byte in a literal that is zero, inclusive or the */
3782 /* the corresponding byte in the operand with W */
3783 /* returns true if any of the bytes are zero */
3784 /*-----------------------------------------------------------------*/
3785 static int genChkZeroes(operand *op, int lit, int size)
3792 i = (lit >> (size*8)) & 0xff;
3796 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3798 emitpcode(POC_IORFW, popGet(AOP(op),size));
3807 /*-----------------------------------------------------------------*/
3808 /* genCmp :- greater or less than comparison */
3809 /*-----------------------------------------------------------------*/
3810 static void genCmp (operand *left,operand *right,
3811 operand *result, iCode *ifx, int sign)
3813 int size; //, offset = 0 ;
3814 unsigned long lit = 0L,i = 0;
3815 resolvedIfx rFalseIfx;
3816 // resolvedIfx rTrueIfx;
3820 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3823 DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
3824 DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
3828 resolveIfx(&rFalseIfx,ifx);
3829 truelbl = newiTempLabel(NULL);
3830 size = max(AOP_SIZE(left),AOP_SIZE(right));
3832 DEBUGpic14_AopType(__LINE__,left,right,result);
3836 /* if literal is on the right then swap with left */
3837 if ((AOP_TYPE(right) == AOP_LIT)) {
3838 operand *tmp = right ;
3839 unsigned long mask = (0x100 << (8*(size-1))) - 1;
3840 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3843 lit = (lit - 1) & mask;
3846 rFalseIfx.condition ^= 1;
3849 } else if ((AOP_TYPE(left) == AOP_LIT)) {
3850 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3854 //if(IC_TRUE(ifx) == NULL)
3855 /* if left & right are bit variables */
3856 if (AOP_TYPE(left) == AOP_CRY &&
3857 AOP_TYPE(right) == AOP_CRY ) {
3858 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3859 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3861 /* subtract right from left if at the
3862 end the carry flag is set then we know that
3863 left is greater than right */
3865 symbol *lbl = newiTempLabel(NULL);
3868 if(AOP_TYPE(right) == AOP_LIT) {
3870 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3872 DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
3879 genSkipCond(&rFalseIfx,left,size-1,7);
3881 /* no need to compare to 0...*/
3882 /* NOTE: this is a de-generate compare that most certainly
3883 * creates some dead code. */
3884 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3886 if(ifx) ifx->generated = 1;
3893 //i = (lit >> (size*8)) & 0xff;
3894 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3896 emitpcode(POC_MOVFW, popGet(AOP(left),size));
3898 i = ((0-lit) & 0xff);
3901 /* lit is 0x7f, all signed chars are less than
3902 * this except for 0x7f itself */
3903 emitpcode(POC_XORLW, popGetLit(0x7f));
3904 genSkipz2(&rFalseIfx,0);
3906 emitpcode(POC_ADDLW, popGetLit(0x80));
3907 emitpcode(POC_ADDLW, popGetLit(i^0x80));
3908 genSkipc(&rFalseIfx);
3913 genSkipz2(&rFalseIfx,1);
3915 emitpcode(POC_ADDLW, popGetLit(i));
3916 genSkipc(&rFalseIfx);
3920 if(ifx) ifx->generated = 1;
3924 /* chars are out of the way. now do ints and longs */
3927 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3934 genSkipCond(&rFalseIfx,left,size,7);
3935 if(ifx) ifx->generated = 1;
3940 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3942 //rFalseIfx.condition ^= 1;
3943 //genSkipCond(&rFalseIfx,left,size,7);
3944 //rFalseIfx.condition ^= 1;
3946 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3947 if(rFalseIfx.condition)
3948 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
3950 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
3952 emitpcode(POC_MOVLW, popGetLit(0x100-lit));
3953 emitpcode(POC_ADDFW, popGet(AOP(left),0));
3954 emitpcode(POC_MOVFW, popGet(AOP(left),1));
3957 emitpcode(POC_IORFW, popGet(AOP(left),size--));
3959 if(rFalseIfx.condition) {
3961 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
3967 genSkipc(&rFalseIfx);
3968 emitpLabel(truelbl->key);
3969 if(ifx) ifx->generated = 1;
3976 if( (lit & 0xff) == 0) {
3977 /* lower byte is zero */
3978 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3979 i = ((lit >> 8) & 0xff) ^0x80;
3980 emitpcode(POC_MOVFW, popGet(AOP(left),size));
3981 emitpcode(POC_ADDLW, popGetLit( 0x80));
3982 emitpcode(POC_ADDLW, popGetLit(0x100-i));
3983 genSkipc(&rFalseIfx);
3986 if(ifx) ifx->generated = 1;
3991 /* Special cases for signed longs */
3992 if( (lit & 0xffffff) == 0) {
3993 /* lower byte is zero */
3994 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3995 i = ((lit >> 8*3) & 0xff) ^0x80;
3996 emitpcode(POC_MOVFW, popGet(AOP(left),size));
3997 emitpcode(POC_ADDLW, popGetLit( 0x80));
3998 emitpcode(POC_ADDLW, popGetLit(0x100-i));
3999 genSkipc(&rFalseIfx);
4002 if(ifx) ifx->generated = 1;
4010 if(lit & (0x80 << (size*8))) {
4011 /* lit is negative */
4012 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4014 //genSkipCond(&rFalseIfx,left,size,7);
4016 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4018 if(rFalseIfx.condition)
4019 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4021 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4025 /* lit is positive */
4026 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4027 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4028 if(rFalseIfx.condition)
4029 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4031 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4035 /* There are no more special cases, so perform a general compare */
4037 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4038 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4042 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4044 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4046 //rFalseIfx.condition ^= 1;
4047 genSkipc(&rFalseIfx);
4049 emitpLabel(truelbl->key);
4051 if(ifx) ifx->generated = 1;
4058 /* sign is out of the way. So now do an unsigned compare */
4059 DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4062 /* General case - compare to an unsigned literal on the right.*/
4064 i = (lit >> (size*8)) & 0xff;
4065 emitpcode(POC_MOVLW, popGetLit(i));
4066 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4068 i = (lit >> (size*8)) & 0xff;
4071 emitpcode(POC_MOVLW, popGetLit(i));
4073 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4075 /* this byte of the lit is zero,
4076 *if it's not the last then OR in the variable */
4078 emitpcode(POC_IORFW, popGet(AOP(left),size));
4083 emitpLabel(lbl->key);
4084 //if(emitFinalCheck)
4085 genSkipc(&rFalseIfx);
4087 emitpLabel(truelbl->key);
4089 if(ifx) ifx->generated = 1;
4096 if(AOP_TYPE(left) == AOP_LIT) {
4097 //symbol *lbl = newiTempLabel(NULL);
4099 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4102 DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4105 if((lit == 0) && (sign == 0)){
4108 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4110 emitpcode(POC_IORFW, popGet(AOP(right),--size));
4112 genSkipz2(&rFalseIfx,0);
4113 if(ifx) ifx->generated = 1;
4120 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4121 /* degenerate compare can never be true */
4122 if(rFalseIfx.condition == 0)
4123 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4125 if(ifx) ifx->generated = 1;
4130 /* signed comparisons to a literal byte */
4132 int lp1 = (lit+1) & 0xff;
4134 DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4137 rFalseIfx.condition ^= 1;
4138 genSkipCond(&rFalseIfx,right,0,7);
4141 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4142 emitpcode(POC_XORLW, popGetLit(0x7f));
4143 genSkipz2(&rFalseIfx,1);
4146 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4147 emitpcode(POC_ADDLW, popGetLit(0x80));
4148 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4149 rFalseIfx.condition ^= 1;
4150 genSkipc(&rFalseIfx);
4153 if(ifx) ifx->generated = 1;
4155 /* unsigned comparisons to a literal byte */
4157 switch(lit & 0xff ) {
4159 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4160 genSkipz2(&rFalseIfx,0);
4161 if(ifx) ifx->generated = 1;
4164 genSkipCond(&rFalseIfx,right,0,7);
4165 if(ifx) ifx->generated = 1;
4169 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4170 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4171 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4172 rFalseIfx.condition ^= 1;
4173 if (AOP_TYPE(result) == AOP_CRY) {
4174 genSkipc(&rFalseIfx);
4175 if(ifx) ifx->generated = 1;
4177 DEBUGpic14_emitcode ("; ***","%s %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4178 emitpcode(POC_CLRF, popGet(AOP(result),0));
4179 emitpcode(POC_RLF, popGet(AOP(result),0));
4180 emitpcode(POC_MOVLW, popGetLit(0x01));
4181 emitpcode(POC_XORWF, popGet(AOP(result),0));
4192 /* Size is greater than 1 */
4200 /* this means lit = 0xffffffff, or -1 */
4203 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4204 rFalseIfx.condition ^= 1;
4205 genSkipCond(&rFalseIfx,right,size,7);
4206 if(ifx) ifx->generated = 1;
4213 if(rFalseIfx.condition) {
4214 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4215 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4218 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4220 emitpcode(POC_IORFW, popGet(AOP(right),size));
4224 if(rFalseIfx.condition) {
4225 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4226 emitpLabel(truelbl->key);
4228 rFalseIfx.condition ^= 1;
4229 genSkipCond(&rFalseIfx,right,s,7);
4232 if(ifx) ifx->generated = 1;
4236 if((size == 1) && (0 == (lp1&0xff))) {
4237 /* lower byte of signed word is zero */
4238 DEBUGpic14_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
4239 i = ((lp1 >> 8) & 0xff) ^0x80;
4240 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4241 emitpcode(POC_ADDLW, popGetLit( 0x80));
4242 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4243 rFalseIfx.condition ^= 1;
4244 genSkipc(&rFalseIfx);
4247 if(ifx) ifx->generated = 1;
4251 if(lit & (0x80 << (size*8))) {
4252 /* Lit is less than zero */
4253 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
4254 //rFalseIfx.condition ^= 1;
4255 //genSkipCond(&rFalseIfx,left,size,7);
4256 //rFalseIfx.condition ^= 1;
4257 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4258 //emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4260 if(rFalseIfx.condition)
4261 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4263 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4267 /* Lit is greater than or equal to zero */
4268 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
4269 //rFalseIfx.condition ^= 1;
4270 //genSkipCond(&rFalseIfx,right,size,7);
4271 //rFalseIfx.condition ^= 1;
4273 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4274 //emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4276 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4277 if(rFalseIfx.condition)
4278 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4280 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4285 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4286 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4290 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4292 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4294 rFalseIfx.condition ^= 1;
4295 //rFalseIfx.condition = 1;
4296 genSkipc(&rFalseIfx);
4298 emitpLabel(truelbl->key);
4300 if(ifx) ifx->generated = 1;
4305 /* compare word or long to an unsigned literal on the right.*/
4310 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4313 break; /* handled above */
4316 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4318 emitpcode(POC_IORFW, popGet(AOP(right),size));
4319 genSkipz2(&rFalseIfx,0);
4323 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4325 emitpcode(POC_IORFW, popGet(AOP(right),size));
4328 if(rFalseIfx.condition)
4329 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4331 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4334 emitpcode(POC_MOVLW, popGetLit(lit+1));
4335 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4337 rFalseIfx.condition ^= 1;
4338 genSkipc(&rFalseIfx);
4341 emitpLabel(truelbl->key);
4343 if(ifx) ifx->generated = 1;
4349 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4350 i = (lit >> (size*8)) & 0xff;
4352 emitpcode(POC_MOVLW, popGetLit(i));
4353 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4356 i = (lit >> (size*8)) & 0xff;
4359 emitpcode(POC_MOVLW, popGetLit(i));
4361 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4363 /* this byte of the lit is zero,
4364 *if it's not the last then OR in the variable */
4366 emitpcode(POC_IORFW, popGet(AOP(right),size));
4371 emitpLabel(lbl->key);
4373 rFalseIfx.condition ^= 1;
4374 genSkipc(&rFalseIfx);
4378 emitpLabel(truelbl->key);
4379 if(ifx) ifx->generated = 1;
4383 /* Compare two variables */
4385 DEBUGpic14_emitcode(";sign","%d",sign);
4389 /* Sigh. thus sucks... */
4391 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4392 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4393 emitpcode(POC_MOVLW, popGetLit(0x80));
4394 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4395 emitpcode(POC_XORFW, popGet(AOP(right),size));
4396 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4398 /* Signed char comparison */
4399 /* Special thanks to Nikolai Golovchenko for this snippet */
4400 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4401 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4402 emitpcode(POC_RRFW, popGet(AOP(left),0)); /* could be any register */
4403 emitpcode(POC_XORFW, popGet(AOP(left),0));
4404 emitpcode(POC_XORFW, popGet(AOP(right),0));
4405 emitpcode(POC_ADDLW, popGetLit(0x80));
4407 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4408 genSkipc(&rFalseIfx);
4410 if(ifx) ifx->generated = 1;
4416 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4417 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4421 /* The rest of the bytes of a multi-byte compare */
4425 emitpcode(POC_GOTO, popGetLabel(lbl->key));
4428 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4429 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4434 emitpLabel(lbl->key);
4436 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4437 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
4438 (AOP_TYPE(result) == AOP_REG)) {
4439 emitpcode(POC_CLRF, popGet(AOP(result),0));
4440 emitpcode(POC_RLF, popGet(AOP(result),0));
4442 genSkipc(&rFalseIfx);
4444 //genSkipc(&rFalseIfx);
4445 if(ifx) ifx->generated = 1;
4452 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4453 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4454 pic14_outBitC(result);
4456 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4457 /* if the result is used in the next
4458 ifx conditional branch then generate
4459 code a little differently */
4461 genIfxJump (ifx,"c");
4463 pic14_outBitC(result);
4464 /* leave the result in acc */
4469 /*-----------------------------------------------------------------*/
4470 /* genCmpGt :- greater than comparison */
4471 /*-----------------------------------------------------------------*/
4472 static void genCmpGt (iCode *ic, iCode *ifx)
4474 operand *left, *right, *result;
4475 sym_link *letype , *retype;
4479 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4481 right= IC_RIGHT(ic);
4482 result = IC_RESULT(ic);
4484 letype = getSpec(operandType(left));
4485 retype =getSpec(operandType(right));
4486 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4487 /* assign the amsops */
4488 aopOp (left,ic,FALSE);
4489 aopOp (right,ic,FALSE);
4490 aopOp (result,ic,TRUE);
4492 genCmp(right, left, result, ifx, sign);
4494 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4495 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4496 freeAsmop(result,NULL,ic,TRUE);
4499 /*-----------------------------------------------------------------*/
4500 /* genCmpLt - less than comparisons */
4501 /*-----------------------------------------------------------------*/
4502 static void genCmpLt (iCode *ic, iCode *ifx)
4504 operand *left, *right, *result;
4505 sym_link *letype , *retype;
4509 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4511 right= IC_RIGHT(ic);
4512 result = IC_RESULT(ic);
4514 letype = getSpec(operandType(left));
4515 retype =getSpec(operandType(right));
4516 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4518 /* assign the amsops */
4519 aopOp (left,ic,FALSE);
4520 aopOp (right,ic,FALSE);
4521 aopOp (result,ic,TRUE);
4523 genCmp(left, right, result, ifx, sign);
4525 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4526 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4527 freeAsmop(result,NULL,ic,TRUE);
4530 /*-----------------------------------------------------------------*/
4531 /* genc16bit2lit - compare a 16 bit value to a literal */
4532 /*-----------------------------------------------------------------*/
4533 static void genc16bit2lit(operand *op, int lit, int offset)
4538 DEBUGpic14_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
4539 if( (lit&0xff) == 0)
4544 switch( BYTEofLONG(lit,i)) {
4546 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4549 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4552 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4555 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4556 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4561 switch( BYTEofLONG(lit,i)) {
4563 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4567 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4571 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4574 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4576 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4582 /*-----------------------------------------------------------------*/
4583 /* gencjneshort - compare and jump if not equal */
4584 /*-----------------------------------------------------------------*/
4585 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4587 int size = max(AOP_SIZE(left),AOP_SIZE(right));
4589 int res_offset = 0; /* the result may be a different size then left or right */
4590 int res_size = AOP_SIZE(result);
4594 unsigned long lit = 0L;
4596 if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4597 emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4600 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4601 DEBUGpic14_AopType(__LINE__,left,right,result);
4603 DEBUGpic14_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
4604 resolveIfx(&rIfx,ifx);
4605 lbl = newiTempLabel(NULL);
4608 /* if the left side is a literal or
4609 if the right is in a pointer register and left
4611 if ((AOP_TYPE(left) == AOP_LIT) ||
4612 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4617 if(AOP_TYPE(right) == AOP_LIT)
4618 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4620 /* if the right side is a literal then anything goes */
4621 if (AOP_TYPE(right) == AOP_LIT &&
4622 AOP_TYPE(left) != AOP_DIR ) {
4625 genc16bit2lit(left, lit, 0);
4627 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4632 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4633 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4635 emitpcode(POC_MOVF,popGet(AOP(left),offset));
4639 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4641 if(res_offset < res_size-1)
4649 /* if the right side is in a register or in direct space or
4650 if the left is a pointer register & right is not */
4651 else if (AOP_TYPE(right) == AOP_REG ||
4652 AOP_TYPE(right) == AOP_DIR ||
4653 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4654 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4655 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4656 int lbl_key = lbl->key;
4659 if (AOP_TYPE(result) != AOP_CRY)
4660 emitpcode(POC_CLRF,popGet(AOP(result),res_offset));
4661 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4663 DEBUGpic14_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
4664 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
4665 __FUNCTION__,__LINE__);
4669 /* switch(size) { */
4671 /* genc16bit2lit(left, lit, 0); */
4673 /* emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
4678 if((AOP_TYPE(left) == AOP_DIR) &&
4679 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4681 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4682 emitpcode(POC_XORFW,popGet(AOP(right),offset));
4684 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4686 switch (lit & 0xff) {
4688 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4691 emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4692 emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4693 //emitpcode(POC_GOTO,popGetLabel(lbl->key));
4697 emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4698 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4699 //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4700 emitpcode(POC_GOTO,popGetLabel(lbl_key));
4704 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4705 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4710 emitpcode(POC_MOVF,popGet(AOP(left),offset));
4713 if(AOP_TYPE(result) == AOP_CRY) {
4714 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
4719 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4721 /* fix me. probably need to check result size too */
4722 //emitpcode(POC_CLRF,popGet(AOP(result),0));
4727 emitpcode(POC_GOTO,popGetLabel(lbl_key));
4728 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4735 if(res_offset < res_size-1)
4740 } else if(AOP_TYPE(right) == AOP_REG &&
4741 AOP_TYPE(left) != AOP_DIR){
4744 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4745 emitpcode(POC_XORFW,popGet(AOP(right),offset));
4746 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
4751 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4753 if(res_offset < res_size-1)
4758 /* right is a pointer reg need both a & b */
4760 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4762 pic14_emitcode("mov","b,%s",l);
4763 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4764 pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
4769 emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4771 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4773 emitpLabel(lbl->key);
4775 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4782 /*-----------------------------------------------------------------*/
4783 /* gencjne - compare and jump if not equal */
4784 /*-----------------------------------------------------------------*/
4785 static void gencjne(operand *left, operand *right, iCode *ifx)
4787 symbol *tlbl = newiTempLabel(NULL);
4789 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4790 gencjneshort(left, right, lbl);
4792 pic14_emitcode("mov","a,%s",one);
4793 pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
4794 pic14_emitcode("","%05d_DS_:",lbl->key+100);
4795 pic14_emitcode("clr","a");
4796 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4798 emitpLabel(lbl->key);
4799 emitpLabel(tlbl->key);
4804 /*-----------------------------------------------------------------*/
4805 /* genCmpEq - generates code for equal to */
4806 /*-----------------------------------------------------------------*/
4807 static void genCmpEq (iCode *ic, iCode *ifx)
4809 operand *left, *right, *result;
4810 unsigned long lit = 0L;
4814 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4817 DEBUGpic14_emitcode ("; ifx is non-null","");
4819 DEBUGpic14_emitcode ("; ifx is null","");
4821 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4822 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4823 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4825 size = max(AOP_SIZE(left),AOP_SIZE(right));
4827 DEBUGpic14_AopType(__LINE__,left,right,result);
4829 /* if literal, literal on the right or
4830 if the right is in a pointer register and left
4832 if (aop_isLitLike (AOP(IC_LEFT(ic)))
4833 || (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4834 operand *tmp = right ;
4840 if(ifx && !AOP_SIZE(result)){
4842 /* if they are both bit variables */
4843 if (AOP_TYPE(left) == AOP_CRY &&
4844 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4845 if(AOP_TYPE(right) == AOP_LIT){
4846 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4848 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4849 pic14_emitcode("cpl","c");
4850 } else if(lit == 1L) {
4851 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4853 pic14_emitcode("clr","c");
4855 /* AOP_TYPE(right) == AOP_CRY */
4857 symbol *lbl = newiTempLabel(NULL);
4858 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4859 pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4860 pic14_emitcode("cpl","c");
4861 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4863 /* if true label then we jump if condition
4865 tlbl = newiTempLabel(NULL);
4866 if ( IC_TRUE(ifx) ) {
4867 pic14_emitcode("jnc","%05d_DS_",tlbl->key+100);
4868 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4870 pic14_emitcode("jc","%05d_DS_",tlbl->key+100);
4871 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4873 pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4876 /* left and right are both bit variables, result is carry */
4879 resolveIfx(&rIfx,ifx);
4881 emitpcode(POC_MOVLW,popGet(AOP(left),0));
4882 emitpcode(POC_ANDFW,popGet(AOP(left),0));
4883 emitpcode(POC_BTFSC,popGet(AOP(right),0));
4884 emitpcode(POC_ANDLW,popGet(AOP(left),0));
4889 /* They're not both bit variables. Is the right a literal? */
4890 if(AOP_TYPE(right) == AOP_LIT) {
4891 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4896 switch(lit & 0xff) {
4898 if ( IC_TRUE(ifx) ) {
4899 emitpcode(POC_DECFW,popGet(AOP(left),offset));
4901 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4903 emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4904 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4908 if ( IC_TRUE(ifx) ) {
4909 emitpcode(POC_INCFW,popGet(AOP(left),offset));
4911 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4913 emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4914 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4918 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4920 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4925 /* end of size == 1 */
4929 genc16bit2lit(left,lit,offset);
4932 /* end of size == 2 */
4937 emitpcode(POC_MOVFW,popGet(AOP(left),0));
4938 emitpcode(POC_IORFW,popGet(AOP(left),1));
4939 emitpcode(POC_IORFW,popGet(AOP(left),2));
4940 emitpcode(POC_IORFW,popGet(AOP(left),3));
4944 /* search for patterns that can be optimized */
4946 genc16bit2lit(left,lit,0);
4949 genSkipz(ifx,IC_TRUE(ifx) == NULL);
4951 genc16bit2lit(left,lit,2);
4953 emitpcode(POC_IORFW,popGet(AOP(left),2));
4954 emitpcode(POC_IORFW,popGet(AOP(left),3));
4967 } else if(AOP_TYPE(right) == AOP_CRY ) {
4968 /* we know the left is not a bit, but that the right is */
4969 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4970 emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4971 popGet(AOP(right),offset));
4972 emitpcode(POC_XORLW,popGetLit(1));
4974 /* if the two are equal, then W will be 0 and the Z bit is set
4975 * we could test Z now, or go ahead and check the high order bytes if
4976 * the variable we're comparing is larger than a byte. */
4979 emitpcode(POC_IORFW,popGet(AOP(left),offset));
4981 if ( IC_TRUE(ifx) ) {
4983 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4984 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4987 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4988 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4992 /* They're both variables that are larger than bits */
4995 tlbl = newiTempLabel(NULL);
4998 mov2w (AOP(right),offset); /* right might be litLike() */
4999 emitpcode(POC_XORFW,popGet(AOP(left),offset));
5001 if ( IC_TRUE(ifx) ) {
5004 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
5005 pic14_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
5008 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5009 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5013 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
5014 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5018 if(s>1 && IC_TRUE(ifx)) {
5019 emitpLabel(tlbl->key);
5020 pic14_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);
5024 /* mark the icode as generated */
5029 /* if they are both bit variables */
5030 if (AOP_TYPE(left) == AOP_CRY &&
5031 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5032 if(AOP_TYPE(right) == AOP_LIT){
5033 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5035 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5036 pic14_emitcode("cpl","c");
5037 } else if(lit == 1L) {
5038 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5040 pic14_emitcode("clr","c");
5042 /* AOP_TYPE(right) == AOP_CRY */
5044 symbol *lbl = newiTempLabel(NULL);
5045 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5046 pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5047 pic14_emitcode("cpl","c");
5048 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
5051 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5052 pic14_outBitC(result);
5056 genIfxJump (ifx,"c");
5059 /* if the result is used in an arithmetic operation
5060 then put the result in place */
5061 pic14_outBitC(result);
5064 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5065 gencjne(left,right,result,ifx);
5068 gencjne(left,right,newiTempLabel(NULL));
5070 if(IC_TRUE(ifx)->key)
5071 gencjne(left,right,IC_TRUE(ifx)->key);
5073 gencjne(left,right,IC_FALSE(ifx)->key);
5077 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5078 aopPut(AOP(result),"a",0);
5083 genIfxJump (ifx,"a");
5087 /* if the result is used in an arithmetic operation
5088 then put the result in place */
5090 if (AOP_TYPE(result) != AOP_CRY)
5091 pic14_outAcc(result);
5093 /* leave the result in acc */
5097 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5098 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5099 freeAsmop(result,NULL,ic,TRUE);
5102 /*-----------------------------------------------------------------*/
5103 /* ifxForOp - returns the icode containing the ifx for operand */
5104 /*-----------------------------------------------------------------*/
5105 static iCode *ifxForOp ( operand *op, iCode *ic )
5108 /* if true symbol then needs to be assigned */
5109 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5110 if (IS_TRUE_SYMOP(op))
5113 /* if this has register type condition and
5114 the next instruction is ifx with the same operand
5115 and live to of the operand is upto the ifx only then */
5117 ic->next->op == IFX &&
5118 IC_COND(ic->next)->key == op->key &&
5119 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5123 ic->next->op == IFX &&
5124 IC_COND(ic->next)->key == op->key) {
5125 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5129 DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5131 ic->next->op == IFX)
5132 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5135 ic->next->op == IFX &&
5136 IC_COND(ic->next)->key == op->key) {
5137 DEBUGpic14_emitcode ("; "," key is okay");
5138 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5139 OP_SYMBOL(op)->liveTo,
5146 /*-----------------------------------------------------------------*/
5147 /* genAndOp - for && operation */
5148 /*-----------------------------------------------------------------*/
5149 static void genAndOp (iCode *ic)
5151 operand *left,*right, *result;
5155 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5156 /* note here that && operations that are in an
5157 if statement are taken away by backPatchLabels
5158 only those used in arthmetic operations remain */
5159 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5160 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5161 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5163 DEBUGpic14_AopType(__LINE__,left,right,result);
5165 emitpcode(POC_MOVFW,popGet(AOP(left),0));
5166 emitpcode(POC_ANDFW,popGet(AOP(right),0));
5167 emitpcode(POC_MOVWF,popGet(AOP(result),0));
5169 /* if both are bit variables */
5170 /* if (AOP_TYPE(left) == AOP_CRY && */
5171 /* AOP_TYPE(right) == AOP_CRY ) { */
5172 /* pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5173 /* pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5174 /* pic14_outBitC(result); */
5176 /* tlbl = newiTempLabel(NULL); */
5177 /* pic14_toBoolean(left); */
5178 /* pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5179 /* pic14_toBoolean(right); */
5180 /* pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5181 /* pic14_outBitAcc(result); */
5184 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5185 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5186 freeAsmop(result,NULL,ic,TRUE);
5190 /*-----------------------------------------------------------------*/
5191 /* genOrOp - for || operation */
5192 /*-----------------------------------------------------------------*/
5195 modified this code, but it doesn't appear to ever get called
5198 static void genOrOp (iCode *ic)
5200 operand *left,*right, *result;
5203 /* note here that || operations that are in an
5204 if statement are taken away by backPatchLabels
5205 only those used in arthmetic operations remain */
5207 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5208 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5209 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5210 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5212 DEBUGpic14_AopType(__LINE__,left,right,result);
5214 /* if both are bit variables */
5215 if (AOP_TYPE(left) == AOP_CRY &&
5216 AOP_TYPE(right) == AOP_CRY ) {
5217 pic14_emitcode("clrc","");
5218 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5219 AOP(left)->aopu.aop_dir,
5220 AOP(left)->aopu.aop_dir);
5221 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5222 AOP(right)->aopu.aop_dir,
5223 AOP(right)->aopu.aop_dir);
5224 pic14_emitcode("setc","");
5227 tlbl = newiTempLabel(NULL);
5228 pic14_toBoolean(left);
5230 pic14_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5231 pic14_toBoolean(right);
5232 pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5234 pic14_outBitAcc(result);
5237 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5238 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5239 freeAsmop(result,NULL,ic,TRUE);
5242 /*-----------------------------------------------------------------*/
5243 /* isLiteralBit - test if lit == 2^n */
5244 /*-----------------------------------------------------------------*/
5245 static int isLiteralBit(unsigned long lit)
5247 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5248 0x100L,0x200L,0x400L,0x800L,
5249 0x1000L,0x2000L,0x4000L,0x8000L,
5250 0x10000L,0x20000L,0x40000L,0x80000L,
5251 0x100000L,0x200000L,0x400000L,0x800000L,
5252 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5253 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5257 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5258 for(idx = 0; idx < 32; idx++)
5264 /*-----------------------------------------------------------------*/
5265 /* continueIfTrue - */
5266 /*-----------------------------------------------------------------*/
5267 static void continueIfTrue (iCode *ic)
5270 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5272 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5276 /*-----------------------------------------------------------------*/
5278 /*-----------------------------------------------------------------*/
5279 static void jumpIfTrue (iCode *ic)
5282 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5284 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5288 /*-----------------------------------------------------------------*/
5289 /* jmpTrueOrFalse - */
5290 /*-----------------------------------------------------------------*/
5291 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5294 // ugly but optimized by peephole
5295 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5297 symbol *nlbl = newiTempLabel(NULL);
5298 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5299 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5300 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5301 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5304 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5305 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5310 /*-----------------------------------------------------------------*/
5311 /* genAnd - code for and */
5312 /*-----------------------------------------------------------------*/
5313 static void genAnd (iCode *ic, iCode *ifx)
5315 operand *left, *right, *result;
5317 unsigned long lit = 0L;
5322 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5323 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5324 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5325 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5327 resolveIfx(&rIfx,ifx);
5329 /* if left is a literal & right is not then exchange them */
5330 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5331 AOP_NEEDSACC(left)) {
5332 operand *tmp = right ;
5337 /* if result = right then exchange them */
5338 if(pic14_sameRegs(AOP(result),AOP(right))){
5339 operand *tmp = right ;
5344 /* if right is bit then exchange them */
5345 if (AOP_TYPE(right) == AOP_CRY &&
5346 AOP_TYPE(left) != AOP_CRY){
5347 operand *tmp = right ;
5351 if(AOP_TYPE(right) == AOP_LIT)
5352 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5354 size = AOP_SIZE(result);
5356 DEBUGpic14_AopType(__LINE__,left,right,result);
5359 // result = bit & yy;
5360 if (AOP_TYPE(left) == AOP_CRY){
5361 // c = bit & literal;
5362 if(AOP_TYPE(right) == AOP_LIT){
5364 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5367 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5370 if(size && (AOP_TYPE(result) == AOP_CRY)){
5371 pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5374 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5378 pic14_emitcode("clr","c");
5381 if (AOP_TYPE(right) == AOP_CRY){
5383 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5384 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5387 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5389 pic14_emitcode("rrc","a");
5390 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5396 pic14_outBitC(result);
5398 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5399 genIfxJump(ifx, "c");
5403 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5404 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5405 if((AOP_TYPE(right) == AOP_LIT) &&
5406 (AOP_TYPE(result) == AOP_CRY) &&
5407 (AOP_TYPE(left) != AOP_CRY)){
5408 int posbit = isLiteralBit(lit);
5412 //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5415 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5420 while (posbit > 7) {
5424 emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5425 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5426 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5433 symbol *tlbl = newiTempLabel(NULL);
5434 int sizel = AOP_SIZE(left);
5436 pic14_emitcode("setb","c");
5438 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5439 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5441 if((posbit = isLiteralBit(bytelit)) != 0)
5442 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5444 if(bytelit != 0x0FFL)
5445 pic14_emitcode("anl","a,%s",
5446 aopGet(AOP(right),offset,FALSE,TRUE));
5447 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5452 // bit = left & literal
5454 pic14_emitcode("clr","c");
5455 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5457 // if(left & literal)
5460 jmpTrueOrFalse(ifx, tlbl);
5464 pic14_outBitC(result);
5468 /* if left is same as result */
5469 if(pic14_sameRegs(AOP(result),AOP(left))){
5471 for(;size--; offset++,lit>>=8) {
5472 if(AOP_TYPE(right) == AOP_LIT){
5473 switch(lit & 0xff) {
5475 /* and'ing with 0 has clears the result */
5476 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5479 /* and'ing with 0xff is a nop when the result and left are the same */
5484 int p = my_powof2( (~lit) & 0xff );
5486 /* only one bit is set in the literal, so use a bcf instruction */
5487 emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5490 if(know_W != (int)(lit&0xff))
5491 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5493 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5498 if (AOP_TYPE(left) == AOP_ACC) {
5499 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5501 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5502 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5509 // left & result in different registers
5510 if(AOP_TYPE(result) == AOP_CRY){
5512 // if(size), result in bit
5513 // if(!size && ifx), conditional oper: if(left & right)
5514 symbol *tlbl = newiTempLabel(NULL);
5515 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5517 pic14_emitcode("setb","c");
5519 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5520 pic14_emitcode("anl","a,%s",
5521 aopGet(AOP(left),offset,FALSE,FALSE));
5522 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5527 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5528 pic14_outBitC(result);
5530 jmpTrueOrFalse(ifx, tlbl);
5532 for(;(size--);offset++) {
5534 // result = left & right
5535 if(AOP_TYPE(right) == AOP_LIT){
5536 int t = (lit >> (offset*8)) & 0x0FFL;
5539 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5542 if(AOP_TYPE(left) != AOP_ACC) {
5543 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5545 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5548 if(AOP_TYPE(left) == AOP_ACC) {
5549 emitpcode(POC_ANDLW, popGetLit(t));
5551 emitpcode(POC_MOVLW, popGetLit(t));
5552 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5554 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5559 if (AOP_TYPE(left) == AOP_ACC) {
5560 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5562 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5563 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5565 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5571 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5572 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5573 freeAsmop(result,NULL,ic,TRUE);
5576 /*-----------------------------------------------------------------*/
5577 /* genOr - code for or */
5578 /*-----------------------------------------------------------------*/
5579 static void genOr (iCode *ic, iCode *ifx)
5581 operand *left, *right, *result;
5583 unsigned long lit = 0L;
5586 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5588 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5589 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5590 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5592 DEBUGpic14_AopType(__LINE__,left,right,result);
5594 /* if left is a literal & right is not then exchange them */
5595 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5596 AOP_NEEDSACC(left)) {
5597 operand *tmp = right ;
5602 /* if result = right then exchange them */
5603 if(pic14_sameRegs(AOP(result),AOP(right))){
5604 operand *tmp = right ;
5609 /* if right is bit then exchange them */
5610 if (AOP_TYPE(right) == AOP_CRY &&
5611 AOP_TYPE(left) != AOP_CRY){
5612 operand *tmp = right ;
5617 DEBUGpic14_AopType(__LINE__,left,right,result);
5619 if(AOP_TYPE(right) == AOP_LIT)
5620 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5622 size = AOP_SIZE(result);
5626 if (AOP_TYPE(left) == AOP_CRY){
5627 if(AOP_TYPE(right) == AOP_LIT){
5628 // c = bit & literal;
5630 // lit != 0 => result = 1
5631 if(AOP_TYPE(result) == AOP_CRY){
5633 emitpcode(POC_BSF, popGet(AOP(result),0));
5634 //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5635 // AOP(result)->aopu.aop_dir,
5636 // AOP(result)->aopu.aop_dir);
5638 continueIfTrue(ifx);
5642 // lit == 0 => result = left
5643 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5645 pic14_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5648 if (AOP_TYPE(right) == AOP_CRY){
5649 if(pic14_sameRegs(AOP(result),AOP(left))){
5651 emitpcode(POC_BCF, popGet(AOP(result),0));
5652 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5653 emitpcode(POC_BSF, popGet(AOP(result),0));
5655 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5656 AOP(result)->aopu.aop_dir,
5657 AOP(result)->aopu.aop_dir);
5658 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5659 AOP(right)->aopu.aop_dir,
5660 AOP(right)->aopu.aop_dir);
5661 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5662 AOP(result)->aopu.aop_dir,
5663 AOP(result)->aopu.aop_dir);
5665 if( AOP_TYPE(result) == AOP_ACC) {
5666 emitpcode(POC_MOVLW, popGetLit(0));
5667 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5668 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5669 emitpcode(POC_MOVLW, popGetLit(1));
5673 emitpcode(POC_BCF, popGet(AOP(result),0));
5674 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5675 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5676 emitpcode(POC_BSF, popGet(AOP(result),0));
5678 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5679 AOP(result)->aopu.aop_dir,
5680 AOP(result)->aopu.aop_dir);
5681 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5682 AOP(right)->aopu.aop_dir,
5683 AOP(right)->aopu.aop_dir);
5684 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5685 AOP(left)->aopu.aop_dir,
5686 AOP(left)->aopu.aop_dir);
5687 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5688 AOP(result)->aopu.aop_dir,
5689 AOP(result)->aopu.aop_dir);
5694 symbol *tlbl = newiTempLabel(NULL);
5695 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5698 emitpcode(POC_BCF, popGet(AOP(result),0));
5699 if( AOP_TYPE(right) == AOP_ACC) {
5700 emitpcode(POC_IORLW, popGetLit(0));
5702 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5703 emitpcode(POC_BSF, popGet(AOP(result),0));
5708 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5709 pic14_emitcode(";XXX setb","c");
5710 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5711 AOP(left)->aopu.aop_dir,tlbl->key+100);
5712 pic14_toBoolean(right);
5713 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5714 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5715 jmpTrueOrFalse(ifx, tlbl);
5719 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5726 pic14_outBitC(result);
5728 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5729 genIfxJump(ifx, "c");
5733 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5734 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5735 if((AOP_TYPE(right) == AOP_LIT) &&
5736 (AOP_TYPE(result) == AOP_CRY) &&
5737 (AOP_TYPE(left) != AOP_CRY)){
5739 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5742 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5744 continueIfTrue(ifx);
5747 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5748 // lit = 0, result = boolean(left)
5750 pic14_emitcode(";XXX setb","c");
5751 pic14_toBoolean(right);
5753 symbol *tlbl = newiTempLabel(NULL);
5754 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5756 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5758 genIfxJump (ifx,"a");
5762 pic14_outBitC(result);
5766 /* if left is same as result */
5767 if(pic14_sameRegs(AOP(result),AOP(left))){
5769 for(;size--; offset++,lit>>=8) {
5770 if(AOP_TYPE(right) == AOP_LIT){
5771 if((lit & 0xff) == 0)
5772 /* or'ing with 0 has no effect */
5775 int p = my_powof2(lit & 0xff);
5777 /* only one bit is set in the literal, so use a bsf instruction */
5779 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5781 if(know_W != (int)(lit & 0xff))
5782 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5783 know_W = lit & 0xff;
5784 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5789 if (AOP_TYPE(left) == AOP_ACC) {
5790 emitpcode(POC_IORFW, popGet(AOP(right),offset));
5791 pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5793 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
5794 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5796 pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5797 pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5803 // left & result in different registers
5804 if(AOP_TYPE(result) == AOP_CRY){
5806 // if(size), result in bit
5807 // if(!size && ifx), conditional oper: if(left | right)
5808 symbol *tlbl = newiTempLabel(NULL);
5809 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5810 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5814 pic14_emitcode(";XXX setb","c");
5816 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5817 pic14_emitcode(";XXX orl","a,%s",
5818 aopGet(AOP(left),offset,FALSE,FALSE));
5819 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5824 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5825 pic14_outBitC(result);
5827 jmpTrueOrFalse(ifx, tlbl);
5828 } else for(;(size--);offset++){
5830 // result = left | right
5831 if(AOP_TYPE(right) == AOP_LIT){
5832 int t = (lit >> (offset*8)) & 0x0FFL;
5835 if (AOP_TYPE(left) != AOP_ACC) {
5836 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
5838 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5842 if (AOP_TYPE(left) == AOP_ACC) {
5843 emitpcode(POC_IORLW, popGetLit(t));
5845 emitpcode(POC_MOVLW, popGetLit(t));
5846 emitpcode(POC_IORFW, popGet(AOP(left),offset));
5848 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5853 // faster than result <- left, anl result,right
5854 // and better if result is SFR
5855 if (AOP_TYPE(left) == AOP_ACC) {
5856 emitpcode(POC_IORFW,popGet(AOP(right),offset));
5858 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5859 emitpcode(POC_IORFW,popGet(AOP(left),offset));
5861 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5866 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5867 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5868 freeAsmop(result,NULL,ic,TRUE);
5871 /*-----------------------------------------------------------------*/
5872 /* genXor - code for xclusive or */
5873 /*-----------------------------------------------------------------*/
5874 static void genXor (iCode *ic, iCode *ifx)
5876 operand *left, *right, *result;
5878 unsigned long lit = 0L;
5881 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5883 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5884 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5885 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5887 /* if left is a literal & right is not ||
5888 if left needs acc & right does not */
5889 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5890 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5891 operand *tmp = right ;
5896 /* if result = right then exchange them */
5897 if(pic14_sameRegs(AOP(result),AOP(right))){
5898 operand *tmp = right ;
5903 /* if right is bit then exchange them */
5904 if (AOP_TYPE(right) == AOP_CRY &&
5905 AOP_TYPE(left) != AOP_CRY){
5906 operand *tmp = right ;
5910 if(AOP_TYPE(right) == AOP_LIT)
5911 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5913 size = AOP_SIZE(result);
5917 if (AOP_TYPE(left) == AOP_CRY){
5918 if(AOP_TYPE(right) == AOP_LIT){
5919 // c = bit & literal;
5921 // lit>>1 != 0 => result = 1
5922 if(AOP_TYPE(result) == AOP_CRY){
5924 {emitpcode(POC_BSF, popGet(AOP(result),offset));
5925 pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
5927 continueIfTrue(ifx);
5930 pic14_emitcode("setb","c");
5934 // lit == 0, result = left
5935 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5937 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5939 // lit == 1, result = not(left)
5940 if(size && pic14_sameRegs(AOP(result),AOP(left))){
5941 emitpcode(POC_MOVLW, popGet(AOP(result),offset));
5942 emitpcode(POC_XORWF, popGet(AOP(result),offset));
5943 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5946 assert ( !"incomplete genXor" );
5947 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5948 pic14_emitcode("cpl","c");
5955 symbol *tlbl = newiTempLabel(NULL);
5956 if (AOP_TYPE(right) == AOP_CRY){
5958 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5961 int sizer = AOP_SIZE(right);
5963 // if val>>1 != 0, result = 1
5964 pic14_emitcode("setb","c");
5966 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5968 // test the msb of the lsb
5969 pic14_emitcode("anl","a,#0xfe");
5970 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5974 pic14_emitcode("rrc","a");
5976 pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5977 pic14_emitcode("cpl","c");
5978 pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
5983 pic14_outBitC(result);
5985 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5986 genIfxJump(ifx, "c");
5990 if(pic14_sameRegs(AOP(result),AOP(left))){
5991 /* if left is same as result */
5992 for(;size--; offset++) {
5993 if(AOP_TYPE(right) == AOP_LIT){
5994 int t = (lit >> (offset*8)) & 0x0FFL;
5998 if (IS_AOP_PREG(left)) {
5999 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6000 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6001 aopPut(AOP(result),"a",offset);
6003 emitpcode(POC_MOVLW, popGetLit(t));
6004 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6005 pic14_emitcode("xrl","%s,%s",
6006 aopGet(AOP(left),offset,FALSE,TRUE),
6007 aopGet(AOP(right),offset,FALSE,FALSE));
6010 if (AOP_TYPE(left) == AOP_ACC)
6011 pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6013 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6014 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6016 if (IS_AOP_PREG(left)) {
6017 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6018 aopPut(AOP(result),"a",offset);
6020 pic14_emitcode("xrl","%s,a",
6021 aopGet(AOP(left),offset,FALSE,TRUE));
6027 // left & result in different registers
6028 if(AOP_TYPE(result) == AOP_CRY){
6030 // if(size), result in bit
6031 // if(!size && ifx), conditional oper: if(left ^ right)
6032 symbol *tlbl = newiTempLabel(NULL);
6033 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6035 pic14_emitcode("setb","c");
6037 if((AOP_TYPE(right) == AOP_LIT) &&
6038 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6039 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6041 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6042 pic14_emitcode("xrl","a,%s",
6043 aopGet(AOP(left),offset,FALSE,FALSE));
6045 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6050 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6051 pic14_outBitC(result);
6053 jmpTrueOrFalse(ifx, tlbl);
6054 } else for(;(size--);offset++){
6056 // result = left & right
6057 if(AOP_TYPE(right) == AOP_LIT){
6058 int t = (lit >> (offset*8)) & 0x0FFL;
6061 if (AOP_TYPE(left) != AOP_ACC) {
6062 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6064 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6065 pic14_emitcode("movf","%s,w",
6066 aopGet(AOP(left),offset,FALSE,FALSE));
6067 pic14_emitcode("movwf","%s",
6068 aopGet(AOP(result),offset,FALSE,FALSE));
6071 if (AOP_TYPE(left) == AOP_ACC) {
6072 emitpcode(POC_XORLW, popGetLit(t));
6074 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6076 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6079 if (AOP_TYPE(left) == AOP_ACC) {
6080 emitpcode(POC_XORLW, popGetLit(t));
6082 emitpcode(POC_MOVLW, popGetLit(t));
6083 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6085 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6086 pic14_emitcode("movlw","0x%x",t);
6087 pic14_emitcode("xorwf","%s,w",
6088 aopGet(AOP(left),offset,FALSE,FALSE));
6089 pic14_emitcode("movwf","%s",
6090 aopGet(AOP(result),offset,FALSE,FALSE));
6096 // faster than result <- left, anl result,right
6097 // and better if result is SFR
6098 if (AOP_TYPE(left) == AOP_ACC) {
6099 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6101 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6102 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6104 if ( AOP_TYPE(result) != AOP_ACC){
6105 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6111 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6112 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6113 freeAsmop(result,NULL,ic,TRUE);
6116 /*-----------------------------------------------------------------*/
6117 /* genInline - write the inline code out */
6118 /*-----------------------------------------------------------------*/
6119 static void genInline (iCode *ic)
6121 char *buffer, *bp, *bp1;
6124 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6126 _G.inLine += (!options.asmpeep);
6128 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6129 strcpy(buffer,IC_INLINE(ic));
6131 /* emit each line as a code */
6137 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6145 /* print label, use this special format with NULL directive
6146 * to denote that the argument should not be indented with tab */
6147 addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6154 if ((bp1 != bp) && *bp1)
6155 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6159 _G.inLine -= (!options.asmpeep);
6162 /*-----------------------------------------------------------------*/
6163 /* genRRC - rotate right with carry */
6164 /*-----------------------------------------------------------------*/
6165 static void genRRC (iCode *ic)
6167 operand *left , *result ;
6168 int size, offset = 0, same;
6171 /* rotate right with carry */
6173 result=IC_RESULT(ic);
6174 aopOp (left,ic,FALSE);
6175 aopOp (result,ic,FALSE);
6177 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6179 same = pic14_sameRegs(AOP(result),AOP(left));
6181 size = AOP_SIZE(result);
6183 /* get the lsb and put it into the carry */
6184 emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6191 emitpcode(POC_RRF, popGet(AOP(left),offset));
6193 emitpcode(POC_RRFW, popGet(AOP(left),offset));
6194 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6200 freeAsmop(left,NULL,ic,TRUE);
6201 freeAsmop(result,NULL,ic,TRUE);
6204 /*-----------------------------------------------------------------*/
6205 /* genRLC - generate code for rotate left with carry */
6206 /*-----------------------------------------------------------------*/
6207 static void genRLC (iCode *ic)
6209 operand *left , *result ;
6210 int size, offset = 0;
6214 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6215 /* rotate right with carry */
6217 result=IC_RESULT(ic);
6218 aopOp (left,ic,FALSE);
6219 aopOp (result,ic,FALSE);
6221 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6223 same = pic14_sameRegs(AOP(result),AOP(left));
6225 /* move it to the result */
6226 size = AOP_SIZE(result);
6228 /* get the msb and put it into the carry */
6229 emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6236 emitpcode(POC_RLF, popGet(AOP(left),offset));
6238 emitpcode(POC_RLFW, popGet(AOP(left),offset));
6239 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6246 freeAsmop(left,NULL,ic,TRUE);
6247 freeAsmop(result,NULL,ic,TRUE);
6250 /*-----------------------------------------------------------------*/
6251 /* genGetHbit - generates code get highest order bit */
6252 /*-----------------------------------------------------------------*/
6253 static void genGetHbit (iCode *ic)
6255 operand *left, *result;
6257 result=IC_RESULT(ic);
6258 aopOp (left,ic,FALSE);
6259 aopOp (result,ic,FALSE);
6262 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6263 /* get the highest order byte into a */
6264 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6265 if(AOP_TYPE(result) == AOP_CRY){
6266 pic14_emitcode("rlc","a");
6267 pic14_outBitC(result);
6270 pic14_emitcode("rl","a");
6271 pic14_emitcode("anl","a,#0x01");
6272 pic14_outAcc(result);
6276 freeAsmop(left,NULL,ic,TRUE);
6277 freeAsmop(result,NULL,ic,TRUE);
6280 /*-----------------------------------------------------------------*/
6281 /* AccRol - rotate left accumulator by known count */
6282 /*-----------------------------------------------------------------*/
6283 static void AccRol (operand *op,int offset,int shCount)
6286 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6287 shCount &= 0x0007; // shCount : 0..7
6292 pic14_emitcode("rl","a");
6293 emitpcode(POC_RLF,popGet(AOP(op),offset));
6296 pic14_emitcode("rl","a");
6297 pic14_emitcode("rl","a");
6298 emitpcode(POC_RLF,popGet(AOP(op),offset));
6299 emitpcode(POC_RLF,popGet(AOP(op),offset));
6302 pic14_emitcode("swap","a");
6303 pic14_emitcode("rr","a");
6304 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6305 emitpcode(POC_RRF,popGet(AOP(op),offset));
6308 pic14_emitcode("swap","a");
6309 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6312 pic14_emitcode("swap","a");
6313 pic14_emitcode("rl","a");
6314 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6315 emitpcode(POC_RLF,popGet(AOP(op),offset));
6318 pic14_emitcode("rr","a");
6319 pic14_emitcode("rr","a");
6320 emitpcode(POC_RRF,popGet(AOP(op),offset));
6321 emitpcode(POC_RRF,popGet(AOP(op),offset));
6324 pic14_emitcode("rr","a");
6325 emitpcode(POC_RRF,popGet(AOP(op),offset));
6330 /*-----------------------------------------------------------------*/
6331 /* AccLsh - left shift accumulator by known count */
6332 /*-----------------------------------------------------------------*/
6333 static void AccLsh (operand *op,int offset,int shCount)
6336 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6341 emitpcode (POC_RLF, popGet (AOP(op), 0));
6343 /* rotate left accumulator */
6344 AccRol(op,offset,shCount);
6345 /* and kill the lower order bits */
6346 emitpcode(POC_MOVLW,popGetLit(SLMask[shCount]));
6347 emitpcode (POC_ANDWF, popGet (AOP(op),0));
6352 /*-----------------------------------------------------------------*/
6353 /* AccRsh - right shift accumulator by known count */
6354 /*-----------------------------------------------------------------*/
6355 static void AccRsh (operand *op,int offset,int shCount)
6358 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6362 emitpcode (POC_RRF, popGet (AOP(op), 0));
6364 /* rotate right accumulator */
6365 AccRol(op,offset,8 - shCount);
6366 /* and kill the higher order bits */
6367 emitpcode (POC_MOVLW, popGetLit (SRMask[shCount]));
6368 emitpcode (POC_ANDWF, popGet (AOP(op),0));
6374 /*-----------------------------------------------------------------*/
6375 /* AccSRsh - signed right shift accumulator by known count */
6376 /*-----------------------------------------------------------------*/
6377 static void AccSRsh (int shCount)
6380 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6383 pic14_emitcode("mov","c,acc.7");
6384 pic14_emitcode("rrc","a");
6385 } else if(shCount == 2){
6386 pic14_emitcode("mov","c,acc.7");
6387 pic14_emitcode("rrc","a");
6388 pic14_emitcode("mov","c,acc.7");
6389 pic14_emitcode("rrc","a");
6391 tlbl = newiTempLabel(NULL);
6392 /* rotate right accumulator */
6393 AccRol(8 - shCount);
6394 /* and kill the higher order bits */
6395 pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6396 pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6397 pic14_emitcode("orl","a,#0x%02x",
6398 (unsigned char)~SRMask[shCount]);
6399 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6404 /*-----------------------------------------------------------------*/
6405 /* shiftR1Left2Result - shift right one byte from left to result */
6406 /*-----------------------------------------------------------------*/
6407 static void shiftR1Left2ResultSigned (operand *left, int offl,
6408 operand *result, int offr,
6414 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6416 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6420 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6422 emitpcode(POC_RRF, popGet(AOP(result),offr));
6424 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6425 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6431 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6433 emitpcode(POC_RRF, popGet(AOP(result),offr));
6435 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6436 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6438 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6439 emitpcode(POC_RRF, popGet(AOP(result),offr));
6445 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6447 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6448 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6451 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6452 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6453 emitpcode(POC_ANDLW, popGetLit(0x1f));
6455 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6456 emitpcode(POC_IORLW, popGetLit(0xe0));
6458 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6462 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6463 emitpcode(POC_ANDLW, popGetLit(0x0f));
6464 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6465 emitpcode(POC_IORLW, popGetLit(0xf0));
6466 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6470 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6472 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6473 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6475 emitpcode(POC_RRFW, popGet(AOP(result),offr));
6476 emitpcode(POC_ANDLW, popGetLit(0x07));
6477 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6478 emitpcode(POC_IORLW, popGetLit(0xf8));
6479 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6484 emitpcode(POC_MOVLW, popGetLit(0x00));
6485 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6486 emitpcode(POC_MOVLW, popGetLit(0xfe));
6487 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6488 emitpcode(POC_IORLW, popGetLit(0x01));
6489 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6491 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6492 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6493 emitpcode(POC_DECF, popGet(AOP(result),offr));
6494 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6495 emitpcode(POC_BCF, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6501 emitpcode(POC_MOVLW, popGetLit(0x00));
6502 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6503 emitpcode(POC_MOVLW, popGetLit(0xff));
6504 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6506 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6507 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6508 emitpcode(POC_DECF, popGet(AOP(result),offr));
6516 /*-----------------------------------------------------------------*/
6517 /* shiftR1Left2Result - shift right one byte from left to result */
6518 /*-----------------------------------------------------------------*/
6519 static void shiftR1Left2Result (operand *left, int offl,
6520 operand *result, int offr,
6521 int shCount, int sign)
6526 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6528 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6530 /* Copy the msb into the carry if signed. */
6532 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6542 emitpcode(POC_RRF, popGet(AOP(result),offr));
6544 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6545 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6551 emitpcode(POC_RRF, popGet(AOP(result),offr));
6553 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6554 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6557 emitpcode(POC_RRF, popGet(AOP(result),offr));
6562 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6564 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6565 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6568 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6569 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6570 emitpcode(POC_ANDLW, popGetLit(0x1f));
6571 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6575 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6576 emitpcode(POC_ANDLW, popGetLit(0x0f));
6577 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6581 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6582 emitpcode(POC_ANDLW, popGetLit(0x0f));
6583 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6585 emitpcode(POC_RRF, popGet(AOP(result),offr));
6590 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6591 emitpcode(POC_ANDLW, popGetLit(0x80));
6592 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6593 emitpcode(POC_RLF, popGet(AOP(result),offr));
6594 emitpcode(POC_RLF, popGet(AOP(result),offr));
6599 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6600 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6601 emitpcode(POC_RLF, popGet(AOP(result),offr));
6610 /*-----------------------------------------------------------------*/
6611 /* shiftL1Left2Result - shift left one byte from left to result */
6612 /*-----------------------------------------------------------------*/
6613 static void shiftL1Left2Result (operand *left, int offl,
6614 operand *result, int offr, int shCount)
6620 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6622 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6623 DEBUGpic14_emitcode ("; ***","same = %d",same);
6624 // l = aopGet(AOP(left),offl,FALSE,FALSE);
6626 /* shift left accumulator */
6627 //AccLsh(shCount); // don't comment out just yet...
6628 // aopPut(AOP(result),"a",offr);
6632 /* Shift left 1 bit position */
6633 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6635 emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6637 emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6638 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6642 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6643 emitpcode(POC_ANDLW,popGetLit(0x7e));
6644 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6645 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6648 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6649 emitpcode(POC_ANDLW,popGetLit(0x3e));
6650 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6651 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6652 emitpcode(POC_RLF, popGet(AOP(result),offr));
6655 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6656 emitpcode(POC_ANDLW, popGetLit(0xf0));
6657 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6660 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6661 emitpcode(POC_ANDLW, popGetLit(0xf0));
6662 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6663 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6666 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6667 emitpcode(POC_ANDLW, popGetLit(0x30));
6668 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6669 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6670 emitpcode(POC_RLF, popGet(AOP(result),offr));
6673 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6674 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6675 emitpcode(POC_RRF, popGet(AOP(result),offr));
6679 DEBUGpic14_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6685 /*-----------------------------------------------------------------*/
6686 /* movLeft2Result - move byte from left to result */
6687 /*-----------------------------------------------------------------*/
6688 static void movLeft2Result (operand *left, int offl,
6689 operand *result, int offr)
6693 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6694 if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6695 l = aopGet(AOP(left),offl,FALSE,FALSE);
6697 if (*l == '@' && (IS_AOP_PREG(result))) {
6698 pic14_emitcode("mov","a,%s",l);
6699 aopPut(AOP(result),"a",offr);
6701 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6702 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6707 /*-----------------------------------------------------------------*/
6708 /* shiftLeft_Left2ResultLit - shift left by known count */
6709 /*-----------------------------------------------------------------*/
6711 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6713 int size, same, offr, i;
6715 size = AOP_SIZE(left);
6716 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6718 same = pic14_sameRegs (AOP(left), AOP(result));
6721 shCount = shCount & 0x07;
6727 case 0: /* takes 0 or 2N cycles (for offr==0) */
6728 if (!same || offr) {
6729 for (i=size-1; i >= 0; i--)
6730 movLeft2Result (left, i, result, offr + i);
6734 case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6736 shiftLeft_Left2ResultLit (left, result, 8 * offr);
6737 shiftLeft_Left2ResultLit (result, result, shCount);
6738 return; /* prevent clearing result again */
6741 for (i=0; i < size; i++) {
6742 if (same && !offr) {
6743 emitpcode (POC_RLF, popGet (AOP(left), i));
6745 emitpcode (POC_RLFW, popGet (AOP(left), i));
6746 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6752 case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
6753 /* works in-place/with offr as well */
6754 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
6755 emitpcode (POC_ANDLW, popGetLit (0xF0));
6756 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
6758 for (i = size - 2; i >= 0; i--)
6760 emitpcode (POC_SWAPFW, popGet (AOP(left), i));
6761 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6762 emitpcode (POC_ANDLW, popGetLit (0x0F));
6763 emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
6764 emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
6768 case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
6769 /* works in-place/with offr as well */
6770 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
6771 for (i = size-2; i >= 0; i--) {
6772 emitpcode (POC_RRFW, popGet (AOP(left), i));
6773 emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
6775 emitpcode (POC_CLRF, popGet (AOP(result), offr));
6776 emitpcode (POC_RRF, popGet (AOP(result), offr));
6780 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
6781 shiftLeft_Left2ResultLit (result, result, 1);
6782 return; /* prevent clearing result again */
6788 emitpcode (POC_CLRF, popGet (AOP(result), offr));
6792 /*-----------------------------------------------------------------*/
6793 /* shiftRight_Left2ResultLit - shift right by known count */
6794 /*-----------------------------------------------------------------*/
6796 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
6798 int size, same, offr, i;
6800 size = AOP_SIZE(left);
6801 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6803 same = pic14_sameRegs (AOP(left), AOP(result));
6806 shCount = shCount & 0x07;
6814 case 0: /* takes 0 or 2N cycles (for offr==0) */
6815 if (!same || offr) {
6816 for (i=0; i < size; i++)
6817 movLeft2Result (left, i + offr, result, i);
6821 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
6822 emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
6824 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
6825 shiftRight_Left2ResultLit (result, result, shCount, sign);
6826 return; /* prevent sign-extending result again */
6830 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
6833 for (i = size-1; i >= 0; i--) {
6834 if (same && !offr) {
6835 emitpcode (POC_RRF, popGet (AOP(left), i));
6837 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
6838 emitpcode (POC_MOVWF, popGet (AOP(result), i));
6844 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
6845 /* works in-place/with offr as well */
6846 emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
6847 emitpcode (POC_ANDLW, popGetLit (0x0F));
6848 emitpcode (POC_MOVWF, popGet(AOP(result), 0));
6850 for (i = 1; i < size; i++)
6852 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
6853 emitpcode (POC_MOVWF, popGet (AOP(result), i));
6854 emitpcode (POC_ANDLW, popGetLit (0xF0));
6855 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
6856 emitpcode (POC_XORWF, popGet (AOP(result), i));
6861 emitpcode (POC_MOVLW, popGetLit (0xF0));
6862 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
6863 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
6867 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
6868 /* works in-place/with offr as well */
6869 emitpcode (POC_RLFW, popGet (AOP(left), offr));
6870 for (i = 0; i < size-1; i++) {
6871 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
6872 emitpcode (POC_MOVWF, popGet (AOP(result), i));
6874 emitpcode (POC_CLRF, popGet (AOP(result), size-1));
6876 emitpcode (POC_RLF, popGet (AOP(result), size-1));
6879 emitpcode (POC_DECF, popGet (AOP(result), size-1));
6884 shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
6885 shiftRight_Left2ResultLit (result, result, 1, sign);
6886 return; /* prevent sign extending result again */
6891 addSign (result, size, sign);
6895 /*-----------------------------------------------------------------*/
6896 /* shiftL2Left2Result - shift left two bytes from left to result */
6897 /*-----------------------------------------------------------------*/
6898 static void shiftL2Left2Result (operand *left, int offl,
6899 operand *result, int offr, int shCount)
6903 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6905 if(pic14_sameRegs(AOP(result), AOP(left))) {
6913 emitpcode(POC_MOVFW,popGet(AOP(result),offr));
6914 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6915 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6919 emitpcode(POC_RLF, popGet(AOP(result),offr));
6920 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6926 emitpcode(POC_MOVLW, popGetLit(0x0f));
6927 emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
6928 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6929 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6930 emitpcode(POC_ANDFW, popGet(AOP(result),offr));
6931 emitpcode(POC_XORWF, popGet(AOP(result),offr));
6932 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6934 emitpcode(POC_RLF, popGet(AOP(result),offr));
6935 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6939 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6940 emitpcode(POC_RRF, popGet(AOP(result),offr));
6941 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6942 emitpcode(POC_RRF, popGet(AOP(result),offr));
6943 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6944 emitpcode(POC_ANDLW,popGetLit(0xc0));
6945 emitpcode(POC_XORFW,popGet(AOP(result),offr));
6946 emitpcode(POC_XORWF,popGet(AOP(result),offr));
6947 emitpcode(POC_XORFW,popGet(AOP(result),offr));
6948 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6951 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6952 emitpcode(POC_RRFW, popGet(AOP(result),offr));
6953 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6954 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6955 emitpcode(POC_RRF, popGet(AOP(result),offr));
6965 /* note, use a mov/add for the shift since the mov has a
6966 chance of getting optimized out */
6967 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6968 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6969 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6970 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6971 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6975 emitpcode(POC_RLF, popGet(AOP(result),offr));
6976 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6982 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6983 emitpcode(POC_ANDLW, popGetLit(0xF0));
6984 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6985 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6986 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6987 emitpcode(POC_ANDLW, popGetLit(0xF0));
6988 emitpcode(POC_XORWF, popGet(AOP(result),offr));
6989 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6993 emitpcode(POC_RLF, popGet(AOP(result),offr));
6994 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6998 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6999 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7000 emitpcode(POC_RRFW, popGet(AOP(result),offl));
7001 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7003 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7004 emitpcode(POC_RRF, popGet(AOP(result),offr));
7005 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7006 emitpcode(POC_ANDLW,popGetLit(0xc0));
7007 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7008 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7009 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7010 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7013 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7014 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7015 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7016 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7017 emitpcode(POC_RRF, popGet(AOP(result),offr));
7023 /*-----------------------------------------------------------------*/
7024 /* shiftR2Left2Result - shift right two bytes from left to result */
7025 /*-----------------------------------------------------------------*/
7026 static void shiftR2Left2Result (operand *left, int offl,
7027 operand *result, int offr,
7028 int shCount, int sign)
7033 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7034 same = pic14_sameRegs(AOP(result), AOP(left));
7036 if(same && ((offl + MSB16) == offr)){
7038 /* don't crash result[offr] */
7039 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7040 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7043 movLeft2Result(left,offl, result, offr);
7044 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7047 /* a:x >> shCount (x = lsb(result))*/
7050 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7052 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7061 emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7066 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7067 emitpcode(POC_RRF,popGet(AOP(result),offr));
7069 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7070 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7071 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7072 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7077 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7080 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7081 emitpcode(POC_RRF,popGet(AOP(result),offr));
7088 emitpcode(POC_MOVLW, popGetLit(0xf0));
7089 emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7090 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7092 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7093 emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7094 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7095 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7097 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7098 emitpcode(POC_ANDLW, popGetLit(0x0f));
7099 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7101 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7102 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7103 emitpcode(POC_ANDLW, popGetLit(0xf0));
7104 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7105 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7109 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7110 emitpcode(POC_RRF, popGet(AOP(result),offr));
7114 emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7115 emitpcode(POC_BTFSC,
7116 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7117 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7125 emitpcode(POC_RLF, popGet(AOP(result),offr));
7126 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7128 emitpcode(POC_RLF, popGet(AOP(result),offr));
7129 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7130 emitpcode(POC_RLFW, popGet(AOP(result),offr));
7131 emitpcode(POC_ANDLW,popGetLit(0x03));
7133 emitpcode(POC_BTFSC,
7134 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7135 emitpcode(POC_IORLW,popGetLit(0xfc));
7137 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7138 emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7139 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7140 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7142 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7143 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7144 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7145 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7146 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7147 emitpcode(POC_RLF, popGet(AOP(result),offr));
7148 emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7149 emitpcode(POC_ANDLW,popGetLit(0x03));
7151 emitpcode(POC_BTFSC,
7152 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7153 emitpcode(POC_IORLW,popGetLit(0xfc));
7155 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7156 //emitpcode(POC_RLF, popGet(AOP(result),offr));
7163 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7164 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7165 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7166 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7169 emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7171 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7175 /*-----------------------------------------------------------------*/
7176 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7177 /*-----------------------------------------------------------------*/
7178 static void shiftLLeftOrResult (operand *left, int offl,
7179 operand *result, int offr, int shCount)
7182 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7184 /* shift left accumulator */
7185 AccLsh(left,offl,shCount);
7186 /* or with result */
7187 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7188 assert ( !"broken (modifies left, fails for left==result))" );
7191 /*-----------------------------------------------------------------*/
7192 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7193 /*-----------------------------------------------------------------*/
7194 static void shiftRLeftOrResult (operand *left, int offl,
7195 operand *result, int offr, int shCount)
7198 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7200 /* shift right accumulator */
7201 AccRsh(left,offl,shCount);
7202 /* or with result */
7203 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7204 assert ( !"broken (modifies left, fails for left==result))" );
7207 /*-----------------------------------------------------------------*/
7208 /* genlshOne - left shift a one byte quantity by known count */
7209 /*-----------------------------------------------------------------*/
7210 static void genlshOne (operand *result, operand *left, int shCount)
7213 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7214 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7217 /*-----------------------------------------------------------------*/
7218 /* genlshTwo - left shift two bytes by known amount != 0 */
7219 /*-----------------------------------------------------------------*/
7220 static void genlshTwo (operand *result,operand *left, int shCount)
7225 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7226 size = pic14_getDataSize(result);
7228 /* if shCount >= 8 */
7234 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7236 movLeft2Result(left, LSB, result, MSB16);
7238 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7241 /* 1 <= shCount <= 7 */
7244 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7246 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7250 /*-----------------------------------------------------------------*/
7251 /* shiftLLong - shift left one long from left to result */
7252 /* offl = LSB or MSB16 */
7253 /*-----------------------------------------------------------------*/
7254 static void shiftLLong (operand *left, operand *result, int offr )
7257 int size = AOP_SIZE(result);
7260 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7261 if(size >= LSB+offr){
7262 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7264 pic14_emitcode("add","a,acc");
7265 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7266 size >= MSB16+offr && offr != LSB )
7267 pic14_emitcode("xch","a,%s",
7268 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7270 aopPut(AOP(result),"a",LSB+offr);
7273 if(size >= MSB16+offr){
7274 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7275 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7278 pic14_emitcode("rlc","a");
7279 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7280 size >= MSB24+offr && offr != LSB)
7281 pic14_emitcode("xch","a,%s",
7282 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7284 aopPut(AOP(result),"a",MSB16+offr);
7287 if(size >= MSB24+offr){
7288 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7289 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7292 pic14_emitcode("rlc","a");
7293 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7294 size >= MSB32+offr && offr != LSB )
7295 pic14_emitcode("xch","a,%s",
7296 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7298 aopPut(AOP(result),"a",MSB24+offr);
7301 if(size > MSB32+offr){
7302 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7303 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7306 pic14_emitcode("rlc","a");
7307 aopPut(AOP(result),"a",MSB32+offr);
7310 aopPut(AOP(result),zero,LSB);
7313 /*-----------------------------------------------------------------*/
7314 /* genlshFour - shift four byte by a known amount != 0 */
7315 /*-----------------------------------------------------------------*/
7316 static void genlshFour (operand *result, operand *left, int shCount)
7321 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7322 size = AOP_SIZE(result);
7324 /* if shifting more that 3 bytes */
7325 if (shCount >= 24 ) {
7328 /* lowest order of left goes to the highest
7329 order of the destination */
7330 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7332 movLeft2Result(left, LSB, result, MSB32);
7333 aopPut(AOP(result),zero,LSB);
7334 aopPut(AOP(result),zero,MSB16);
7335 aopPut(AOP(result),zero,MSB32);
7339 /* more than two bytes */
7340 else if ( shCount >= 16 ) {
7341 /* lower order two bytes goes to higher order two bytes */
7343 /* if some more remaining */
7345 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7347 movLeft2Result(left, MSB16, result, MSB32);
7348 movLeft2Result(left, LSB, result, MSB24);
7350 aopPut(AOP(result),zero,MSB16);
7351 aopPut(AOP(result),zero,LSB);
7355 /* if more than 1 byte */
7356 else if ( shCount >= 8 ) {
7357 /* lower order three bytes goes to higher order three bytes */
7361 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7363 movLeft2Result(left, LSB, result, MSB16);
7365 else{ /* size = 4 */
7367 movLeft2Result(left, MSB24, result, MSB32);
7368 movLeft2Result(left, MSB16, result, MSB24);
7369 movLeft2Result(left, LSB, result, MSB16);
7370 aopPut(AOP(result),zero,LSB);
7372 else if(shCount == 1)
7373 shiftLLong(left, result, MSB16);
7375 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7376 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7377 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7378 aopPut(AOP(result),zero,LSB);
7383 /* 1 <= shCount <= 7 */
7384 else if(shCount <= 2){
7385 shiftLLong(left, result, LSB);
7387 shiftLLong(result, result, LSB);
7389 /* 3 <= shCount <= 7, optimize */
7391 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7392 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7393 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7399 /*-----------------------------------------------------------------*/
7400 /* genLeftShiftLiteral - left shifting by known count */
7401 /*-----------------------------------------------------------------*/
7402 static void genLeftShiftLiteral (operand *left,
7407 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7411 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7412 freeAsmop(right,NULL,ic,TRUE);
7414 aopOp(left,ic,FALSE);
7415 aopOp(result,ic,FALSE);
7417 size = getSize(operandType(result));
7420 pic14_emitcode("; shift left ","result %d, left %d",size,
7424 /* I suppose that the left size >= result size */
7427 movLeft2Result(left, size, result, size);
7431 else if(shCount >= (size * 8))
7433 aopPut(AOP(result),zero,size);
7437 genlshOne (result,left,shCount);
7442 genlshTwo (result,left,shCount);
7446 genlshFour (result,left,shCount);
7450 freeAsmop(left,NULL,ic,TRUE);
7451 freeAsmop(result,NULL,ic,TRUE);
7455 /*-----------------------------------------------------------------*
7456 * genMultiAsm - repeat assembly instruction for size of register.
7457 * if endian == 1, then the high byte (i.e base address + size of
7458 * register) is used first else the low byte is used first;
7459 *-----------------------------------------------------------------*/
7460 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7466 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7479 emitpcode(poc, popGet(AOP(reg),offset));
7484 /*-----------------------------------------------------------------*/
7485 /* genLeftShift - generates code for left shifting */
7486 /*-----------------------------------------------------------------*/
7487 static void genLeftShift (iCode *ic)
7489 operand *left,*right, *result;
7491 unsigned long lit = 0L;
7493 symbol *tlbl , *tlbl1;
7497 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7499 right = IC_RIGHT(ic);
7501 result = IC_RESULT(ic);
7503 aopOp(right,ic,FALSE);
7504 aopOp(left,ic,FALSE);
7505 aopOp(result,ic,FALSE);
7508 /* if the shift count is known then do it
7509 as efficiently as possible */
7510 if (AOP_TYPE(right) == AOP_LIT) {
7511 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7515 /* shift count is unknown then we have to form
7516 a loop get the loop count in B : Note: we take
7517 only the lower order byte since shifting
7518 more that 32 bits make no sense anyway, ( the
7519 largest size of an object can be only 32 bits ) */
7522 /* now move the left to the result if they are not the
7524 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
7525 AOP_SIZE(result) > 1) {
7527 size = AOP_SIZE(result);
7530 l = aopGet(AOP(left),offset,FALSE,TRUE);
7531 if (*l == '@' && (IS_AOP_PREG(result))) {
7533 pic14_emitcode("mov","a,%s",l);
7534 aopPut(AOP(result),"a",offset);
7536 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
7537 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7538 //aopPut(AOP(result),l,offset);
7544 if(AOP_TYPE(left) == AOP_LIT)
7545 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7547 size = AOP_SIZE(result);
7549 /* if it is only one byte then */
7551 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7552 emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7553 emitpcode(POC_ANDLW, popGetLit(0xf0));
7554 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7555 emitpcode(POC_MOVFW, popGet(AOP(left),0));
7556 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7557 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7558 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7559 emitpcode(POC_RLFW, popGet(AOP(result),0));
7560 emitpcode(POC_ANDLW, popGetLit(0xfe));
7561 emitpcode(POC_ADDFW, popGet(AOP(result),0));
7562 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7563 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7566 tlbl = newiTempLabel(NULL);
7567 if (!pic14_sameRegs(AOP(left),AOP(result))) {
7568 if (AOP_TYPE(left) == AOP_LIT)
7569 emitpcode(POC_MOVLW, popGetLit(lit));
7571 emitpcode(POC_MOVFW, popGet(AOP(left),0));
7572 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7575 emitpcode(POC_COMFW, popGet(AOP(right),0));
7576 emitpcode(POC_RRF, popGet(AOP(result),0));
7577 emitpLabel(tlbl->key);
7578 emitpcode(POC_RLF, popGet(AOP(result),0));
7579 emitpcode(POC_ADDLW, popGetLit(1));
7581 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7586 if (pic14_sameRegs(AOP(left),AOP(result))) {
7588 tlbl = newiTempLabel(NULL);
7589 emitpcode(POC_COMFW, popGet(AOP(right),0));
7590 genMultiAsm(POC_RRF, result, size,1);
7591 emitpLabel(tlbl->key);
7592 genMultiAsm(POC_RLF, result, size,0);
7593 emitpcode(POC_ADDLW, popGetLit(1));
7595 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7599 //tlbl = newiTempLabel(NULL);
7601 //tlbl1 = newiTempLabel(NULL);
7603 //reAdjustPreg(AOP(result));
7605 //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7606 //pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7607 //l = aopGet(AOP(result),offset,FALSE,FALSE);
7609 //pic14_emitcode("add","a,acc");
7610 //aopPut(AOP(result),"a",offset++);
7612 // l = aopGet(AOP(result),offset,FALSE,FALSE);
7614 // pic14_emitcode("rlc","a");
7615 // aopPut(AOP(result),"a",offset++);
7617 //reAdjustPreg(AOP(result));
7619 //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7620 //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7623 tlbl = newiTempLabel(NULL);
7624 tlbl1= newiTempLabel(NULL);
7626 size = AOP_SIZE(result);
7629 pctemp = popGetTempReg(); /* grab a temporary working register. */
7631 emitpcode(POC_MOVFW, popGet(AOP(right),0));
7633 /* offset should be 0, 1 or 3 */
7634 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7636 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
7638 emitpcode(POC_MOVWF, pctemp);
7641 emitpLabel(tlbl->key);
7644 emitpcode(POC_RLF, popGet(AOP(result),0));
7646 emitpcode(POC_RLF, popGet(AOP(result),offset++));
7648 emitpcode(POC_DECFSZ, pctemp);
7649 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7650 emitpLabel(tlbl1->key);
7652 popReleaseTempReg(pctemp);
7656 freeAsmop (right,NULL,ic,TRUE);
7657 freeAsmop(left,NULL,ic,TRUE);
7658 freeAsmop(result,NULL,ic,TRUE);
7662 /*-----------------------------------------------------------------*/
7663 /* genrshOne - right shift a one byte quantity by known count */
7664 /*-----------------------------------------------------------------*/
7665 static void genrshOne (operand *result, operand *left,
7666 int shCount, int sign)
7669 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7670 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7673 /*-----------------------------------------------------------------*/
7674 /* genrshTwo - right shift two bytes by known amount != 0 */
7675 /*-----------------------------------------------------------------*/
7676 static void genrshTwo (operand *result,operand *left,
7677 int shCount, int sign)
7680 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7681 /* if shCount >= 8 */
7685 shiftR1Left2Result(left, MSB16, result, LSB,
7688 movLeft2Result(left, MSB16, result, LSB);
7690 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7693 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7694 emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7698 /* 1 <= shCount <= 7 */
7700 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
7703 /*-----------------------------------------------------------------*/
7704 /* shiftRLong - shift right one long from left to result */
7705 /* offl = LSB or MSB16 */
7706 /*-----------------------------------------------------------------*/
7707 static void shiftRLong (operand *left, int offl,
7708 operand *result, int sign)
7713 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7715 size = AOP_SIZE(left);
7716 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7719 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7723 assert (offl >= 0 && offl < size);
7725 same = pic14_sameRegs (AOP(left), AOP(result));
7727 /* perform the shift */
7730 if (same && !offl) {
7731 emitpcode (POC_RRF, popGet (AOP(result), size));
7733 emitpcode (POC_RRFW, popGet (AOP(left), size));
7734 emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7738 addSign (result, AOP_SIZE(left) - offl, sign);
7741 /*-----------------------------------------------------------------*/
7742 /* genrshFour - shift four byte by a known amount != 0 */
7743 /*-----------------------------------------------------------------*/
7744 static void genrshFour (operand *result, operand *left,
7745 int shCount, int sign)
7748 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7749 /* if shifting more that 3 bytes */
7750 if(shCount >= 24 ) {
7753 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7755 movLeft2Result(left, MSB32, result, LSB);
7757 addSign(result, MSB16, sign);
7759 else if(shCount >= 16){
7762 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7764 movLeft2Result(left, MSB24, result, LSB);
7765 movLeft2Result(left, MSB32, result, MSB16);
7767 addSign(result, MSB24, sign);
7769 else if(shCount >= 8){
7772 shiftRLong(left, MSB16, result, sign);
7773 else if(shCount == 0){
7774 movLeft2Result(left, MSB16, result, LSB);
7775 movLeft2Result(left, MSB24, result, MSB16);
7776 movLeft2Result(left, MSB32, result, MSB24);
7777 addSign(result, MSB32, sign);
7780 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7781 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7782 /* the last shift is signed */
7783 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7784 addSign(result, MSB32, sign);
7787 else{ /* 1 <= shCount <= 7 */
7789 shiftRLong(left, LSB, result, sign);
7791 shiftRLong(result, LSB, result, sign);
7794 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7795 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7796 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7801 /*-----------------------------------------------------------------*/
7802 /* genRightShiftLiteral - right shifting by known count */
7803 /*-----------------------------------------------------------------*/
7804 static void genRightShiftLiteral (operand *left,
7810 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7814 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7815 freeAsmop(right,NULL,ic,TRUE);
7817 aopOp(left,ic,FALSE);
7818 aopOp(result,ic,FALSE);
7821 pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7825 lsize = pic14_getDataSize(left);
7826 res_size = pic14_getDataSize(result);
7827 /* test the LEFT size !!! */
7829 /* I suppose that the left size >= result size */
7832 movLeft2Result(left, res_size, result, res_size);
7835 else if(shCount >= (lsize * 8)){
7838 emitpcode(POC_CLRF, popGet(AOP(result),LSB));
7840 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7841 emitpcode(POC_DECF, popGet(AOP(result),LSB));
7846 emitpcode(POC_MOVLW, popGetLit(0));
7847 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7848 emitpcode(POC_MOVLW, popGetLit(0xff));
7850 emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
7855 emitpcode(POC_CLRF, popGet(AOP(result),res_size));
7862 genrshOne (result,left,shCount,sign);
7866 genrshTwo (result,left,shCount,sign);
7870 genrshFour (result,left,shCount,sign);
7878 freeAsmop(left,NULL,ic,TRUE);
7879 freeAsmop(result,NULL,ic,TRUE);
7883 /*-----------------------------------------------------------------*/
7884 /* genSignedRightShift - right shift of signed number */
7885 /*-----------------------------------------------------------------*/
7886 static void genSignedRightShift (iCode *ic)
7888 operand *right, *left, *result;
7891 symbol *tlbl, *tlbl1 ;
7894 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7896 /* we do it the hard way put the shift count in b
7897 and loop thru preserving the sign */
7899 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7901 right = IC_RIGHT(ic);
7903 result = IC_RESULT(ic);
7905 aopOp(right,ic,FALSE);
7906 aopOp(left,ic,FALSE);
7907 aopOp(result,ic,FALSE);
7910 if ( AOP_TYPE(right) == AOP_LIT) {
7911 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
7912 //genRightShiftLiteral (left,right,result,ic,1);
7915 /* shift count is unknown then we have to form
7916 a loop get the loop count in B : Note: we take
7917 only the lower order byte since shifting
7918 more that 32 bits make no sense anyway, ( the
7919 largest size of an object can be only 32 bits ) */
7921 //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7922 //pic14_emitcode("inc","b");
7923 //freeAsmop (right,NULL,ic,TRUE);
7924 //aopOp(left,ic,FALSE);
7925 //aopOp(result,ic,FALSE);
7927 /* now move the left to the result if they are not the
7929 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
7930 AOP_SIZE(result) > 1) {
7932 size = AOP_SIZE(result);
7936 l = aopGet(AOP(left),offset,FALSE,TRUE);
7937 if (*l == '@' && IS_AOP_PREG(result)) {
7938 pic14_emitcode("mov","a,%s",l);
7939 aopPut(AOP(result),"a",offset);
7941 aopPut(AOP(result),l,offset);
7943 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
7944 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7950 /* mov the highest order bit to OVR */
7951 tlbl = newiTempLabel(NULL);
7952 tlbl1= newiTempLabel(NULL);
7954 size = AOP_SIZE(result);
7957 pctemp = popGetTempReg(); /* grab a temporary working register. */
7959 emitpcode(POC_MOVFW, popGet(AOP(right),0));
7961 /* offset should be 0, 1 or 3 */
7962 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7964 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
7966 emitpcode(POC_MOVWF, pctemp);
7969 emitpLabel(tlbl->key);
7971 emitpcode(POC_RLFW, popGet(AOP(result),offset));
7972 emitpcode(POC_RRF, popGet(AOP(result),offset));
7975 emitpcode(POC_RRF, popGet(AOP(result),--offset));
7978 emitpcode(POC_DECFSZ, pctemp);
7979 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7980 emitpLabel(tlbl1->key);
7982 popReleaseTempReg(pctemp);
7984 size = AOP_SIZE(result);
7986 pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
7987 pic14_emitcode("rlc","a");
7988 pic14_emitcode("mov","ov,c");
7989 /* if it is only one byte then */
7991 l = aopGet(AOP(left),0,FALSE,FALSE);
7993 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7994 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7995 pic14_emitcode("mov","c,ov");
7996 pic14_emitcode("rrc","a");
7997 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7998 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7999 aopPut(AOP(result),"a",0);
8003 reAdjustPreg(AOP(result));
8004 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8005 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8006 pic14_emitcode("mov","c,ov");
8008 l = aopGet(AOP(result),offset,FALSE,FALSE);
8010 pic14_emitcode("rrc","a");
8011 aopPut(AOP(result),"a",offset--);
8013 reAdjustPreg(AOP(result));
8014 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8015 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8020 freeAsmop(left,NULL,ic,TRUE);
8021 freeAsmop(result,NULL,ic,TRUE);
8022 freeAsmop(right,NULL,ic,TRUE);
8025 /*-----------------------------------------------------------------*/
8026 /* genRightShift - generate code for right shifting */
8027 /*-----------------------------------------------------------------*/
8028 static void genRightShift (iCode *ic)
8030 operand *right, *left, *result;
8034 symbol *tlbl, *tlbl1 ;
8037 /* if signed then we do it the hard way preserve the
8038 sign bit moving it inwards */
8039 retype = getSpec(operandType(IC_RESULT(ic)));
8040 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8042 if (!SPEC_USIGN(retype)) {
8043 genSignedRightShift (ic);
8047 /* signed & unsigned types are treated the same : i.e. the
8048 signed is NOT propagated inwards : quoting from the
8049 ANSI - standard : "for E1 >> E2, is equivalent to division
8050 by 2**E2 if unsigned or if it has a non-negative value,
8051 otherwise the result is implementation defined ", MY definition
8052 is that the sign does not get propagated */
8054 right = IC_RIGHT(ic);
8056 result = IC_RESULT(ic);
8058 aopOp(right,ic,FALSE);
8059 aopOp(left,ic,FALSE);
8060 aopOp(result,ic,FALSE);
8062 /* if the shift count is known then do it
8063 as efficiently as possible */
8064 if (AOP_TYPE(right) == AOP_LIT) {
8065 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 0);
8066 //genRightShiftLiteral (left,right,result,ic, 0);
8070 /* shift count is unknown then we have to form
8071 a loop get the loop count in B : Note: we take
8072 only the lower order byte since shifting
8073 more that 32 bits make no sense anyway, ( the
8074 largest size of an object can be only 32 bits ) */
8076 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8077 pic14_emitcode("inc","b");
8079 /* now move the left to the result if they are not the
8081 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
8082 AOP_SIZE(result) > 1) {
8084 size = AOP_SIZE(result);
8087 l = aopGet(AOP(left),offset,FALSE,TRUE);
8088 if (*l == '@' && IS_AOP_PREG(result)) {
8090 pic14_emitcode("mov","a,%s",l);
8091 aopPut(AOP(result),"a",offset);
8093 aopPut(AOP(result),l,offset);
8098 tlbl = newiTempLabel(NULL);
8099 tlbl1= newiTempLabel(NULL);
8100 size = AOP_SIZE(result);
8103 /* if it is only one byte then */
8106 tlbl = newiTempLabel(NULL);
8107 if (!pic14_sameRegs(AOP(left),AOP(result))) {
8108 emitpcode(POC_MOVFW, popGet(AOP(left),0));
8109 emitpcode(POC_MOVWF, popGet(AOP(result),0));
8112 emitpcode(POC_COMFW, popGet(AOP(right),0));
8113 emitpcode(POC_RLF, popGet(AOP(result),0));
8114 emitpLabel(tlbl->key);
8115 emitpcode(POC_RRF, popGet(AOP(result),0));
8116 emitpcode(POC_ADDLW, popGetLit(1));
8118 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8123 reAdjustPreg(AOP(result));
8124 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8125 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8128 l = aopGet(AOP(result),offset,FALSE,FALSE);
8130 pic14_emitcode("rrc","a");
8131 aopPut(AOP(result),"a",offset--);
8133 reAdjustPreg(AOP(result));
8135 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8136 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8139 freeAsmop(left,NULL,ic,TRUE);
8140 freeAsmop (right,NULL,ic,TRUE);
8141 freeAsmop(result,NULL,ic,TRUE);
8144 /*-----------------------------------------------------------------*/
8145 /* genUnpackBits - generates code for unpacking bits */
8146 /*-----------------------------------------------------------------*/
8147 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype, iCode *ifx)
8150 int offset = 0; /* result byte offset */
8151 int rsize; /* result size */
8152 int rlen = 0; /* remaining bitfield length */
8153 sym_link *etype; /* bitfield type information */
8154 int blen; /* bitfield length */
8155 int bstr; /* bitfield starting bit within byte */
8158 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8159 etype = getSpec(operandType(result));
8160 rsize = getSize (operandType (result));
8161 blen = SPEC_BLEN (etype);
8162 bstr = SPEC_BSTR (etype);
8164 /* single bit field case */
8166 if (ifx) { /* that is for an if statement */
8169 resolveIfx(&rIfx,ifx);
8170 if (ptype == -1) /* direct */
8171 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8173 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8174 emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8175 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8180 if (ptype == -1) /* direct */
8181 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8183 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8184 emitpcode(POC_BTFSC,pcop);
8185 emitpcode(POC_BSF,newpCodeOpBit(aopGet(AOP(result), 0,FALSE,FALSE),bstr,0));
8186 if (ptype == -1) /* direct */
8187 pcop = newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),bstr,0);
8189 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8190 emitpcode(POC_BTFSS,pcop);
8191 emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0));
8197 static int has_warned=0;
8200 fprintf (stderr, "%s: bitfields with more than 1 bit are probably broken...", __FUNCTION__);
8205 /* read the first byte */
8210 // pic14_emitcode("mov","a,@%s",rname);
8211 emitpcode(POC_MOVFW, popCopyReg(&pc_indf));
8215 pic14_emitcode("movx","a,@%s",rname);
8219 pic14_emitcode("movx","a,@dptr");
8223 pic14_emitcode("clr","a");
8224 pic14_emitcode("movc","a","@a+dptr");
8228 pic14_emitcode("lcall","__gptrget");
8232 /* if we have bitdisplacement then it fits */
8233 /* into this byte completely or if length is */
8234 /* less than a byte */
8235 if ((shCnt = SPEC_BSTR(etype)) || blen <= 8) {
8237 /* shift right acc */
8238 AccRsh(left,0,shCnt);
8240 pic14_emitcode("anl","a,#0x%02x",
8241 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
8242 aopPut(AOP(result),"a",offset);
8246 /* bit field did not fit in a byte */
8247 rlen = SPEC_BLEN(etype) - 8;
8248 aopPut(AOP(result),"a",offset++);
8255 pic14_emitcode("inc","%s",rname);
8256 pic14_emitcode("mov","a,@%s",rname);
8260 pic14_emitcode("inc","%s",rname);
8261 pic14_emitcode("movx","a,@%s",rname);
8265 pic14_emitcode("inc","dptr");
8266 pic14_emitcode("movx","a,@dptr");
8270 pic14_emitcode("clr","a");
8271 pic14_emitcode("inc","dptr");
8272 pic14_emitcode("movc","a","@a+dptr");
8276 pic14_emitcode("inc","dptr");
8277 pic14_emitcode("lcall","__gptrget");
8282 /* if we are done */
8286 aopPut(AOP(result),"a",offset++);
8291 pic14_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
8292 aopPut(AOP(result),"a",offset);
8299 /*-----------------------------------------------------------------*/
8300 /* genDataPointerGet - generates code when ptr offset is known */
8301 /*-----------------------------------------------------------------*/
8302 static void genDataPointerGet (operand *left,
8306 int size , offset = 0;
8309 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8312 /* optimization - most of the time, left and result are the same
8313 * address, but different types. for the pic code, we could omit
8316 aopOp(result,ic,TRUE);
8318 if (pic14_sameRegs (AOP(left), AOP(result)))
8321 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8323 //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8325 size = AOP_SIZE(result);
8326 if (size > AOP_SIZE(left)) size = AOP_SIZE(left);
8329 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8330 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8334 freeAsmop(left,NULL,ic,TRUE);
8335 freeAsmop(result,NULL,ic,TRUE);
8338 /*-----------------------------------------------------------------*/
8339 /* genNearPointerGet - pic14_emitcode for near pointer fetch */
8340 /*-----------------------------------------------------------------*/
8341 static void genNearPointerGet (operand *left,
8346 sym_link *ltype = operandType(left);
8347 sym_link *rtype = operandType(result);
8348 sym_link *retype= getSpec(rtype); /* bitfield type information */
8352 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8355 aopOp(left,ic,FALSE);
8357 /* if left is rematerialisable and
8358 result is not bit variable type and
8359 the left is pointer to data space i.e
8360 lower 128 bytes of space */
8361 if (AOP_TYPE(left) == AOP_PCODE && //AOP_TYPE(left) == AOP_IMMD &&
8362 !IS_BITVAR(retype) &&
8363 DCL_TYPE(ltype) == POINTER) {
8364 genDataPointerGet (left,result,ic);
8368 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8369 aopOp (result,ic,FALSE);
8371 /* Check if can access directly instead of via a pointer */
8372 if (PCOP(AOP(left))->type == PO_LITERAL && AOP_SIZE(result) == 1) {
8376 /* If the pointer value is not in a the FSR then need to put it in */
8377 if (!AOP_INPREG(AOP(left)) && !direct) {
8378 /* otherwise get a free pointer register */
8379 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8380 if (PCOP(AOP(result))->type == PO_LITERAL) /* XXX: check me */
8381 emitpcode(POC_MOVLW, popGet(AOP(left),0));
8383 emitpcode(POC_MOVFW, popGet(AOP(left),0));
8384 emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
8389 /* if bitfield then unpack the bits */
8390 if (IS_BITFIELD(retype))
8391 genUnpackBits (result,left,"indf",direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8393 /* we have can just get the values */
8394 int size = AOP_SIZE(result);
8397 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8401 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8403 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8404 if (AOP_TYPE(result) == AOP_LIT) {
8405 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8407 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8409 if (size && !direct)
8410 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8415 /* now some housekeeping stuff */
8417 /* we had to allocate for this iCode */
8418 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8419 freeAsmop(NULL,aop,ic,TRUE);
8421 /* we did not allocate which means left
8422 already in a pointer register, then
8423 if size > 0 && this could be used again
8424 we have to point it back to where it
8426 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8427 if (AOP_SIZE(result) > 1 &&
8428 !OP_SYMBOL(left)->remat &&
8429 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8431 int size = AOP_SIZE(result) - 1;
8433 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8438 freeAsmop(left,NULL,ic,TRUE);
8439 freeAsmop(result,NULL,ic,TRUE);
8443 /*-----------------------------------------------------------------*/
8444 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch */
8445 /*-----------------------------------------------------------------*/
8446 static void genPagedPointerGet (operand *left,
8453 sym_link *rtype, *retype;
8456 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8458 rtype = operandType(result);
8459 retype= getSpec(rtype);
8461 aopOp(left,ic,FALSE);
8463 /* if the value is already in a pointer register
8464 then don't need anything more */
8465 if (!AOP_INPREG(AOP(left))) {
8466 /* otherwise get a free pointer register */
8468 preg = getFreePtr(ic,&aop,FALSE);
8469 pic14_emitcode("mov","%s,%s",
8471 aopGet(AOP(left),0,FALSE,TRUE));
8472 rname = preg->name ;
8474 rname = aopGet(AOP(left),0,FALSE,FALSE);
8476 freeAsmop(left,NULL,ic,TRUE);
8477 aopOp (result,ic,FALSE);
8479 /* if bitfield then unpack the bits */
8480 if (IS_BITFIELD(retype))
8481 genUnpackBits (result,left,rname,PPOINTER,0);
8483 /* we have can just get the values */
8484 int size = AOP_SIZE(result);
8489 pic14_emitcode("movx","a,@%s",rname);
8490 aopPut(AOP(result),"a",offset);
8495 pic14_emitcode("inc","%s",rname);
8499 /* now some housekeeping stuff */
8501 /* we had to allocate for this iCode */
8502 freeAsmop(NULL,aop,ic,TRUE);
8504 /* we did not allocate which means left
8505 already in a pointer register, then
8506 if size > 0 && this could be used again
8507 we have to point it back to where it
8509 if (AOP_SIZE(result) > 1 &&
8510 !OP_SYMBOL(left)->remat &&
8511 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8513 int size = AOP_SIZE(result) - 1;
8515 pic14_emitcode("dec","%s",rname);
8520 freeAsmop(result,NULL,ic,TRUE);
8525 /*-----------------------------------------------------------------*/
8526 /* genFarPointerGet - gget value from far space */
8527 /*-----------------------------------------------------------------*/
8528 static void genFarPointerGet (operand *left,
8529 operand *result, iCode *ic)
8532 sym_link *retype = getSpec(operandType(result));
8535 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8537 aopOp(left,ic,FALSE);
8539 /* if the operand is already in dptr
8540 then we do nothing else we move the value to dptr */
8541 if (AOP_TYPE(left) != AOP_STR) {
8542 /* if this is remateriazable */
8543 if (AOP_TYPE(left) == AOP_IMMD)
8544 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8545 else { /* we need to get it byte by byte */
8546 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8547 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8548 if (options.model == MODEL_FLAT24)
8550 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8554 /* so dptr know contains the address */
8555 freeAsmop(left,NULL,ic,TRUE);
8556 aopOp(result,ic,FALSE);
8558 /* if bit then unpack */
8559 if (IS_BITFIELD(retype))
8560 genUnpackBits(result,left,"dptr",FPOINTER,0);
8562 size = AOP_SIZE(result);
8566 pic14_emitcode("movx","a,@dptr");
8567 aopPut(AOP(result),"a",offset++);
8569 pic14_emitcode("inc","dptr");
8573 freeAsmop(result,NULL,ic,TRUE);
8576 /*-----------------------------------------------------------------*/
8577 /* genCodePointerGet - get value from code space */
8578 /*-----------------------------------------------------------------*/
8579 static void genCodePointerGet (operand *left,
8580 operand *result, iCode *ic)
8583 sym_link *retype = getSpec(operandType(result));
8585 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8587 aopOp(left,ic,FALSE);
8589 /* if the operand is already in dptr
8590 then we do nothing else we move the value to dptr */
8591 if (AOP_TYPE(left) != AOP_STR) {
8592 /* if this is remateriazable */
8593 if (AOP_TYPE(left) == AOP_IMMD)
8594 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8595 else { /* we need to get it byte by byte */
8596 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8597 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8598 if (options.model == MODEL_FLAT24)
8600 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8604 /* so dptr know contains the address */
8605 freeAsmop(left,NULL,ic,TRUE);
8606 aopOp(result,ic,FALSE);
8608 /* if bit then unpack */
8609 if (IS_BITFIELD(retype))
8610 genUnpackBits(result,left,"dptr",CPOINTER,0);
8612 size = AOP_SIZE(result);
8616 pic14_emitcode("clr","a");
8617 pic14_emitcode("movc","a,@a+dptr");
8618 aopPut(AOP(result),"a",offset++);
8620 pic14_emitcode("inc","dptr");
8624 freeAsmop(result,NULL,ic,TRUE);
8627 /*-----------------------------------------------------------------*/
8628 /* genGenPointerGet - gget value from generic pointer space */
8629 /*-----------------------------------------------------------------*/
8630 static void genGenPointerGet (operand *left,
8631 operand *result, iCode *ic)
8634 sym_link *retype = getSpec(operandType(result));
8637 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8638 aopOp(left,ic,FALSE);
8639 aopOp(result,ic,FALSE);
8642 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8644 /* if the operand is already in dptr
8645 then we do nothing else we move the value to dptr */
8646 // if (AOP_TYPE(left) != AOP_STR) {
8647 /* if this is remateriazable */
8648 if (AOP_TYPE(left) == AOP_IMMD) {
8649 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8650 pic14_emitcode("mov","b,#%d",pointerCode(retype));
8652 else { /* we need to get it byte by byte */
8654 emitpcode(POC_MOVFW,popGet(AOP(left),0));
8655 emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8657 size = AOP_SIZE(result);
8661 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8662 emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
8664 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8669 /* so dptr know contains the address */
8671 /* if bit then unpack */
8672 //if (IS_BITFIELD(retype))
8673 // genUnpackBits(result,"dptr",GPOINTER);
8676 freeAsmop(left,NULL,ic,TRUE);
8677 freeAsmop(result,NULL,ic,TRUE);
8681 /*-----------------------------------------------------------------*/
8682 /* genConstPointerGet - get value from const generic pointer space */
8683 /*-----------------------------------------------------------------*/
8684 static void genConstPointerGet (operand *left,
8685 operand *result, iCode *ic)
8687 //sym_link *retype = getSpec(operandType(result));
8688 symbol *albl, *blbl;//, *clbl;
8694 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8695 aopOp(left,ic,FALSE);
8696 aopOp(result,ic,FALSE);
8698 size = AOP_SIZE(result);
8700 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8702 DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
8704 lit = aop_isLitLike (AOP(left));
8705 poc = lit ? POC_MOVLW : POC_MOVFW;
8709 for (i = 0; i < size; i++)
8711 albl = newiTempLabel(NULL);
8712 blbl = newiTempLabel(NULL);
8714 emitpcode(POC_CALL,popGetLabel(albl->key));
8715 pcop = popGetLabel(blbl->key);
8716 emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
8717 emitpcode(POC_GOTO,pcop);
8719 emitpLabel(albl->key);
8720 emitpcode(poc,popGetAddr(AOP(left),1,i));
8721 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
8722 emitpcode(poc,popGetAddr(AOP(left),0,i));
8723 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
8725 emitpLabel(blbl->key);
8726 emitpcode(POC_MOVWF,popGet(AOP(result),i));
8729 albl = newiTempLabel(NULL);
8730 blbl = newiTempLabel(NULL);
8731 //clbl = newiTempLabel(NULL);
8733 emitpcode (POC_GOTO, popGetLabel (blbl->key));
8735 emitpLabel(albl->key);
8736 emitpcode(poc,popGet(AOP(left),1));
8737 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
8738 emitpcode(poc,popGet(AOP(left),0));
8739 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
8741 emitpLabel(blbl->key);
8743 for (i = 0; i < size; i++)
8745 emitpcode(POC_CALL,popGetLabel(albl->key));
8746 /* the next two instructions (plus clbl) might be useless... */
8747 //pcop = popGetLabel(clbl->key);
8748 //emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
8749 //emitpcode(POC_GOTO,pcop);
8750 //emitpLabel(clbl->key);
8753 emitpcode (POC_INCF, popGet (AOP(left), 0));
8755 emitpcode (POC_INCF, popGet (AOP(left), 1));
8757 emitpcode(POC_MOVWF,popGet(AOP(result),i));
8760 /* restore left's value */
8761 emitpcode (POC_MOVLW, popGetLit (size-1));
8762 emitpcode (POC_SUBWF, popGet (AOP(left), 0));
8764 emitpcode (POC_DECF, popGet (AOP(left), 1));
8768 freeAsmop(left,NULL,ic,TRUE);
8769 freeAsmop(result,NULL,ic,TRUE);
8772 /*-----------------------------------------------------------------*/
8773 /* genPointerGet - generate code for pointer get */
8774 /*-----------------------------------------------------------------*/
8775 static void genPointerGet (iCode *ic)
8777 operand *left, *result ;
8778 sym_link *type, *etype;
8782 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8785 result = IC_RESULT(ic) ;
8787 /* depending on the type of pointer we need to
8788 move it to the correct pointer register */
8789 type = operandType(left);
8790 etype = getSpec(type);
8792 if (IS_PTR_CONST(type))
8793 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
8795 /* if left is of type of pointer then it is simple */
8796 if (IS_PTR(type) && !IS_FUNC(type->next))
8797 p_type = DCL_TYPE(type);
8799 /* we have to go by the storage class */
8800 p_type = PTR_TYPE(SPEC_OCLS(etype));
8802 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8804 if (SPEC_OCLS(etype)->codesp ) {
8805 DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
8806 //p_type = CPOINTER ;
8809 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
8810 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
8811 /*p_type = FPOINTER ;*/
8813 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
8814 DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
8815 /* p_type = PPOINTER; */
8817 if (SPEC_OCLS(etype) == idata )
8818 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
8819 /* p_type = IPOINTER; */
8821 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
8822 /* p_type = POINTER ; */
8825 /* now that we have the pointer type we assign
8826 the pointer values */
8831 genNearPointerGet (left,result,ic);
8835 genPagedPointerGet(left,result,ic);
8839 genFarPointerGet (left,result,ic);
8843 genConstPointerGet (left,result,ic);
8844 //pic14_emitcodePointerGet (left,result,ic);
8848 if (IS_CODEPTR(type) || IS_PTR_CONST(type) || SPEC_CONST(etype))
8849 genConstPointerGet (left,result,ic);
8851 genGenPointerGet (left,result,ic);
8854 assert ( !"unhandled pointer type" );
8860 /*-----------------------------------------------------------------*/
8861 /* emitPtrByteGet - for legacy 8051 emits code to get a byte into */
8862 /* A through a pointer register (R0, R1, or DPTR). The original */
8863 /* value of A can be preserved in B. */
8864 /* PIC has to use INDF register. */
8865 /*-----------------------------------------------------------------*/
8867 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
8875 pic14_emitcode ("mov", "b,a");
8876 // pic14_emitcode ("mov", "a,@%s", rname);
8877 emitpcode(POC_MOVFW, popCopyReg(&pc_indf));
8882 pic14_emitcode ("mov", "b,a");
8883 pic14_emitcode ("movx", "a,@%s", rname);
8888 pic14_emitcode ("mov", "b,a");
8889 pic14_emitcode ("movx", "a,@dptr");
8894 pic14_emitcode ("mov", "b,a");
8895 pic14_emitcode ("clr", "a");
8896 pic14_emitcode ("movc", "a,@a+dptr");
8902 pic14_emitcode ("push", "b");
8903 pic14_emitcode ("push", "acc");
8905 pic14_emitcode ("lcall", "__gptrget");
8907 pic14_emitcode ("pop", "b");
8912 /*-----------------------------------------------------------------*/
8913 /* emitPtrByteSet - emits code to set a byte from src through a */
8914 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR). */
8915 /*-----------------------------------------------------------------*/
8917 emitPtrByteSet (char *rname, int p_type, char *src)
8927 pic14_emitcode ("mov", "@%s,a", rname);
8930 // pic14_emitcode ("mov", "@%s,%s", rname, src);
8931 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8936 pic14_emitcode ("movx", "@%s,a", rname);
8941 pic14_emitcode ("movx", "@dptr,a");
8946 pic14_emitcode ("lcall", "__gptrput");
8951 /*-----------------------------------------------------------------*/
8952 /* genPackBits - generates code for packed bit storage */
8953 /*-----------------------------------------------------------------*/
8954 static void genPackBits(sym_link *etype,operand *result,operand *right,char *rname,int p_type)
8956 int offset = 0; /* source byte offset */
8957 int rlen = 0; /* remaining bitfield length */
8958 int blen; /* bitfield length */
8959 int bstr; /* bitfield starting bit within byte */
8960 int litval; /* source literal value (if AOP_LIT) */
8961 unsigned char mask; /* bitmask within current byte */
8964 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8966 blen = SPEC_BLEN (etype);
8967 bstr = SPEC_BSTR (etype);
8969 /* If the bitfield length is less than a byte */
8972 mask = ((unsigned char) (0xFF << (blen + bstr)) |
8973 (unsigned char) (0xFF >> (8 - bstr)));
8975 if (AOP_TYPE (right) == AOP_LIT)
8977 /* Case with a bitfield length <8 and literal source
8979 int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8983 if (AOP(result)->type == AOP_PCODE)
8984 pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
8986 pcop = popGet(AOP(result),0);
8987 emitpcode(lit?POC_BSF:POC_BCF,pcop);
8989 emitpcode(lit?POC_BSF:POC_BCF,popCopyReg(&pc_indf));
8993 litval = lit << bstr;
8994 litval &= (~mask) & 0xff;
8996 emitpcode(POC_MOVFW,popGet(AOP(result),0));
8998 emitPtrByteGet (rname, p_type, FALSE);
8999 if ((mask|litval)!=0xff)
9000 emitpcode(POC_ANDLW,popGetLit(mask));
9002 emitpcode(POC_IORLW,popGetLit(litval));
9009 /* 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 */
9010 emitpcode(POC_RLF,popGet(AOP(right),0));
9012 emitpcode(POC_BCF,popGet(AOP(result),0));
9014 emitpcode(POC_BSF,popGet(AOP(result),0));
9015 } else if (p_type!=GPOINTER) {
9016 /* Case with a bitfield length == 1 and no generic pointer
9018 if (AOP_TYPE (right) == AOP_CRY)
9019 pic14_emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9022 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
9023 pic14_emitcode ("rrc","a");
9025 emitPtrByteGet (rname, p_type, FALSE);
9026 pic14_emitcode ("mov","acc.%d,c",bstr);
9032 /* Case with a bitfield length < 8 and arbitrary source
9034 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
9035 /* shift and mask source value */
9036 AccLsh (right,0,bstr);
9037 pic14_emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9038 emitpcode(POC_ANDLW, popGetLit((~mask) & 0xff));
9040 //pushedB = pushB ();
9042 emitpcode(POC_MOVFW,popGet(AOP(result),0));
9044 emitPtrByteGet (rname, p_type, TRUE);
9046 pic14_emitcode ("anl", "a,#0x%02x", mask);
9047 pic14_emitcode ("orl", "a,b");
9048 emitpcode(POC_ANDLW,popGetLit(mask));
9049 emitpcode(POC_IORFW,popGet(AOP(right),0));
9050 if (p_type == GPOINTER)
9051 pic14_emitcode ("pop", "b");
9058 emitpcode(POC_MOVWF,popGet(AOP(result),0));
9060 emitPtrByteSet (rname, p_type, "a");
9064 /* Bit length is greater than 7 bits. In this case, copy */
9065 /* all except the partial byte at the end */
9066 for (rlen=blen;rlen>=8;rlen-=8)
9068 emitPtrByteSet (rname, p_type,
9069 aopGet (AOP (right), offset++, FALSE, TRUE) );
9071 pic14_emitcode ("inc", "%s", rname);
9074 /* If there was a partial byte at the end */
9077 mask = (((unsigned char) -1 << rlen) & 0xff);
9079 if (AOP_TYPE (right) == AOP_LIT)
9081 /* Case with partial byte and literal source
9083 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9084 litval >>= (blen-rlen);
9085 litval &= (~mask) & 0xff;
9086 emitPtrByteGet (rname, p_type, FALSE);
9087 if ((mask|litval)!=0xff)
9088 pic14_emitcode ("anl","a,#0x%02x", mask);
9090 pic14_emitcode ("orl","a,#0x%02x", litval);
9095 /* Case with partial byte and arbitrary source
9097 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
9098 pic14_emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9100 //pushedB = pushB ();
9101 /* transfer A to B and get next byte */
9102 emitPtrByteGet (rname, p_type, TRUE);
9104 pic14_emitcode ("anl", "a,#0x%02x", mask);
9105 pic14_emitcode ("orl", "a,b");
9106 if (p_type == GPOINTER)
9107 pic14_emitcode ("pop", "b");
9111 emitPtrByteSet (rname, p_type, "a");
9116 /*-----------------------------------------------------------------*/
9117 /* SetIrp - Set IRP bit */
9118 /*-----------------------------------------------------------------*/
9119 void SetIrp(operand *result) {
9121 if (AOP_TYPE(result) == AOP_LIT) {
9122 unsigned lit = (unsigned)operandLitValue(result);
9123 emitpcode((lit&0x100)?POC_BSF:POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
9125 if (PCOP(AOP(result))->type == PO_LITERAL) {
9126 int addrs = PCOL(AOP(result))->lit;
9127 emitpcode((addrs&0x100)?POC_BSF:POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
9129 emitpcode(POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT)); /* always ensure this is clear as it may have previouly been set */
9130 if(AOP_SIZE(result) > 1) {
9131 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
9132 emitpcode(POC_BSF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
9138 /*-----------------------------------------------------------------*/
9139 /* genDataPointerSet - remat pointer to data space */
9140 /*-----------------------------------------------------------------*/
9141 static void genDataPointerSet(operand *right,
9145 int size, offset = 0 ;
9148 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9149 aopOp(right,ic,FALSE);
9150 aopOp(result,ic,FALSE);
9152 size = AOP_SIZE(right);
9154 if ( AOP_TYPE(result) == AOP_PCODE) {
9155 fprintf(stderr,"genDataPointerSet %s, %d\n",
9156 AOP(result)->aopu.pcop->name,
9157 PCOI(AOP(result)->aopu.pcop)->offset);
9161 // tsd, was l+1 - the underline `_' prefix was being stripped
9163 emitpComment ("%s:%u: size=%i, offset=%i", __FILE__,__LINE__, size, offset);
9165 if (AOP_TYPE(right) == AOP_LIT) {
9166 unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9167 lit = lit >> (8*offset);
9169 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9170 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9172 emitpcode(POC_CLRF, popGet(AOP(result),offset));
9175 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9176 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9182 freeAsmop(right,NULL,ic,TRUE);
9183 freeAsmop(result,NULL,ic,TRUE);
9186 /*-----------------------------------------------------------------*/
9187 /* genNearPointerSet - pic14_emitcode for near pointer put */
9188 /*-----------------------------------------------------------------*/
9189 static void genNearPointerSet (operand *right,
9194 sym_link *ptype = operandType(result);
9195 sym_link *retype = getSpec(operandType(right));
9196 sym_link *letype = getSpec(ptype);
9201 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9202 aopOp(result,ic,FALSE);
9205 /* if the result is rematerializable &
9206 in data space & not a bit variable */
9207 //if (AOP_TYPE(result) == AOP_IMMD &&
9208 if (AOP_TYPE(result) == AOP_PCODE &&
9209 DCL_TYPE(ptype) == POINTER &&
9210 !IS_BITVAR (retype) &&
9211 !IS_BITVAR (letype)) {
9212 genDataPointerSet (right,result,ic);
9213 freeAsmop(result,NULL,ic,TRUE);
9217 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9218 aopOp(right,ic,FALSE);
9219 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9221 /* Check if can access directly instead of via a pointer */
9222 if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9226 /* If the pointer value is not in a the FSR then need to put it in */
9227 if (!AOP_INPREG(AOP(result)) && !direct) {
9228 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9229 if (PCOP(AOP(result))->type == PO_LITERAL)
9230 emitpcode(POC_MOVLW, popGet(AOP(result),0));
9232 emitpcode(POC_MOVFW, popGet(AOP(result),0));
9233 emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
9236 /* Must set/reset IRP bit for use with FSR. */
9237 /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9241 /* if bitfield then unpack the bits */
9242 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9243 genPackBits ((IS_BITFIELD (retype) ? retype : letype), result, right, "indf", direct?-1:POINTER);
9245 /* we have can just get the values */
9246 int size = AOP_SIZE(right);
9249 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9251 char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9253 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9255 if (AOP_TYPE(right) == AOP_LIT) {
9256 emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9258 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9261 emitpcode(POC_MOVWF,popGet(AOP(result),0));
9263 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9265 if (size && !direct)
9266 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9271 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9272 /* now some housekeeping stuff */
9274 /* we had to allocate for this iCode */
9275 freeAsmop(NULL,aop,ic,TRUE);
9277 /* we did not allocate which means left
9278 already in a pointer register, then
9279 if size > 0 && this could be used again
9280 we have to point it back to where it
9282 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9283 if (AOP_SIZE(right) > 1 &&
9284 !OP_SYMBOL(result)->remat &&
9285 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9287 int size = AOP_SIZE(right) - 1;
9289 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9293 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9296 freeAsmop(right,NULL,ic,TRUE);
9297 freeAsmop(result,NULL,ic,TRUE);
9300 /*-----------------------------------------------------------------*/
9301 /* genPagedPointerSet - pic14_emitcode for Paged pointer put */
9302 /*-----------------------------------------------------------------*/
9303 static void genPagedPointerSet (operand *right,
9313 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9315 retype= getSpec(operandType(right));
9317 aopOp(result,ic,FALSE);
9319 /* if the value is already in a pointer register
9320 then don't need anything more */
9321 if (!AOP_INPREG(AOP(result))) {
9322 /* otherwise get a free pointer register */
9324 preg = getFreePtr(ic,&aop,FALSE);
9325 pic14_emitcode("mov","%s,%s",
9327 aopGet(AOP(result),0,FALSE,TRUE));
9328 rname = preg->name ;
9330 rname = aopGet(AOP(result),0,FALSE,FALSE);
9332 freeAsmop(result,NULL,ic,TRUE);
9333 aopOp (right,ic,FALSE);
9335 /* if bitfield then unpack the bits */
9336 if (IS_BITFIELD(retype))
9337 genPackBits (retype,result,right,rname,PPOINTER);
9339 /* we have can just get the values */
9340 int size = AOP_SIZE(right);
9344 l = aopGet(AOP(right),offset,FALSE,TRUE);
9347 pic14_emitcode("movx","@%s,a",rname);
9350 pic14_emitcode("inc","%s",rname);
9356 /* now some housekeeping stuff */
9358 /* we had to allocate for this iCode */
9359 freeAsmop(NULL,aop,ic,TRUE);
9361 /* we did not allocate which means left
9362 already in a pointer register, then
9363 if size > 0 && this could be used again
9364 we have to point it back to where it
9366 if (AOP_SIZE(right) > 1 &&
9367 !OP_SYMBOL(result)->remat &&
9368 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9370 int size = AOP_SIZE(right) - 1;
9372 pic14_emitcode("dec","%s",rname);
9377 freeAsmop(right,NULL,ic,TRUE);
9382 /*-----------------------------------------------------------------*/
9383 /* genFarPointerSet - set value from far space */
9384 /*-----------------------------------------------------------------*/
9385 static void genFarPointerSet (operand *right,
9386 operand *result, iCode *ic)
9389 sym_link *retype = getSpec(operandType(right));
9392 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9393 aopOp(result,ic,FALSE);
9395 /* if the operand is already in dptr
9396 then we do nothing else we move the value to dptr */
9397 if (AOP_TYPE(result) != AOP_STR) {
9398 /* if this is remateriazable */
9399 if (AOP_TYPE(result) == AOP_IMMD)
9400 pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9401 else { /* we need to get it byte by byte */
9402 pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9403 pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9404 if (options.model == MODEL_FLAT24)
9406 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9410 /* so dptr know contains the address */
9411 freeAsmop(result,NULL,ic,TRUE);
9412 aopOp(right,ic,FALSE);
9414 /* if bit then unpack */
9415 if (IS_BITFIELD(retype))
9416 genPackBits(retype,result,right,"dptr",FPOINTER);
9418 size = AOP_SIZE(right);
9422 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9424 pic14_emitcode("movx","@dptr,a");
9426 pic14_emitcode("inc","dptr");
9430 freeAsmop(right,NULL,ic,TRUE);
9433 /*-----------------------------------------------------------------*/
9434 /* genGenPointerSet - set value from generic pointer space */
9435 /*-----------------------------------------------------------------*/
9436 static void genGenPointerSet (operand *right,
9437 operand *result, iCode *ic)
9439 sym_link *ptype = operandType(result);
9440 sym_link *retype = getSpec(operandType(right));
9441 sym_link *letype = getSpec (ptype);
9444 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9446 aopOp(result,ic,FALSE);
9447 aopOp(right,ic,FALSE);
9449 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9451 /* if the operand is already in dptr
9452 then we do nothing else we move the value to dptr */
9453 if (AOP_TYPE(result) != AOP_STR) {
9454 /* if this is remateriazable */
9455 if (AOP_TYPE(result) == AOP_IMMD) {
9456 pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9457 pic14_emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
9460 emitpcode(POC_MOVFW,popGet(AOP(result),0));
9461 emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
9463 /* Must set/reset IRP bit for use with FSR. */
9464 /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9469 /* if bitfield then unpack the bits */
9470 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9471 genPackBits ((IS_BITFIELD (retype) ? retype : letype),result, right, "indf", POINTER);
9473 /* we have can just get the values */
9474 int size = AOP_SIZE(right);
9477 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9479 char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9481 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9483 if (AOP_TYPE(right) == AOP_LIT) {
9484 emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9486 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9488 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9491 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9496 freeAsmop(right,NULL,ic,TRUE);
9497 freeAsmop(result,NULL,ic,TRUE);
9500 /*-----------------------------------------------------------------*/
9501 /* genPointerSet - stores the value into a pointer location */
9502 /*-----------------------------------------------------------------*/
9503 static void genPointerSet (iCode *ic)
9505 operand *right, *result ;
9506 sym_link *type, *etype;
9510 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9512 right = IC_RIGHT(ic);
9513 result = IC_RESULT(ic) ;
9515 /* depending on the type of pointer we need to
9516 move it to the correct pointer register */
9517 type = operandType(result);
9518 etype = getSpec(type);
9519 /* if left is of type of pointer then it is simple */
9520 if (IS_PTR(type) && !IS_FUNC(type->next)) {
9521 p_type = DCL_TYPE(type);
9524 /* we have to go by the storage class */
9525 p_type = PTR_TYPE(SPEC_OCLS(etype));
9527 /* if (SPEC_OCLS(etype)->codesp ) { */
9528 /* p_type = CPOINTER ; */
9531 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9532 /* p_type = FPOINTER ; */
9534 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9535 /* p_type = PPOINTER ; */
9537 /* if (SPEC_OCLS(etype) == idata ) */
9538 /* p_type = IPOINTER ; */
9540 /* p_type = POINTER ; */
9543 /* now that we have the pointer type we assign
9544 the pointer values */
9549 genNearPointerSet (right,result,ic);
9553 genPagedPointerSet (right,result,ic);
9557 genFarPointerSet (right,result,ic);
9561 genGenPointerSet (right,result,ic);
9565 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9566 "genPointerSet: illegal pointer type");
9570 /*-----------------------------------------------------------------*/
9571 /* genIfx - generate code for Ifx statement */
9572 /*-----------------------------------------------------------------*/
9573 static void genIfx (iCode *ic, iCode *popIc)
9575 operand *cond = IC_COND(ic);
9579 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9581 aopOp(cond,ic,FALSE);
9583 /* get the value into acc */
9584 if (AOP_TYPE(cond) != AOP_CRY)
9585 pic14_toBoolean(cond);
9588 /* the result is now in the accumulator */
9589 freeAsmop(cond,NULL,ic,TRUE);
9591 /* if there was something to be popped then do it */
9595 /* if the condition is a bit variable */
9596 if (isbit && IS_ITEMP(cond) &&
9598 genIfxJump(ic,SPIL_LOC(cond)->rname);
9599 DEBUGpic14_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9602 if (isbit && !IS_ITEMP(cond))
9603 genIfxJump(ic,OP_SYMBOL(cond)->rname);
9611 /*-----------------------------------------------------------------*/
9612 /* genAddrOf - generates code for address of */
9613 /*-----------------------------------------------------------------*/
9614 static void genAddrOf (iCode *ic)
9616 operand *right, *result, *left;
9620 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9623 //aopOp(IC_RESULT(ic),ic,FALSE);
9625 aopOp((left=IC_LEFT(ic)),ic,FALSE);
9626 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9627 aopOp((result=IC_RESULT(ic)),ic,TRUE);
9629 DEBUGpic14_AopType(__LINE__,left,right,result);
9630 assert (IS_SYMOP (left));
9632 /* sanity check: generic pointers to code space are not yet supported,
9633 * pionters to codespace must not be assigned addresses of __data values. */
9635 fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9636 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)));
9637 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)));
9638 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)));
9639 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)));
9642 if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9643 fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9644 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9645 OP_SYMBOL(left)->name);
9646 } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9647 fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9648 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9649 OP_SYMBOL(left)->name);
9652 size = AOP_SIZE(IC_RESULT(ic));
9656 /* fixing bug #863624, reported from (errolv) */
9657 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9658 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9661 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9662 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9667 freeAsmop(left,NULL,ic,FALSE);
9668 freeAsmop(result,NULL,ic,TRUE);
9673 /*-----------------------------------------------------------------*/
9674 /* genFarFarAssign - assignment when both are in far space */
9675 /*-----------------------------------------------------------------*/
9676 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9678 int size = AOP_SIZE(right);
9681 /* first push the right side on to the stack */
9683 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9685 pic14_emitcode ("push","acc");
9688 freeAsmop(right,NULL,ic,FALSE);
9689 /* now assign DPTR to result */
9690 aopOp(result,ic,FALSE);
9691 size = AOP_SIZE(result);
9693 pic14_emitcode ("pop","acc");
9694 aopPut(AOP(result),"a",--offset);
9696 freeAsmop(result,NULL,ic,FALSE);
9701 /*-----------------------------------------------------------------*/
9702 /* genAssign - generate code for assignment */
9703 /*-----------------------------------------------------------------*/
9704 static void genAssign (iCode *ic)
9706 operand *result, *right;
9707 int size, offset,know_W;
9708 unsigned long lit = 0L;
9710 result = IC_RESULT(ic);
9711 right = IC_RIGHT(ic) ;
9714 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9716 /* if they are the same */
9717 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9720 aopOp(right,ic,FALSE);
9721 aopOp(result,ic,TRUE);
9723 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9725 /* if they are the same registers */
9726 if (pic14_sameRegs(AOP(right),AOP(result)))
9729 /* special case: assign from __code */
9730 if (!IS_ITEMP(right) /* --> iTemps never reside in __code */
9731 && IS_SYMOP (right) /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
9732 && !IS_FUNC(OP_SYM_TYPE(right)) /* --> we would want its address instead of the first instruction */
9733 && !IS_CODEPTR(OP_SYM_TYPE(right)) /* --> get symbols address instread */
9734 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
9736 emitpComment ("genAssign from CODESPACE");
9737 genConstPointerGet (right, result, ic);
9741 /* just for symmetry reasons... */
9742 if (!IS_ITEMP(result)
9743 && IS_SYMOP (result)
9744 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
9746 assert ( !"cannot write to CODESPACE" );
9749 /* if the result is a bit */
9750 if (AOP_TYPE(result) == AOP_CRY) {
9752 /* if the right size is a literal then
9753 we know what the value is */
9754 if (AOP_TYPE(right) == AOP_LIT) {
9756 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9757 popGet(AOP(result),0));
9759 if (((int) operandLitValue(right)))
9760 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9761 AOP(result)->aopu.aop_dir,
9762 AOP(result)->aopu.aop_dir);
9764 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9765 AOP(result)->aopu.aop_dir,
9766 AOP(result)->aopu.aop_dir);
9770 /* the right is also a bit variable */
9771 if (AOP_TYPE(right) == AOP_CRY) {
9772 emitpcode(POC_BCF, popGet(AOP(result),0));
9773 emitpcode(POC_BTFSC, popGet(AOP(right),0));
9774 emitpcode(POC_BSF, popGet(AOP(result),0));
9776 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9777 AOP(result)->aopu.aop_dir,
9778 AOP(result)->aopu.aop_dir);
9779 pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
9780 AOP(right)->aopu.aop_dir,
9781 AOP(right)->aopu.aop_dir);
9782 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9783 AOP(result)->aopu.aop_dir,
9784 AOP(result)->aopu.aop_dir);
9789 emitpcode(POC_BCF, popGet(AOP(result),0));
9790 pic14_toBoolean(right);
9792 emitpcode(POC_BSF, popGet(AOP(result),0));
9793 //aopPut(AOP(result),"a",0);
9797 /* bit variables done */
9799 size = AOP_SIZE(result);
9801 if(AOP_TYPE(right) == AOP_LIT)
9802 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9804 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
9805 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9806 if(aopIdx(AOP(result),0) == 4) {
9807 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9808 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9809 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9812 DEBUGpic14_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
9817 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9818 if(AOP_TYPE(right) == AOP_LIT) {
9820 if(know_W != (int)(lit&0xff))
9821 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
9823 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9825 emitpcode(POC_CLRF, popGet(AOP(result),offset));
9829 } else if (AOP_TYPE(right) == AOP_CRY) {
9830 emitpcode(POC_CLRF, popGet(AOP(result),offset));
9832 emitpcode(POC_BTFSS, popGet(AOP(right),0));
9833 emitpcode(POC_INCF, popGet(AOP(result),0));
9836 mov2w (AOP(right), offset);
9837 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9845 freeAsmop (right,NULL,ic,FALSE);
9846 freeAsmop (result,NULL,ic,TRUE);
9849 /*-----------------------------------------------------------------*/
9850 /* genJumpTab - genrates code for jump table */
9851 /*-----------------------------------------------------------------*/
9852 static void genJumpTab (iCode *ic)
9858 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9860 aopOp(IC_JTCOND(ic),ic,FALSE);
9861 /* get the condition into accumulator */
9862 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9864 /* multiply by three */
9865 pic14_emitcode("add","a,acc");
9866 pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9868 jtab = newiTempLabel(NULL);
9869 pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9870 pic14_emitcode("jmp","@a+dptr");
9871 pic14_emitcode("","%05d_DS_:",jtab->key+100);
9873 emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
9874 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
9875 emitpcode(POC_MOVLW, popGetLabel(jtab->key));
9876 emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
9878 emitpcode(POC_INCF, popCopyReg(&pc_pclath));
9879 emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
9880 emitpLabel(jtab->key);
9882 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9884 /* now generate the jump labels */
9885 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9886 jtab = setNextItem(IC_JTLABELS(ic))) {
9887 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
9888 emitpcode(POC_GOTO,popGetLabel(jtab->key));
9894 /*-----------------------------------------------------------------*/
9895 /* genMixedOperation - gen code for operators between mixed types */
9896 /*-----------------------------------------------------------------*/
9898 TSD - Written for the PIC port - but this unfortunately is buggy.
9899 This routine is good in that it is able to efficiently promote
9900 types to different (larger) sizes. Unfortunately, the temporary
9901 variables that are optimized out by this routine are sometimes
9902 used in other places. So until I know how to really parse the
9903 iCode tree, I'm going to not be using this routine :(.
9905 static int genMixedOperation (iCode *ic)
9909 operand *result = IC_RESULT(ic);
9910 sym_link *ctype = operandType(IC_LEFT(ic));
9911 operand *right = IC_RIGHT(ic);
9917 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9919 pic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
9925 nextright = IC_RIGHT(nextic);
9926 nextleft = IC_LEFT(nextic);
9927 nextresult = IC_RESULT(nextic);
9929 aopOp(right,ic,FALSE);
9930 aopOp(result,ic,FALSE);
9931 aopOp(nextright, nextic, FALSE);
9932 aopOp(nextleft, nextic, FALSE);
9933 aopOp(nextresult, nextic, FALSE);
9935 if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9941 pic14_emitcode(";remove right +","");
9943 } else if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9949 pic14_emitcode(";remove left +","");
9953 big = AOP_SIZE(nextleft);
9954 small = AOP_SIZE(nextright);
9956 switch(nextic->op) {
9959 pic14_emitcode(";optimize a +","");
9960 /* if unsigned or not an integral type */
9961 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9962 pic14_emitcode(";add a bit to something","");
9965 pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9967 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9968 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9969 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9971 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9979 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9980 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9981 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9984 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9986 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
9987 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9988 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9989 pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9990 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9993 pic14_emitcode("rlf","known_zero,w");
10000 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10001 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10002 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10004 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10014 freeAsmop(right,NULL,ic,TRUE);
10015 freeAsmop(result,NULL,ic,TRUE);
10016 freeAsmop(nextright,NULL,ic,TRUE);
10017 freeAsmop(nextleft,NULL,ic,TRUE);
10019 nextic->generated = 1;
10026 /*-----------------------------------------------------------------*/
10027 /* genCast - gen code for casting */
10028 /*-----------------------------------------------------------------*/
10029 static void genCast (iCode *ic)
10031 operand *result = IC_RESULT(ic);
10032 sym_link *ctype = operandType(IC_LEFT(ic));
10033 sym_link *rtype = operandType(IC_RIGHT(ic));
10034 operand *right = IC_RIGHT(ic);
10038 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10039 /* if they are equivalent then do nothing */
10040 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10043 aopOp(right,ic,FALSE) ;
10044 aopOp(result,ic,FALSE);
10046 DEBUGpic14_AopType(__LINE__,NULL,right,result);
10048 /* if the result is a bit */
10049 if (AOP_TYPE(result) == AOP_CRY) {
10050 /* if the right size is a literal then
10051 we know what the value is */
10052 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10053 if (AOP_TYPE(right) == AOP_LIT) {
10055 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10056 popGet(AOP(result),0));
10058 if (((int) operandLitValue(right)))
10059 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
10060 AOP(result)->aopu.aop_dir,
10061 AOP(result)->aopu.aop_dir);
10063 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
10064 AOP(result)->aopu.aop_dir,
10065 AOP(result)->aopu.aop_dir);
10070 /* the right is also a bit variable */
10071 if (AOP_TYPE(right) == AOP_CRY) {
10074 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10076 pic14_emitcode("clrc","");
10077 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10078 AOP(right)->aopu.aop_dir,
10079 AOP(right)->aopu.aop_dir);
10080 aopPut(AOP(result),"c",0);
10084 /* we need to or */
10085 if (AOP_TYPE(right) == AOP_REG) {
10086 emitpcode(POC_BCF, popGet(AOP(result),0));
10087 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
10088 emitpcode(POC_BSF, popGet(AOP(result),0));
10090 pic14_toBoolean(right);
10091 aopPut(AOP(result),"a",0);
10095 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10097 size = AOP_SIZE(result);
10099 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10101 emitpcode(POC_CLRF, popGet(AOP(result),0));
10102 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10103 emitpcode(POC_INCF, popGet(AOP(result),0));
10106 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
10111 /* if they are the same size : or less */
10112 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10114 /* if they are in the same place */
10115 if (pic14_sameRegs(AOP(right),AOP(result)))
10118 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10119 if (IS_PTR_CONST(rtype))
10120 DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10121 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10122 DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10124 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10125 emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10126 emitpcode(POC_MOVWF, popGet(AOP(result),0));
10127 emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10128 emitpcode(POC_MOVWF, popGet(AOP(result),1));
10129 if(AOP_SIZE(result) <2)
10130 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10134 /* if they in different places then copy */
10135 size = AOP_SIZE(result);
10138 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10139 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10141 //aopPut(AOP(result),
10142 // aopGet(AOP(right),offset,FALSE,FALSE),
10152 /* if the result is of type pointer */
10153 if (IS_PTR(ctype)) {
10156 sym_link *type = operandType(right);
10157 sym_link *etype = getSpec(type);
10158 DEBUGpic14_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
10160 /* pointer to generic pointer */
10161 if (IS_GENPTR(ctype)) {
10165 p_type = DCL_TYPE(type);
10167 /* we have to go by the storage class */
10168 p_type = PTR_TYPE(SPEC_OCLS(etype));
10170 /* if (SPEC_OCLS(etype)->codesp ) */
10171 /* p_type = CPOINTER ; */
10173 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10174 /* p_type = FPOINTER ; */
10176 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10177 /* p_type = PPOINTER; */
10179 /* if (SPEC_OCLS(etype) == idata ) */
10180 /* p_type = IPOINTER ; */
10182 /* p_type = POINTER ; */
10185 /* the first two bytes are known */
10186 DEBUGpic14_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
10187 size = GPTRSIZE - 1;
10190 if(offset < AOP_SIZE(right)) {
10191 DEBUGpic14_emitcode("; ***","%s %d - pointer cast3",__FUNCTION__,__LINE__);
10192 if ((AOP_TYPE(right) == AOP_PCODE) &&
10193 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10194 emitpcode(POC_MOVLW, popGetAddr(AOP(right),offset,0));
10195 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10197 aopPut(AOP(result),
10198 aopGet(AOP(right),offset,FALSE,FALSE),
10202 emitpcode(POC_CLRF,popGet(AOP(result),offset));
10205 /* the last byte depending on type */
10209 emitpcode(POC_CLRF,popGet(AOP(result),GPTRSIZE - 1));
10212 pic14_emitcode(";BUG!? ","%d",__LINE__);
10216 pic14_emitcode(";BUG!? ","%d",__LINE__);
10220 pic14_emitcode(";BUG!? ","%d",__LINE__);
10225 /* this should never happen */
10226 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10227 "got unknown pointer type");
10230 //aopPut(AOP(result),l, GPTRSIZE - 1);
10234 /* just copy the pointers */
10235 size = AOP_SIZE(result);
10238 aopPut(AOP(result),
10239 aopGet(AOP(right),offset,FALSE,FALSE),
10248 /* so we now know that the size of destination is greater
10249 than the size of the source.
10250 Now, if the next iCode is an operator then we might be
10251 able to optimize the operation without performing a cast.
10253 if(genMixedOperation(ic))
10256 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10258 /* we move to result for the size of source */
10259 size = AOP_SIZE(right);
10262 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10263 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10267 /* now depending on the sign of the destination */
10268 size = AOP_SIZE(result) - AOP_SIZE(right);
10269 /* if unsigned or not an integral type */
10270 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
10272 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
10274 /* we need to extend the sign :{ */
10277 /* Save one instruction of casting char to int */
10278 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10279 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10280 emitpcode(POC_DECF, popGet(AOP(result),offset));
10282 emitpcodeNULLop(POC_CLRW);
10285 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10287 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),offset,FALSE,FALSE),7,0));
10289 emitpcode(POC_MOVLW, popGetLit(0xff));
10292 emitpcode(POC_MOVWF, popGet(AOP(result),offset++));
10297 freeAsmop(right,NULL,ic,TRUE);
10298 freeAsmop(result,NULL,ic,TRUE);
10302 /*-----------------------------------------------------------------*/
10303 /* genDjnz - generate decrement & jump if not zero instrucion */
10304 /*-----------------------------------------------------------------*/
10305 static int genDjnz (iCode *ic, iCode *ifx)
10307 symbol *lbl, *lbl1;
10309 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10314 /* if the if condition has a false label
10315 then we cannot save */
10319 /* if the minus is not of the form
10321 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10322 !IS_OP_LITERAL(IC_RIGHT(ic)))
10325 if (operandLitValue(IC_RIGHT(ic)) != 1)
10328 /* if the size of this greater than one then no
10330 if (getSize(operandType(IC_RESULT(ic))) > 1)
10333 /* otherwise we can save BIG */
10334 lbl = newiTempLabel(NULL);
10335 lbl1= newiTempLabel(NULL);
10337 aopOp(IC_RESULT(ic),ic,FALSE);
10339 if (IS_AOP_PREG(IC_RESULT(ic))) {
10340 pic14_emitcode("dec","%s",
10341 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10342 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10343 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10347 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10348 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10350 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10351 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10354 /* pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10355 /* pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10356 /* pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10357 /* pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10360 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10361 ifx->generated = 1;
10365 /*-----------------------------------------------------------------*/
10366 /* genReceive - generate code for a receive iCode */
10367 /*-----------------------------------------------------------------*/
10368 static void genReceive (iCode *ic)
10371 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10373 if (isOperandInFarSpace(IC_RESULT(ic)) &&
10374 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10375 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10377 int size = getSize(operandType(IC_RESULT(ic)));
10378 int offset = fReturnSizePic - size;
10380 pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10381 fReturn[fReturnSizePic - offset - 1] : "acc"));
10384 aopOp(IC_RESULT(ic),ic,FALSE);
10385 size = AOP_SIZE(IC_RESULT(ic));
10388 pic14_emitcode ("pop","acc");
10389 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10394 aopOp(IC_RESULT(ic),ic,FALSE);
10396 assignResultValue(IC_RESULT(ic));
10399 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10402 /*-----------------------------------------------------------------*/
10403 /* genDummyRead - generate code for dummy read of volatiles */
10404 /*-----------------------------------------------------------------*/
10406 genDummyRead (iCode * ic)
10409 pic14_emitcode ("; genDummyRead","");
10410 pic14_emitcode ("; not implemented","");
10415 /*-----------------------------------------------------------------*/
10416 /* genpic14Code - generate code for pic14 based controllers */
10417 /*-----------------------------------------------------------------*/
10419 * At this point, ralloc.c has gone through the iCode and attempted
10420 * to optimize in a way suitable for a PIC. Now we've got to generate
10421 * PIC instructions that correspond to the iCode.
10423 * Once the instructions are generated, we'll pass through both the
10424 * peep hole optimizer and the pCode optimizer.
10425 *-----------------------------------------------------------------*/
10427 void genpic14Code (iCode *lic)
10434 lineHead = lineCurr = NULL;
10436 pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10439 /* if debug information required */
10440 if (options.debug && currFunc) {
10442 debugFile->writeFunction (currFunc, lic);
10447 for (ic = lic ; ic ; ic = ic->next ) {
10449 //DEBUGpic14_emitcode(";ic","");
10450 //fprintf (stderr, "in ic loop\n");
10451 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10452 //ic->lineno, printCLine(ic->filename, ic->lineno));
10454 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10456 //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10457 cline = printCLine (ic->filename, ic->lineno);
10458 if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10459 addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10460 //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10463 if (options.iCodeInAsm) {
10464 emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10466 /* if the result is marked as
10467 spilt and rematerializable or code for
10468 this has already been generated then
10470 if (resultRemat(ic) || ic->generated )
10473 /* depending on the operation */
10492 /* IPOP happens only when trying to restore a
10493 spilt live range, if there is an ifx statement
10494 following this pop then the if statement might
10495 be using some of the registers being popped which
10496 would destory the contents of the register so
10497 we need to check for this condition and handle it */
10499 ic->next->op == IFX &&
10500 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10501 genIfx (ic->next,ic);
10519 genEndFunction (ic);
10539 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10556 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
10560 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10567 /* note these two are xlated by algebraic equivalence
10568 during parsing SDCC.y */
10569 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10570 "got '>=' or '<=' shouldn't have come here");
10574 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10586 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10590 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10594 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10618 genRightShift (ic);
10621 case GET_VALUE_AT_ADDRESS:
10626 if (POINTER_SET(ic))
10653 addSet(&_G.sendSet,ic);
10656 case DUMMY_READ_VOLATILE:
10666 /* now we are ready to call the
10667 peep hole optimizer */
10668 if (!options.nopeep) {
10669 peepHole (&lineHead);
10671 /* now do the actual printing */
10672 printLine (lineHead,codeOutFile);
10675 DFPRINTF((stderr,"printing pBlock\n\n"));
10676 printpBlock(stdout,pb);
10683 aop_isLitLike (asmop *aop)
10686 if (aop->type == AOP_LIT) return 1;
10687 if (aop->type == AOP_IMMD) return 1;
10688 if ((aop->type == AOP_PCODE) &&
10689 ((aop->aopu.pcop->type == PO_LITERAL) || (aop->aopu.pcop->type == PO_IMMEDIATE)))
10691 /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10692 * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10699 op_isLitLike (operand *op)
10702 if (aop_isLitLike (AOP(op))) return 1;