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 && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
904 /* force a new aop if sizes differ */
905 sym->usl.spillLoc->aop = NULL;
907 DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
908 __FUNCTION__,__LINE__,
909 sym->usl.spillLoc->rname,
910 sym->rname, sym->usl.spillLoc->offset);
912 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
913 //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
914 aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname,
916 sym->usl.spillLoc->offset);
917 aop->size = getSize(sym->type);
923 sym_link *type = operandType(op);
924 if(IS_PTR_CONST(type))
925 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
928 /* must be in a register */
929 DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
930 sym->aop = op->aop = aop = newAsmop(AOP_REG);
931 aop->size = sym->nRegs;
932 for ( i = 0 ; i < sym->nRegs ;i++)
933 aop->aopu.aop_reg[i] = sym->regs[i];
936 /*-----------------------------------------------------------------*/
937 /* freeAsmop - free up the asmop given to an operand */
938 /*----------------------------------------------------------------*/
939 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
956 /* depending on the asmop type only three cases need work AOP_RO
957 , AOP_R1 && AOP_STK */
963 pic14_emitcode ("pop","ar0");
967 bitVectUnSetBit(ic->rUsed,R0_IDX);
973 pic14_emitcode ("pop","ar1");
977 bitVectUnSetBit(ic->rUsed,R1_IDX);
983 int stk = aop->aopu.aop_stk + aop->size;
984 bitVectUnSetBit(ic->rUsed,R0_IDX);
985 bitVectUnSetBit(ic->rUsed,R1_IDX);
987 getFreePtr(ic,&aop,FALSE);
989 if (options.stack10bit)
991 /* I'm not sure what to do here yet... */
994 "*** Warning: probably generating bad code for "
995 "10 bit stack mode.\n");
999 pic14_emitcode ("mov","a,_bp");
1000 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1001 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1003 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1007 pic14_emitcode("pop","acc");
1008 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1010 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1013 freeAsmop(op,NULL,ic,TRUE);
1015 pic14_emitcode("pop","ar0");
1020 pic14_emitcode("pop","ar1");
1028 /* all other cases just dealloc */
1032 OP_SYMBOL(op)->aop = NULL;
1033 /* if the symbol has a spill */
1035 SPIL_LOC(op)->aop = NULL;
1040 /*-----------------------------------------------------------------*/
1041 /* aopGet - for fetching value of the aop */
1042 /*-----------------------------------------------------------------*/
1043 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1048 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1049 /* offset is greater than
1051 if (offset > (aop->size - 1) &&
1052 aop->type != AOP_LIT)
1055 /* depending on type */
1056 switch (aop->type) {
1060 DEBUGpic14_emitcode(";","%d",__LINE__);
1061 /* if we need to increment it */
1062 while (offset > aop->coff) {
1063 pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);
1067 while (offset < aop->coff) {
1068 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1072 aop->coff = offset ;
1074 pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1075 return (dname ? "acc" : "a");
1077 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1078 rs = Safe_calloc(1,strlen(s)+1);
1084 DEBUGpic14_emitcode(";","%d",__LINE__);
1085 if (aop->type == AOP_DPTR2)
1090 while (offset > aop->coff) {
1091 pic14_emitcode ("inc","dptr");
1095 while (offset < aop->coff) {
1096 pic14_emitcode("lcall","__decdptr");
1102 pic14_emitcode("clr","a");
1103 pic14_emitcode("movc","a,@a+dptr");
1106 pic14_emitcode("movx","a,@dptr");
1109 if (aop->type == AOP_DPTR2)
1114 return (dname ? "acc" : "a");
1119 sprintf (s,"%s",aop->aopu.aop_immd);
1122 sprintf(s,"(%s >> %d)",
1127 aop->aopu.aop_immd);
1128 DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1129 rs = Safe_calloc(1,strlen(s)+1);
1135 sprintf(s,"(%s + %d)",
1138 DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1140 sprintf(s,"%s",aop->aopu.aop_dir);
1141 rs = Safe_calloc(1,strlen(s)+1);
1147 // return aop->aopu.aop_reg[offset]->dname;
1149 return aop->aopu.aop_reg[offset]->name;
1152 //pic14_emitcode(";","%d",__LINE__);
1153 return aop->aopu.aop_dir;
1156 DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1157 return "AOP_accumulator_bug";
1160 sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1161 rs = Safe_calloc(1,strlen(s)+1);
1166 aop->coff = offset ;
1167 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1170 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1172 return aop->aopu.aop_str[offset];
1176 pCodeOp *pcop = aop->aopu.pcop;
1177 DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1180 DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
1181 sprintf(s,"(%s+%d)", pcop->name,offset);
1183 DEBUGpic14_emitcode(";","%s",pcop->name);
1184 sprintf(s,"%s", pcop->name);
1187 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1190 rs = Safe_calloc(1,strlen(s)+1);
1196 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1197 "aopget got unsupported aop->type");
1202 /*-----------------------------------------------------------------*/
1203 /* popGetTempReg - create a new temporary pCodeOp */
1204 /*-----------------------------------------------------------------*/
1205 pCodeOp *popGetTempReg(void)
1210 pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1211 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1212 PCOR(pcop)->r->wasUsed=1;
1213 PCOR(pcop)->r->isFree=0;
1219 /*-----------------------------------------------------------------*/
1220 /* popReleaseTempReg - create a new temporary pCodeOp */
1221 /*-----------------------------------------------------------------*/
1222 void popReleaseTempReg(pCodeOp *pcop)
1225 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1226 PCOR(pcop)->r->isFree = 1;
1229 /*-----------------------------------------------------------------*/
1230 /* popGetLabel - create a new pCodeOp of type PO_LABEL */
1231 /*-----------------------------------------------------------------*/
1232 pCodeOp *popGetLabel(unsigned int key)
1235 DEBUGpic14_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1237 if(key>(unsigned int)max_key)
1240 return newpCodeOpLabel(NULL,key+100+labelOffset);
1243 /*-------------------------------------------------------------------*/
1244 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1245 /*-------------------------------------------------------------------*/
1246 pCodeOp *popGetHighLabel(unsigned int key)
1249 pcop = popGetLabel(key);
1250 PCOLAB(pcop)->offset = 1;
1254 /*-----------------------------------------------------------------*/
1255 /* popGetLit - asm operator to pcode operator conversion */
1256 /*-----------------------------------------------------------------*/
1257 pCodeOp *popGetLit(unsigned int lit)
1260 return newpCodeOpLit(lit);
1263 /*-----------------------------------------------------------------*/
1264 /* popGetImmd - asm operator to pcode immediate conversion */
1265 /*-----------------------------------------------------------------*/
1266 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1269 return newpCodeOpImmd(name, offset,index, 0, is_func);
1273 /*-----------------------------------------------------------------*/
1274 /* popGetWithString - asm operator to pcode operator conversion */
1275 /*-----------------------------------------------------------------*/
1276 pCodeOp *popGetWithString(char *str, int isExtern)
1282 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1286 pcop = newpCodeOp(str,PO_STR);
1287 PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1292 /*-----------------------------------------------------------------*/
1293 /* popRegFromString - */
1294 /*-----------------------------------------------------------------*/
1295 pCodeOp *popRegFromString(char *str, int size, int offset)
1298 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1299 pcop->type = PO_DIR;
1301 DEBUGpic14_emitcode(";","%d",__LINE__);
1306 pcop->name = Safe_calloc(1,strlen(str)+1);
1307 strcpy(pcop->name,str);
1309 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1311 PCOR(pcop)->r = dirregWithName(pcop->name);
1312 if(PCOR(pcop)->r == NULL) {
1313 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1314 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1315 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1317 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1319 PCOR(pcop)->instance = offset;
1324 /*-----------------------------------------------------------------*/
1325 /*-----------------------------------------------------------------*/
1326 pCodeOp *popRegFromIdx(int rIdx)
1330 DEBUGpic14_emitcode ("; ***","%s,%d , rIdx=0x%x",
1331 __FUNCTION__,__LINE__,rIdx);
1333 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1335 PCOR(pcop)->rIdx = rIdx;
1336 PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1337 PCOR(pcop)->r->isFree = 0;
1338 PCOR(pcop)->r->wasUsed = 1;
1340 pcop->type = PCOR(pcop)->r->pc_type;
1346 /*-----------------------------------------------------------------*/
1347 /* popGet - asm operator to pcode operator conversion */
1348 /*-----------------------------------------------------------------*/
1349 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1351 //char *s = buffer ;
1356 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1357 /* offset is greater than
1360 if (!(offset >= 0 && ((offset < aop->size) || (aop->size == 0))))
1362 fprintf (stderr, "%s:%u: offset=%d, aop-type:%s, size:%d\n", __FILE__, __LINE__, offset, AopType (aop->type), aop->size);
1364 assert (offset >= 0 && ((offset < aop->size) || (aop->size == 0)));
1366 /* XXX: still needed for BIT operands (AOP_CRY) */
1367 if (offset > (aop->size - 1) &&
1368 aop->type != AOP_LIT)
1369 return NULL; //zero;
1371 /* depending on type */
1372 switch (aop->type) {
1379 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1383 DEBUGpic14_emitcode(";","%d",__LINE__);
1384 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1387 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1389 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1390 pcop->type = PO_DIR;
1392 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1393 strcpy(pcop->name,aop->aopu.aop_dir);
1394 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1395 if(PCOR(pcop)->r == NULL) {
1396 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1397 PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1398 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1400 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1402 PCOR(pcop)->instance = offset;
1409 int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1411 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1412 PCOR(pcop)->rIdx = rIdx;
1413 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1414 PCOR(pcop)->r->wasUsed=1;
1415 PCOR(pcop)->r->isFree=0;
1417 PCOR(pcop)->instance = offset;
1418 pcop->type = PCOR(pcop)->r->pc_type;
1419 //rs = aop->aopu.aop_reg[offset]->name;
1420 DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1425 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1426 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1427 //if(PCOR(pcop)->r == NULL)
1428 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1432 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1435 DEBUGpic14_emitcode(";","%d %s",__LINE__,aop->aopu.aop_str[offset]);
1436 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1438 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1439 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1440 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1441 pcop->type = PCOR(pcop)->r->pc_type;
1442 pcop->name = PCOR(pcop)->r->name;
1449 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1451 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1452 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1453 switch (aop->aopu.pcop->type)
1456 pcop = pCodeOpCopy (aop->aopu.pcop);
1457 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1458 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1459 PCOI(pcop)->index += offset;
1460 //PCOI(pcop)->offset = 0;
1463 pcop = pCodeOpCopy (aop->aopu.pcop);
1464 PCOR(pcop)->instance = offset;
1467 assert ( !"unhandled pCode type" );
1473 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1474 "popGet got unsupported aop->type");
1478 /*-----------------------------------------------------------------*/
1479 /* popGetAddr - access the low/high word of a symbol (immediate) */
1480 /* (for non-PO_IMMEDIATEs this is the same as poGet) */
1481 /*-----------------------------------------------------------------*/
1482 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1484 if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1486 pCodeOp *pcop = aop->aopu.pcop;
1487 pcop = pCodeOpCopy (pcop);
1488 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1489 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1490 PCOI(pcop)->offset += offset;
1491 PCOI(pcop)->index += index;
1494 return popGet (aop, offset + index);
1498 /*-----------------------------------------------------------------*/
1499 /* aopPut - puts a string for a aop */
1500 /*-----------------------------------------------------------------*/
1501 void aopPut (asmop *aop, char *s, int offset)
1506 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1508 if (aop->size && offset > ( aop->size - 1)) {
1509 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1510 "aopPut got offset > aop->size");
1514 /* will assign value to value */
1515 /* depending on where it is ofcourse */
1516 switch (aop->type) {
1519 sprintf(d,"(%s + %d)",
1520 aop->aopu.aop_dir,offset);
1521 fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1524 sprintf(d,"%s",aop->aopu.aop_dir);
1527 DEBUGpic14_emitcode(";","%d",__LINE__);
1529 pic14_emitcode("movf","%s,w",s);
1530 pic14_emitcode("movwf","%s",d);
1533 pic14_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
1534 if(offset >= aop->size) {
1535 emitpcode(POC_CLRF,popGet(aop,offset));
1538 emitpcode(POC_MOVLW,popGetImmd(s,offset,0,0));
1541 emitpcode(POC_MOVWF,popGet(aop,offset));
1548 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1549 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1552 strcmp(s,"r0") == 0 ||
1553 strcmp(s,"r1") == 0 ||
1554 strcmp(s,"r2") == 0 ||
1555 strcmp(s,"r3") == 0 ||
1556 strcmp(s,"r4") == 0 ||
1557 strcmp(s,"r5") == 0 ||
1558 strcmp(s,"r6") == 0 ||
1559 strcmp(s,"r7") == 0 )
1560 pic14_emitcode("mov","%s,%s ; %d",
1561 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1565 if(strcmp(s,"W")==0 )
1566 pic14_emitcode("movf","%s,w ; %d",s,__LINE__);
1568 pic14_emitcode("movwf","%s",
1569 aop->aopu.aop_reg[offset]->name);
1571 if(strcmp(s,zero)==0) {
1572 emitpcode(POC_CLRF,popGet(aop,offset));
1574 } else if(strcmp(s,"W")==0) {
1575 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1576 pcop->type = PO_GPR_REGISTER;
1578 PCOR(pcop)->rIdx = -1;
1579 PCOR(pcop)->r = NULL;
1581 DEBUGpic14_emitcode(";","%d",__LINE__);
1582 pcop->name = Safe_strdup(s);
1583 emitpcode(POC_MOVFW,pcop);
1584 emitpcode(POC_MOVWF,popGet(aop,offset));
1585 } else if(strcmp(s,one)==0) {
1586 emitpcode(POC_CLRF,popGet(aop,offset));
1587 emitpcode(POC_INCF,popGet(aop,offset));
1589 emitpcode(POC_MOVWF,popGet(aop,offset));
1597 if (aop->type == AOP_DPTR2)
1603 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1604 "aopPut writting to code space");
1608 while (offset > aop->coff) {
1610 pic14_emitcode ("inc","dptr");
1613 while (offset < aop->coff) {
1615 pic14_emitcode("lcall","__decdptr");
1620 /* if not in accumulater */
1623 pic14_emitcode ("movx","@dptr,a");
1625 if (aop->type == AOP_DPTR2)
1633 while (offset > aop->coff) {
1635 pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1637 while (offset < aop->coff) {
1639 pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1645 pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1650 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1652 if (strcmp(s,"r0") == 0 ||
1653 strcmp(s,"r1") == 0 ||
1654 strcmp(s,"r2") == 0 ||
1655 strcmp(s,"r3") == 0 ||
1656 strcmp(s,"r4") == 0 ||
1657 strcmp(s,"r5") == 0 ||
1658 strcmp(s,"r6") == 0 ||
1659 strcmp(s,"r7") == 0 ) {
1661 sprintf(buffer,"a%s",s);
1662 pic14_emitcode("mov","@%s,%s",
1663 aop->aopu.aop_ptr->name,buffer);
1665 pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1670 if (strcmp(s,"a") == 0)
1671 pic14_emitcode("push","acc");
1673 pic14_emitcode("push","%s",s);
1678 /* if bit variable */
1679 if (!aop->aopu.aop_dir) {
1680 pic14_emitcode("clr","a");
1681 pic14_emitcode("rlc","a");
1684 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1687 pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1690 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1692 lbl = newiTempLabel(NULL);
1694 if (strcmp(s,"a")) {
1697 pic14_emitcode("clr","c");
1698 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1699 pic14_emitcode("cpl","c");
1700 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1701 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1708 if (strcmp(aop->aopu.aop_str[offset],s))
1709 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1714 if (!offset && (strcmp(s,"acc") == 0))
1717 if (strcmp(aop->aopu.aop_str[offset],s))
1718 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1722 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1723 "aopPut got unsupported aop->type");
1729 /*-----------------------------------------------------------------*/
1730 /* mov2w - generate either a MOVLW or MOVFW based operand type */
1731 /*-----------------------------------------------------------------*/
1732 void mov2w (asmop *aop, int offset)
1738 DEBUGpic14_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
1740 if ( aop_isLitLike (aop) )
1741 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1743 emitpcode(POC_MOVFW,popGet(aop,offset));
1747 /*-----------------------------------------------------------------*/
1748 /* reAdjustPreg - points a register back to where it should */
1749 /*-----------------------------------------------------------------*/
1750 static void reAdjustPreg (asmop *aop)
1754 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1756 if ((size = aop->size) <= 1)
1759 switch (aop->type) {
1763 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1767 if (aop->type == AOP_DPTR2)
1773 pic14_emitcode("lcall","__decdptr");
1776 if (aop->type == AOP_DPTR2)
1788 /*-----------------------------------------------------------------*/
1789 /* opIsGptr: returns non-zero if the passed operand is */
1790 /* a generic pointer type. */
1791 /*-----------------------------------------------------------------*/
1792 static int opIsGptr(operand *op)
1794 sym_link *type = operandType(op);
1796 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1797 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1805 /*-----------------------------------------------------------------*/
1806 /* pic14_getDataSize - get the operand data size */
1807 /*-----------------------------------------------------------------*/
1808 int pic14_getDataSize(operand *op)
1810 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1813 return AOP_SIZE(op);
1815 // tsd- in the pic port, the genptr size is 1, so this code here
1816 // fails. ( in the 8051 port, the size was 4).
1819 size = AOP_SIZE(op);
1820 if (size == GPTRSIZE)
1822 sym_link *type = operandType(op);
1823 if (IS_GENPTR(type))
1825 /* generic pointer; arithmetic operations
1826 * should ignore the high byte (pointer type).
1829 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1836 /*-----------------------------------------------------------------*/
1837 /* pic14_outAcc - output Acc */
1838 /*-----------------------------------------------------------------*/
1839 void pic14_outAcc(operand *result)
1842 DEBUGpic14_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
1843 DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1846 size = pic14_getDataSize(result);
1848 emitpcode(POC_MOVWF,popGet(AOP(result),0));
1851 /* unsigned or positive */
1853 emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1858 /*-----------------------------------------------------------------*/
1859 /* pic14_outBitC - output a bit C */
1860 /*-----------------------------------------------------------------*/
1861 void pic14_outBitC(operand *result)
1864 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1865 /* if the result is bit */
1866 if (AOP_TYPE(result) == AOP_CRY)
1867 aopPut(AOP(result),"c",0);
1869 pic14_emitcode("clr","a ; %d", __LINE__);
1870 pic14_emitcode("rlc","a");
1871 pic14_outAcc(result);
1875 /*-----------------------------------------------------------------*/
1876 /* pic14_toBoolean - emit code for orl a,operator(sizeop) */
1877 /*-----------------------------------------------------------------*/
1878 void pic14_toBoolean(operand *oper)
1880 int size = AOP_SIZE(oper) - 1;
1883 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1885 if ( AOP_TYPE(oper) != AOP_ACC) {
1886 emitpcode(POC_MOVFW,popGet(AOP(oper),0));
1889 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
1894 /*-----------------------------------------------------------------*/
1895 /* genNot - generate code for ! operation */
1896 /*-----------------------------------------------------------------*/
1897 static void genNot (iCode *ic)
1904 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1905 /* assign asmOps to operand & result */
1906 aopOp (IC_LEFT(ic),ic,FALSE);
1907 aopOp (IC_RESULT(ic),ic,TRUE);
1909 DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1910 /* if in bit space then a special case */
1911 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1912 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1913 emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
1914 emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
1916 emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
1917 emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
1918 emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
1923 size = AOP_SIZE(IC_LEFT(ic));
1925 emitpcode(POC_COMFW,popGet(AOP(IC_LEFT(ic)),0));
1926 emitpcode(POC_ANDLW,popGetLit(1));
1927 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
1930 pic14_toBoolean(IC_LEFT(ic));
1932 tlbl = newiTempLabel(NULL);
1933 pic14_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1934 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
1935 pic14_outBitC(IC_RESULT(ic));
1938 /* release the aops */
1939 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1940 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1944 /*-----------------------------------------------------------------*/
1945 /* genCpl - generate code for complement */
1946 /*-----------------------------------------------------------------*/
1947 static void genCpl (iCode *ic)
1949 operand *left, *result;
1954 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1955 aopOp((left = IC_LEFT(ic)),ic,FALSE);
1956 aopOp((result=IC_RESULT(ic)),ic,TRUE);
1958 /* if both are in bit space then
1960 if (AOP_TYPE(result) == AOP_CRY &&
1961 AOP_TYPE(left) == AOP_CRY ) {
1963 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir);
1964 pic14_emitcode("cpl","c");
1965 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir);
1969 size = AOP_SIZE(result);
1972 if(AOP_TYPE(left) == AOP_ACC)
1973 emitpcode(POC_XORLW, popGetLit(0xff));
1975 emitpcode(POC_COMFW,popGet(AOP(left),offset));
1977 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
1983 /* release the aops */
1984 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1985 freeAsmop(result,NULL,ic,TRUE);
1988 /*-----------------------------------------------------------------*/
1989 /* genUminusFloat - unary minus for floating points */
1990 /*-----------------------------------------------------------------*/
1991 static void genUminusFloat(operand *op,operand *result)
1993 int size ,offset =0 ;
1998 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1999 /* for this we just need to flip the
2000 first it then copy the rest in place */
2001 size = AOP_SIZE(op) - 1;
2002 l = aopGet(AOP(op),3,FALSE,FALSE);
2006 pic14_emitcode("cpl","acc.7");
2007 aopPut(AOP(result),"a",3);
2011 aopGet(AOP(op),offset,FALSE,FALSE),
2017 /*-----------------------------------------------------------------*/
2018 /* genUminus - unary minus code generation */
2019 /*-----------------------------------------------------------------*/
2020 static void genUminus (iCode *ic)
2023 sym_link *optype, *rtype;
2027 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2029 aopOp(IC_LEFT(ic),ic,FALSE);
2030 aopOp(IC_RESULT(ic),ic,TRUE);
2032 /* if both in bit space then special
2034 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2035 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2037 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0));
2038 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2039 emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0));
2044 optype = operandType(IC_LEFT(ic));
2045 rtype = operandType(IC_RESULT(ic));
2047 /* if float then do float stuff */
2048 if (IS_FLOAT(optype)) {
2049 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2053 /* otherwise subtract from zero by taking the 2's complement */
2054 size = AOP_SIZE(IC_LEFT(ic));
2056 for(i=0; i<size; i++) {
2057 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2058 emitpcode(POC_COMF, popGet(AOP(IC_LEFT(ic)),i));
2060 emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2061 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2065 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0));
2066 for(i=1; i<size; i++) {
2068 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),i));
2072 /* release the aops */
2073 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2074 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2077 /*-----------------------------------------------------------------*/
2078 /* saveRegisters - will look for a call and save the registers */
2079 /*-----------------------------------------------------------------*/
2080 static void saveRegisters(iCode *lic)
2089 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2091 for (ic = lic ; ic ; ic = ic->next)
2092 if (ic->op == CALL || ic->op == PCALL)
2096 fprintf(stderr,"found parameter push with no function call\n");
2100 /* if the registers have been saved already then
2102 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2105 /* find the registers in use at this time
2106 and push them away to safety */
2107 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2111 if (options.useXstack) {
2112 if (bitVectBitValue(rsave,R0_IDX))
2113 pic14_emitcode("mov","b,r0");
2114 pic14_emitcode("mov","r0,%s",spname);
2115 for (i = 0 ; i < pic14_nRegs ; i++) {
2116 if (bitVectBitValue(rsave,i)) {
2118 pic14_emitcode("mov","a,b");
2120 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2121 pic14_emitcode("movx","@r0,a");
2122 pic14_emitcode("inc","r0");
2125 pic14_emitcode("mov","%s,r0",spname);
2126 if (bitVectBitValue(rsave,R0_IDX))
2127 pic14_emitcode("mov","r0,b");
2129 //for (i = 0 ; i < pic14_nRegs ; i++) {
2130 // if (bitVectBitValue(rsave,i))
2131 // pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2134 dtype = operandType(IC_LEFT(ic));
2135 if (currFunc && dtype &&
2136 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2137 IFFUNC_ISISR(currFunc->type) &&
2140 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2143 /*-----------------------------------------------------------------*/
2144 /* unsaveRegisters - pop the pushed registers */
2145 /*-----------------------------------------------------------------*/
2146 static void unsaveRegisters (iCode *ic)
2153 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2154 /* find the registers in use at this time
2155 and push them away to safety */
2156 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2159 if (options.useXstack) {
2160 pic14_emitcode("mov","r0,%s",spname);
2161 for (i = pic14_nRegs ; i >= 0 ; i--) {
2162 if (bitVectBitValue(rsave,i)) {
2163 pic14_emitcode("dec","r0");
2164 pic14_emitcode("movx","a,@r0");
2166 pic14_emitcode("mov","b,a");
2168 pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2172 pic14_emitcode("mov","%s,r0",spname);
2173 if (bitVectBitValue(rsave,R0_IDX))
2174 pic14_emitcode("mov","r0,b");
2176 //for (i = pic14_nRegs ; i >= 0 ; i--) {
2177 // if (bitVectBitValue(rsave,i))
2178 // pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2184 /*-----------------------------------------------------------------*/
2186 /*-----------------------------------------------------------------*/
2187 static void pushSide(operand * oper, int size)
2191 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2193 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2194 if (AOP_TYPE(oper) != AOP_REG &&
2195 AOP_TYPE(oper) != AOP_DIR &&
2197 pic14_emitcode("mov","a,%s",l);
2198 pic14_emitcode("push","acc");
2200 pic14_emitcode("push","%s",l);
2205 /*-----------------------------------------------------------------*/
2206 /* assignResultValue - */
2207 /*-----------------------------------------------------------------*/
2208 static void assignResultValue(operand * oper)
2210 int size = AOP_SIZE(oper);
2214 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2216 DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2219 if (GpsuedoStkPtr++)
2220 emitpcode(POC_MOVFW,popRegFromIdx(Gstack_base_addr+2-GpsuedoStkPtr));
2221 emitpcode(POC_MOVWF, popGet(AOP(oper),size));
2226 /*-----------------------------------------------------------------*/
2227 /* genIpush - genrate code for pushing this gets a little complex */
2228 /*-----------------------------------------------------------------*/
2229 static void genIpush (iCode *ic)
2233 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2235 int size, offset = 0 ;
2239 /* if this is not a parm push : ie. it is spill push
2240 and spill push is always done on the local stack */
2241 if (!ic->parmPush) {
2243 /* and the item is spilt then do nothing */
2244 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2247 aopOp(IC_LEFT(ic),ic,FALSE);
2248 size = AOP_SIZE(IC_LEFT(ic));
2249 /* push it on the stack */
2251 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2256 pic14_emitcode("push","%s",l);
2261 /* this is a paramter push: in this case we call
2262 the routine to find the call and save those
2263 registers that need to be saved */
2266 /* then do the push */
2267 aopOp(IC_LEFT(ic),ic,FALSE);
2270 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2271 size = AOP_SIZE(IC_LEFT(ic));
2274 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2275 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
2276 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2278 pic14_emitcode("mov","a,%s",l);
2279 pic14_emitcode("push","acc");
2281 pic14_emitcode("push","%s",l);
2284 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2288 /*-----------------------------------------------------------------*/
2289 /* genIpop - recover the registers: can happen only for spilling */
2290 /*-----------------------------------------------------------------*/
2291 static void genIpop (iCode *ic)
2295 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2300 /* if the temp was not pushed then */
2301 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2304 aopOp(IC_LEFT(ic),ic,FALSE);
2305 size = AOP_SIZE(IC_LEFT(ic));
2308 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2311 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2315 /*-----------------------------------------------------------------*/
2316 /* unsaverbank - restores the resgister bank from stack */
2317 /*-----------------------------------------------------------------*/
2318 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2322 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2328 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2330 if (options.useXstack) {
2332 r = getFreePtr(ic,&aop,FALSE);
2335 pic14_emitcode("mov","%s,_spx",r->name);
2336 pic14_emitcode("movx","a,@%s",r->name);
2337 pic14_emitcode("mov","psw,a");
2338 pic14_emitcode("dec","%s",r->name);
2341 pic14_emitcode ("pop","psw");
2344 for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2345 if (options.useXstack) {
2346 pic14_emitcode("movx","a,@%s",r->name);
2347 //pic14_emitcode("mov","(%s+%d),a",
2348 // regspic14[i].base,8*bank+regspic14[i].offset);
2349 pic14_emitcode("dec","%s",r->name);
2352 pic14_emitcode("pop",""); //"(%s+%d)",
2353 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2356 if (options.useXstack) {
2358 pic14_emitcode("mov","_spx,%s",r->name);
2359 freeAsmop(NULL,aop,ic,TRUE);
2365 /*-----------------------------------------------------------------*/
2366 /* saverbank - saves an entire register bank on the stack */
2367 /*-----------------------------------------------------------------*/
2368 static void saverbank (int bank, iCode *ic, bool pushPsw)
2372 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2378 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2379 if (options.useXstack) {
2382 r = getFreePtr(ic,&aop,FALSE);
2383 pic14_emitcode("mov","%s,_spx",r->name);
2387 for (i = 0 ; i < pic14_nRegs ;i++) {
2388 if (options.useXstack) {
2389 pic14_emitcode("inc","%s",r->name);
2390 //pic14_emitcode("mov","a,(%s+%d)",
2391 // regspic14[i].base,8*bank+regspic14[i].offset);
2392 pic14_emitcode("movx","@%s,a",r->name);
2394 pic14_emitcode("push","");// "(%s+%d)",
2395 //regspic14[i].base,8*bank+regspic14[i].offset);
2399 if (options.useXstack) {
2400 pic14_emitcode("mov","a,psw");
2401 pic14_emitcode("movx","@%s,a",r->name);
2402 pic14_emitcode("inc","%s",r->name);
2403 pic14_emitcode("mov","_spx,%s",r->name);
2404 freeAsmop (NULL,aop,ic,TRUE);
2407 pic14_emitcode("push","psw");
2409 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2415 /*-----------------------------------------------------------------*/
2416 /* genCall - generates a call statement */
2417 /*-----------------------------------------------------------------*/
2418 static void genCall (iCode *ic)
2422 unsigned char *name;
2427 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2429 /* if caller saves & we have not saved then */
2433 /* if we are calling a function that is not using
2434 the same register bank then we need to save the
2435 destination registers on the stack */
2436 dtype = operandType(IC_LEFT(ic));
2437 if (currFunc && dtype &&
2438 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2439 IFFUNC_ISISR(currFunc->type) &&
2442 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2444 /* if send set is not empty the assign */
2447 /* For the Pic port, there is no data stack.
2448 * So parameters passed to functions are stored
2449 * in registers. (The pCode optimizer will get
2450 * rid of most of these :).
2452 int psuedoStkPtr=-1;
2453 int firstTimeThruLoop = 1;
2455 _G.sendSet = reverseSet(_G.sendSet);
2457 /* First figure how many parameters are getting passed */
2458 for (sic = setFirstItem(_G.sendSet) ; sic ;
2459 sic = setNextItem(_G.sendSet)) {
2461 aopOp(IC_LEFT(sic),sic,FALSE);
2462 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2463 freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2466 for (sic = setFirstItem(_G.sendSet) ; sic ;
2467 sic = setNextItem(_G.sendSet)) {
2468 int size, offset = 0;
2470 aopOp(IC_LEFT(sic),sic,FALSE);
2471 size = AOP_SIZE(IC_LEFT(sic));
2474 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2475 AopType(AOP_TYPE(IC_LEFT(sic))));
2477 if(!firstTimeThruLoop) {
2478 /* If this is not the first time we've been through the loop
2479 * then we need to save the parameter in a temporary
2480 * register. The last byte of the last parameter is
2482 emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2485 firstTimeThruLoop=0;
2487 mov2w (AOP(IC_LEFT(sic)), offset);
2490 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2495 sym = OP_SYMBOL(IC_LEFT(ic));
2496 name = sym->rname[0] ? sym->rname : sym->name;
2497 isExtern = IS_EXTERN(sym->etype);
2499 emitpcode(POC_PAGESEL,popGetWithString(name,1)); /* Extern functions maybe on another page - must call pagesel */
2501 emitpcode(POC_CALL,popGetWithString(name,isExtern));
2503 emitpcode(POC_PAGESEL,popGetWithString("$",0)); /* May have returned from another page - must call pagesel to restore PCLATH before next goto or call instruction */
2506 /* if we need assign a result value */
2507 if ((IS_ITEMP(IC_RESULT(ic)) &&
2508 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2509 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2510 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2513 aopOp(IC_RESULT(ic),ic,FALSE);
2516 assignResultValue(IC_RESULT(ic));
2518 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2519 AopType(AOP_TYPE(IC_RESULT(ic))));
2521 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2524 /* adjust the stack for parameters if
2526 if (ic->parmBytes) {
2528 if (ic->parmBytes > 3) {
2529 pic14_emitcode("mov","a,%s",spname);
2530 pic14_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2531 pic14_emitcode("mov","%s,a",spname);
2533 for ( i = 0 ; i < ic->parmBytes ;i++)
2534 pic14_emitcode("dec","%s",spname);
2538 /* if register bank was saved then pop them */
2540 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2542 /* if we hade saved some registers then unsave them */
2543 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2544 unsaveRegisters (ic);
2549 /*-----------------------------------------------------------------*/
2550 /* genPcall - generates a call by pointer statement */
2551 /*-----------------------------------------------------------------*/
2552 static void genPcall (iCode *ic)
2555 symbol *albl = newiTempLabel(NULL);
2556 symbol *blbl = newiTempLabel(NULL);
2563 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2564 /* if caller saves & we have not saved then */
2568 /* if we are calling a function that is not using
2569 the same register bank then we need to save the
2570 destination registers on the stack */
2571 dtype = operandType(IC_LEFT(ic));
2572 if (currFunc && dtype &&
2573 IFFUNC_ISISR(currFunc->type) &&
2574 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2575 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2578 aopOp(left,ic,FALSE);
2579 DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2581 pushSide(IC_LEFT(ic), FPTRSIZE);
2583 /* if send set is not empty, assign parameters */
2586 DEBUGpic14_emitcode ("; ***","%s %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2587 /* no way to pass args - W always gets used to make the call */
2589 /* first idea - factor out a common helper function and call it.
2590 But don't know how to get it generated only once in its own block
2592 if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2595 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2596 DEBUGpic14_emitcode ("; ***","%s %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2597 buffer = Safe_calloc(1,strlen(rname)+16);
2598 sprintf(buffer, "%s_goto_helper", rname);
2599 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2603 emitpcode(POC_CALL,popGetLabel(albl->key));
2604 pcop = popGetLabel(blbl->key);
2605 emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
2606 emitpcode(POC_GOTO,pcop);
2607 emitpLabel(albl->key);
2609 poc = ( aop_isLitLike (AOP(left)) ? POC_MOVLW : POC_MOVFW );
2611 emitpcode(poc,popGetAddr(AOP(left),1,0));
2612 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2613 emitpcode(poc,popGetAddr(AOP(left),0,0));
2614 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2616 emitpLabel(blbl->key);
2618 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2620 /* if we need to assign a result value */
2621 if ((IS_ITEMP(IC_RESULT(ic)) &&
2622 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2623 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2624 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2627 aopOp(IC_RESULT(ic),ic,FALSE);
2630 assignResultValue(IC_RESULT(ic));
2632 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2635 /* if register bank was saved then unsave them */
2636 if (currFunc && dtype &&
2637 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2638 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2640 /* if we hade saved some registers then
2643 unsaveRegisters (ic);
2647 /*-----------------------------------------------------------------*/
2648 /* resultRemat - result is rematerializable */
2649 /*-----------------------------------------------------------------*/
2650 static int resultRemat (iCode *ic)
2652 // DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2655 if (SKIP_IC(ic) || ic->op == IFX)
2658 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2659 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2660 if (sym->remat && !POINTER_SET(ic))
2667 #if defined(__BORLANDC__) || defined(_MSC_VER)
2668 #define STRCASECMP stricmp
2670 #define STRCASECMP strcasecmp
2674 /*-----------------------------------------------------------------*/
2675 /* inExcludeList - return 1 if the string is in exclude Reg list */
2676 /*-----------------------------------------------------------------*/
2677 static bool inExcludeList(char *s)
2679 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2682 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2683 if (options.excludeRegs[i] &&
2684 STRCASECMP(options.excludeRegs[i],"none") == 0)
2687 for ( i = 0 ; options.excludeRegs[i]; i++) {
2688 if (options.excludeRegs[i] &&
2689 STRCASECMP(s,options.excludeRegs[i]) == 0)
2696 /*-----------------------------------------------------------------*/
2697 /* genFunction - generated code for function entry */
2698 /*-----------------------------------------------------------------*/
2699 static void genFunction (iCode *ic)
2706 DEBUGpic14_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2708 labelOffset += (max_key+4);
2712 /* create the function header */
2713 pic14_emitcode(";","-----------------------------------------");
2714 pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2715 pic14_emitcode(";","-----------------------------------------");
2717 pic14_emitcode("","%s:",sym->rname);
2718 addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2720 ftype = operandType(IC_LEFT(ic));
2722 /* if critical function then turn interrupts off */
2723 if (IFFUNC_ISCRITICAL(ftype))
2724 pic14_emitcode("clr","ea");
2726 /* here we need to generate the equates for the
2727 register bank if required */
2729 if (FUNC_REGBANK(ftype) != rbank) {
2732 rbank = FUNC_REGBANK(ftype);
2733 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2734 if (strcmp(regspic14[i].base,"0") == 0)
2735 pic14_emitcode("","%s = 0x%02x",
2737 8*rbank+regspic14[i].offset);
2739 pic14_emitcode ("","%s = %s + 0x%02x",
2742 8*rbank+regspic14[i].offset);
2747 /* if this is an interrupt service routine */
2748 if (IFFUNC_ISISR(sym->type)) {
2749 /* already done in pic14createInterruptVect() - delete me
2750 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2751 emitpcodeNULLop(POC_NOP);
2752 emitpcodeNULLop(POC_NOP);
2753 emitpcodeNULLop(POC_NOP);
2755 emitpcode(POC_MOVWF, popCopyReg(&pc_wsave));
2756 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2757 emitpcode(POC_CLRF, popCopyReg(&pc_status));
2758 emitpcode(POC_MOVWF, popCopyReg(&pc_ssave));
2759 emitpcode(POC_MOVFW, popCopyReg(&pc_pclath));
2760 emitpcode(POC_MOVWF, popCopyReg(&pc_psave));
2761 emitpcode(POC_CLRF, popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2763 pBlockConvert2ISR(pb);
2765 if (!inExcludeList("acc"))
2766 pic14_emitcode ("push","acc");
2767 if (!inExcludeList("b"))
2768 pic14_emitcode ("push","b");
2769 if (!inExcludeList("dpl"))
2770 pic14_emitcode ("push","dpl");
2771 if (!inExcludeList("dph"))
2772 pic14_emitcode ("push","dph");
2773 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2775 pic14_emitcode ("push", "dpx");
2776 /* Make sure we're using standard DPTR */
2777 pic14_emitcode ("push", "dps");
2778 pic14_emitcode ("mov", "dps, #0x00");
2779 if (options.stack10bit)
2781 /* This ISR could conceivably use DPTR2. Better save it. */
2782 pic14_emitcode ("push", "dpl1");
2783 pic14_emitcode ("push", "dph1");
2784 pic14_emitcode ("push", "dpx1");
2787 /* if this isr has no bank i.e. is going to
2788 run with bank 0 , then we need to save more
2790 if (!FUNC_REGBANK(sym->type)) {
2792 /* if this function does not call any other
2793 function then we can be economical and
2794 save only those registers that are used */
2795 if (! IFFUNC_HASFCALL(sym->type)) {
2798 /* if any registers used */
2799 if (sym->regsUsed) {
2800 /* save the registers used */
2801 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2802 if (bitVectBitValue(sym->regsUsed,i) ||
2803 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2804 pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);
2809 /* this function has a function call cannot
2810 determines register usage so we will have the
2812 saverbank(0,ic,FALSE);
2817 /* if callee-save to be used for this function
2818 then save the registers being used in this function */
2819 if (IFFUNC_CALLEESAVES(sym->type)) {
2822 /* if any registers used */
2823 if (sym->regsUsed) {
2824 /* save the registers used */
2825 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2826 if (bitVectBitValue(sym->regsUsed,i) ||
2827 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2828 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2836 /* set the register bank to the desired value */
2837 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2838 pic14_emitcode("push","psw");
2839 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);
2842 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2844 if (options.useXstack) {
2845 pic14_emitcode("mov","r0,%s",spname);
2846 pic14_emitcode("mov","a,_bp");
2847 pic14_emitcode("movx","@r0,a");
2848 pic14_emitcode("inc","%s",spname);
2852 /* set up the stack */
2853 pic14_emitcode ("push","_bp"); /* save the callers stack */
2855 pic14_emitcode ("mov","_bp,%s",spname);
2858 /* adjust the stack for the function */
2863 werror(W_STACK_OVERFLOW,sym->name);
2865 if (i > 3 && sym->recvSize < 4) {
2867 pic14_emitcode ("mov","a,sp");
2868 pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2869 pic14_emitcode ("mov","sp,a");
2874 pic14_emitcode("inc","sp");
2879 pic14_emitcode ("mov","a,_spx");
2880 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2881 pic14_emitcode ("mov","_spx,a");
2886 /*-----------------------------------------------------------------*/
2887 /* genEndFunction - generates epilogue for functions */
2888 /*-----------------------------------------------------------------*/
2889 static void genEndFunction (iCode *ic)
2891 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2895 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2897 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2899 pic14_emitcode ("mov","%s,_bp",spname);
2902 /* if use external stack but some variables were
2903 added to the local stack then decrement the
2905 if (options.useXstack && sym->stack) {
2906 pic14_emitcode("mov","a,sp");
2907 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2908 pic14_emitcode("mov","sp,a");
2912 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2913 if (options.useXstack) {
2914 pic14_emitcode("mov","r0,%s",spname);
2915 pic14_emitcode("movx","a,@r0");
2916 pic14_emitcode("mov","_bp,a");
2917 pic14_emitcode("dec","%s",spname);
2921 pic14_emitcode ("pop","_bp");
2925 /* restore the register bank */
2926 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2927 pic14_emitcode ("pop","psw");
2929 if (IFFUNC_ISISR(sym->type)) {
2931 /* now we need to restore the registers */
2932 /* if this isr has no bank i.e. is going to
2933 run with bank 0 , then we need to save more
2935 if (!FUNC_REGBANK(sym->type)) {
2937 /* if this function does not call any other
2938 function then we can be economical and
2939 save only those registers that are used */
2940 if (! IFFUNC_HASFCALL(sym->type)) {
2943 /* if any registers used */
2944 if (sym->regsUsed) {
2945 /* save the registers used */
2946 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2947 if (bitVectBitValue(sym->regsUsed,i) ||
2948 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2949 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2954 /* this function has a function call cannot
2955 determines register usage so we will have the
2957 unsaverbank(0,ic,FALSE);
2961 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2963 if (options.stack10bit)
2965 pic14_emitcode ("pop", "dpx1");
2966 pic14_emitcode ("pop", "dph1");
2967 pic14_emitcode ("pop", "dpl1");
2969 pic14_emitcode ("pop", "dps");
2970 pic14_emitcode ("pop", "dpx");
2972 if (!inExcludeList("dph"))
2973 pic14_emitcode ("pop","dph");
2974 if (!inExcludeList("dpl"))
2975 pic14_emitcode ("pop","dpl");
2976 if (!inExcludeList("b"))
2977 pic14_emitcode ("pop","b");
2978 if (!inExcludeList("acc"))
2979 pic14_emitcode ("pop","acc");
2981 if (IFFUNC_ISCRITICAL(sym->type))
2982 pic14_emitcode("setb","ea");
2985 /* if debug then send end of function */
2986 /* if (options.debug && currFunc) { */
2988 debugFile->writeEndFunction (currFunc, ic, 1);
2991 pic14_emitcode ("reti","");
2992 emitpcode(POC_MOVFW, popCopyReg(&pc_psave));
2993 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
2994 emitpcode(POC_CLRF, popCopyReg(&pc_status));
2995 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
2996 emitpcode(POC_MOVWF, popCopyReg(&pc_status));
2997 emitpcode(POC_SWAPF, popCopyReg(&pc_wsave));
2998 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
2999 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3000 emitpcodeNULLop(POC_RETFIE);
3003 if (IFFUNC_ISCRITICAL(sym->type))
3004 pic14_emitcode("setb","ea");
3006 if (IFFUNC_CALLEESAVES(sym->type)) {
3009 /* if any registers used */
3010 if (sym->regsUsed) {
3011 /* save the registers used */
3012 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3013 if (bitVectBitValue(sym->regsUsed,i) ||
3014 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3015 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3021 /* if debug then send end of function */
3023 debugFile->writeEndFunction (currFunc, ic, 1);
3026 pic14_emitcode ("return","");
3027 emitpcodeNULLop(POC_RETURN);
3029 /* Mark the end of a function */
3030 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3035 /*-----------------------------------------------------------------*/
3036 /* genRet - generate code for return statement */
3037 /*-----------------------------------------------------------------*/
3038 static void genRet (iCode *ic)
3040 int size,offset = 0 , pushed = 0;
3044 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3045 /* if we have no return value then
3046 just generate the "ret" */
3050 /* we have something to return then
3051 move the return value into place */
3052 aopOp(IC_LEFT(ic),ic,FALSE);
3053 size = AOP_SIZE(IC_LEFT(ic));
3057 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3059 l = aopGet(AOP(IC_LEFT(ic)),offset++,
3061 pic14_emitcode("push","%s",l);
3064 l = aopGet(AOP(IC_LEFT(ic)),offset,
3066 if (strcmp(fReturn[offset],l)) {
3067 if ((((AOP(IC_LEFT(ic))->type) == AOP_PCODE) &&
3068 AOP(IC_LEFT(ic))->aopu.pcop->type == PO_IMMEDIATE) ||
3069 ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
3070 ( (AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3071 emitpcode(POC_MOVLW, popGetAddr(AOP(IC_LEFT(ic)),offset,0));
3073 emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset));
3076 emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr+1-size));
3086 if (strcmp(fReturn[pushed],"a"))
3087 pic14_emitcode("pop",fReturn[pushed]);
3089 pic14_emitcode("pop","acc");
3092 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3095 /* generate a jump to the return label
3096 if the next is not the return statement */
3097 if (!(ic->next && ic->next->op == LABEL &&
3098 IC_LABEL(ic->next) == returnLabel)) {
3100 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3101 pic14_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3106 /*-----------------------------------------------------------------*/
3107 /* genLabel - generates a label */
3108 /*-----------------------------------------------------------------*/
3109 static void genLabel (iCode *ic)
3113 /* special case never generate */
3114 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3115 if (IC_LABEL(ic) == entryLabel)
3118 emitpLabel(IC_LABEL(ic)->key);
3119 pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3122 /*-----------------------------------------------------------------*/
3123 /* genGoto - generates a goto */
3124 /*-----------------------------------------------------------------*/
3126 static void genGoto (iCode *ic)
3130 emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3131 pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3135 /*-----------------------------------------------------------------*/
3136 /* genMultbits :- multiplication of bits */
3137 /*-----------------------------------------------------------------*/
3138 static void genMultbits (operand *left,
3143 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3145 if(!pic14_sameRegs(AOP(result),AOP(right)))
3146 emitpcode(POC_BSF, popGet(AOP(result),0));
3148 emitpcode(POC_BTFSC,popGet(AOP(right),0));
3149 emitpcode(POC_BTFSS,popGet(AOP(left),0));
3150 emitpcode(POC_BCF, popGet(AOP(result),0));
3155 /*-----------------------------------------------------------------*/
3156 /* genMultOneByte : 8 bit multiplication & division */
3157 /*-----------------------------------------------------------------*/
3158 static void genMultOneByte (operand *left,
3162 sym_link *opetype = operandType(result);
3169 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3170 DEBUGpic14_AopType(__LINE__,left,right,result);
3171 DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3173 /* (if two literals, the value is computed before) */
3174 /* if one literal, literal on the right */
3175 if (AOP_TYPE(left) == AOP_LIT){
3181 size = AOP_SIZE(result);
3184 if (AOP_TYPE(right) == AOP_LIT){
3185 pic14_emitcode("multiply ","lit val:%s by variable %s and store in %s",
3186 aopGet(AOP(right),0,FALSE,FALSE),
3187 aopGet(AOP(left),0,FALSE,FALSE),
3188 aopGet(AOP(result),0,FALSE,FALSE));
3189 pic14_emitcode("call","genMultLit");
3191 pic14_emitcode("multiply ","variable :%s by variable %s and store in %s",
3192 aopGet(AOP(right),0,FALSE,FALSE),
3193 aopGet(AOP(left),0,FALSE,FALSE),
3194 aopGet(AOP(result),0,FALSE,FALSE));
3195 pic14_emitcode("call","genMult8X8_8");
3198 genMult8X8_8 (left, right,result);
3201 /* signed or unsigned */
3202 //pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3203 //l = aopGet(AOP(left),0,FALSE,FALSE);
3205 //pic14_emitcode("mul","ab");
3206 /* if result size = 1, mul signed = mul unsigned */
3207 //aopPut(AOP(result),"a",0);
3209 } else { // (size > 1)
3211 pic14_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s",
3212 aopGet(AOP(right),0,FALSE,FALSE),
3213 aopGet(AOP(left),0,FALSE,FALSE),
3214 aopGet(AOP(result),0,FALSE,FALSE));
3216 if (SPEC_USIGN(opetype)){
3217 pic14_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3218 genUMult8X8_16 (left, right, result, NULL);
3221 /* for filling the MSBs */
3222 emitpcode(POC_CLRF, popGet(AOP(result),2));
3223 emitpcode(POC_CLRF, popGet(AOP(result),3));
3227 pic14_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3229 pic14_emitcode("mov","a,b");
3231 /* adjust the MSB if left or right neg */
3233 /* if one literal */
3234 if (AOP_TYPE(right) == AOP_LIT){
3235 pic14_emitcode("multiply ","right is a lit");
3236 /* AND literal negative */
3237 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3238 /* adjust MSB (c==0 after mul) */
3239 pic14_emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3243 genSMult8X8_16 (left, right, result, NULL);
3247 pic14_emitcode("multiply ","size is greater than 2, so propogate sign");
3249 pic14_emitcode("rlc","a");
3250 pic14_emitcode("subb","a,acc");
3258 pic14_emitcode("multiply ","size is way greater than 2, so propogate sign");
3259 //aopPut(AOP(result),"a",offset++);
3263 /*-----------------------------------------------------------------*/
3264 /* genMult - generates code for multiplication */
3265 /*-----------------------------------------------------------------*/
3266 static void genMult (iCode *ic)
3268 operand *left = IC_LEFT(ic);
3269 operand *right = IC_RIGHT(ic);
3270 operand *result= IC_RESULT(ic);
3274 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3275 /* assign the amsops */
3276 aopOp (left,ic,FALSE);
3277 aopOp (right,ic,FALSE);
3278 aopOp (result,ic,TRUE);
3280 DEBUGpic14_AopType(__LINE__,left,right,result);
3282 /* special cases first */
3284 if (AOP_TYPE(left) == AOP_CRY &&
3285 AOP_TYPE(right)== AOP_CRY) {
3286 genMultbits(left,right,result);
3290 /* if both are of size == 1 */
3291 if (AOP_SIZE(left) == 1 &&
3292 AOP_SIZE(right) == 1 ) {
3293 genMultOneByte(left,right,result);
3297 pic14_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3299 /* should have been converted to function call */
3303 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3304 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3305 freeAsmop(result,NULL,ic,TRUE);
3308 /*-----------------------------------------------------------------*/
3309 /* genDivbits :- division of bits */
3310 /*-----------------------------------------------------------------*/
3311 static void genDivbits (operand *left,
3320 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3321 /* the result must be bit */
3322 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3323 l = aopGet(AOP(left),0,FALSE,FALSE);
3327 pic14_emitcode("div","ab");
3328 pic14_emitcode("rrc","a");
3329 aopPut(AOP(result),"c",0);
3332 /*-----------------------------------------------------------------*/
3333 /* genDivOneByte : 8 bit division */
3334 /*-----------------------------------------------------------------*/
3335 static void genDivOneByte (operand *left,
3339 sym_link *opetype = operandType(result);
3345 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3346 size = AOP_SIZE(result) - 1;
3348 /* signed or unsigned */
3349 if (SPEC_USIGN(opetype)) {
3350 /* unsigned is easy */
3351 pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3352 l = aopGet(AOP(left),0,FALSE,FALSE);
3354 pic14_emitcode("div","ab");
3355 aopPut(AOP(result),"a",0);
3357 aopPut(AOP(result),zero,offset++);
3361 /* signed is a little bit more difficult */
3363 /* save the signs of the operands */
3364 l = aopGet(AOP(left),0,FALSE,FALSE);
3366 pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3367 pic14_emitcode("push","acc"); /* save it on the stack */
3369 /* now sign adjust for both left & right */
3370 l = aopGet(AOP(right),0,FALSE,FALSE);
3372 lbl = newiTempLabel(NULL);
3373 pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3374 pic14_emitcode("cpl","a");
3375 pic14_emitcode("inc","a");
3376 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3377 pic14_emitcode("mov","b,a");
3379 /* sign adjust left side */
3380 l = aopGet(AOP(left),0,FALSE,FALSE);
3383 lbl = newiTempLabel(NULL);
3384 pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3385 pic14_emitcode("cpl","a");
3386 pic14_emitcode("inc","a");
3387 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3389 /* now the division */
3390 pic14_emitcode("div","ab");
3391 /* we are interested in the lower order
3393 pic14_emitcode("mov","b,a");
3394 lbl = newiTempLabel(NULL);
3395 pic14_emitcode("pop","acc");
3396 /* if there was an over flow we don't
3397 adjust the sign of the result */
3398 pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3399 pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3401 pic14_emitcode("clr","a");
3402 pic14_emitcode("subb","a,b");
3403 pic14_emitcode("mov","b,a");
3404 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3406 /* now we are done */
3407 aopPut(AOP(result),"b",0);
3409 pic14_emitcode("mov","c,b.7");
3410 pic14_emitcode("subb","a,acc");
3413 aopPut(AOP(result),"a",offset++);
3417 /*-----------------------------------------------------------------*/
3418 /* genDiv - generates code for division */
3419 /*-----------------------------------------------------------------*/
3420 static void genDiv (iCode *ic)
3422 operand *left = IC_LEFT(ic);
3423 operand *right = IC_RIGHT(ic);
3424 operand *result= IC_RESULT(ic);
3427 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3428 /* assign the amsops */
3429 aopOp (left,ic,FALSE);
3430 aopOp (right,ic,FALSE);
3431 aopOp (result,ic,TRUE);
3433 /* special cases first */
3435 if (AOP_TYPE(left) == AOP_CRY &&
3436 AOP_TYPE(right)== AOP_CRY) {
3437 genDivbits(left,right,result);
3441 /* if both are of size == 1 */
3442 if (AOP_SIZE(left) == 1 &&
3443 AOP_SIZE(right) == 1 ) {
3444 genDivOneByte(left,right,result);
3448 /* should have been converted to function call */
3451 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3452 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3453 freeAsmop(result,NULL,ic,TRUE);
3456 /*-----------------------------------------------------------------*/
3457 /* genModbits :- modulus of bits */
3458 /*-----------------------------------------------------------------*/
3459 static void genModbits (operand *left,
3467 /* the result must be bit */
3468 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3469 l = aopGet(AOP(left),0,FALSE,FALSE);
3473 pic14_emitcode("div","ab");
3474 pic14_emitcode("mov","a,b");
3475 pic14_emitcode("rrc","a");
3476 aopPut(AOP(result),"c",0);
3479 /*-----------------------------------------------------------------*/
3480 /* genModOneByte : 8 bit modulus */
3481 /*-----------------------------------------------------------------*/
3482 static void genModOneByte (operand *left,
3486 sym_link *opetype = operandType(result);
3491 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3492 /* signed or unsigned */
3493 if (SPEC_USIGN(opetype)) {
3494 /* unsigned is easy */
3495 pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3496 l = aopGet(AOP(left),0,FALSE,FALSE);
3498 pic14_emitcode("div","ab");
3499 aopPut(AOP(result),"b",0);
3503 /* signed is a little bit more difficult */
3505 /* save the signs of the operands */
3506 l = aopGet(AOP(left),0,FALSE,FALSE);
3509 pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3510 pic14_emitcode("push","acc"); /* save it on the stack */
3512 /* now sign adjust for both left & right */
3513 l = aopGet(AOP(right),0,FALSE,FALSE);
3516 lbl = newiTempLabel(NULL);
3517 pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3518 pic14_emitcode("cpl","a");
3519 pic14_emitcode("inc","a");
3520 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3521 pic14_emitcode("mov","b,a");
3523 /* sign adjust left side */
3524 l = aopGet(AOP(left),0,FALSE,FALSE);
3527 lbl = newiTempLabel(NULL);
3528 pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3529 pic14_emitcode("cpl","a");
3530 pic14_emitcode("inc","a");
3531 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3533 /* now the multiplication */
3534 pic14_emitcode("div","ab");
3535 /* we are interested in the lower order
3537 lbl = newiTempLabel(NULL);
3538 pic14_emitcode("pop","acc");
3539 /* if there was an over flow we don't
3540 adjust the sign of the result */
3541 pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3542 pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3544 pic14_emitcode("clr","a");
3545 pic14_emitcode("subb","a,b");
3546 pic14_emitcode("mov","b,a");
3547 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3549 /* now we are done */
3550 aopPut(AOP(result),"b",0);
3554 /*-----------------------------------------------------------------*/
3555 /* genMod - generates code for division */
3556 /*-----------------------------------------------------------------*/
3557 static void genMod (iCode *ic)
3559 operand *left = IC_LEFT(ic);
3560 operand *right = IC_RIGHT(ic);
3561 operand *result= IC_RESULT(ic);
3564 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3565 /* assign the amsops */
3566 aopOp (left,ic,FALSE);
3567 aopOp (right,ic,FALSE);
3568 aopOp (result,ic,TRUE);
3570 /* special cases first */
3572 if (AOP_TYPE(left) == AOP_CRY &&
3573 AOP_TYPE(right)== AOP_CRY) {
3574 genModbits(left,right,result);
3578 /* if both are of size == 1 */
3579 if (AOP_SIZE(left) == 1 &&
3580 AOP_SIZE(right) == 1 ) {
3581 genModOneByte(left,right,result);
3585 /* should have been converted to function call */
3589 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3590 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3591 freeAsmop(result,NULL,ic,TRUE);
3594 /*-----------------------------------------------------------------*/
3595 /* genIfxJump :- will create a jump depending on the ifx */
3596 /*-----------------------------------------------------------------*/
3598 note: May need to add parameter to indicate when a variable is in bit space.
3600 static void genIfxJump (iCode *ic, char *jval)
3604 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3605 /* if true label then we jump if condition
3607 if ( IC_TRUE(ic) ) {
3609 if(strcmp(jval,"a") == 0)
3611 else if (strcmp(jval,"c") == 0)
3614 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3615 emitpcode(POC_BTFSC, newpCodeOpBit(jval,-1,1));
3618 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3619 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3623 /* false label is present */
3624 if(strcmp(jval,"a") == 0)
3626 else if (strcmp(jval,"c") == 0)
3629 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3630 emitpcode(POC_BTFSS, newpCodeOpBit(jval,-1,1));
3633 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3634 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3639 /* mark the icode as generated */
3643 /*-----------------------------------------------------------------*/
3645 /*-----------------------------------------------------------------*/
3646 static void genSkip(iCode *ifx,int status_bit)
3652 if ( IC_TRUE(ifx) ) {
3653 switch(status_bit) {
3668 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3669 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3673 switch(status_bit) {
3687 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3688 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3694 /*-----------------------------------------------------------------*/
3696 /*-----------------------------------------------------------------*/
3697 static void genSkipc(resolvedIfx *rifx)
3708 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3709 rifx->generated = 1;
3712 /*-----------------------------------------------------------------*/
3714 /*-----------------------------------------------------------------*/
3715 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3721 if( (rifx->condition ^ invert_condition) & 1)
3726 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3727 rifx->generated = 1;
3730 /*-----------------------------------------------------------------*/
3732 /*-----------------------------------------------------------------*/
3733 static void genSkipz(iCode *ifx, int condition)
3745 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3747 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3750 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3752 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3755 /*-----------------------------------------------------------------*/
3757 /*-----------------------------------------------------------------*/
3758 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3765 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3767 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3770 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3771 rifx->generated = 1;
3775 /*-----------------------------------------------------------------*/
3776 /* genChkZeroes :- greater or less than comparison */
3777 /* For each byte in a literal that is zero, inclusive or the */
3778 /* the corresponding byte in the operand with W */
3779 /* returns true if any of the bytes are zero */
3780 /*-----------------------------------------------------------------*/
3781 static int genChkZeroes(operand *op, int lit, int size)
3788 i = (lit >> (size*8)) & 0xff;
3792 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3794 emitpcode(POC_IORFW, popGet(AOP(op),size));
3803 /*-----------------------------------------------------------------*/
3804 /* genCmp :- greater or less than comparison */
3805 /*-----------------------------------------------------------------*/
3806 static void genCmp (operand *left,operand *right,
3807 operand *result, iCode *ifx, int sign)
3809 int size; //, offset = 0 ;
3810 unsigned long lit = 0L,i = 0;
3811 resolvedIfx rFalseIfx;
3812 // resolvedIfx rTrueIfx;
3816 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3819 DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
3820 DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
3824 resolveIfx(&rFalseIfx,ifx);
3825 truelbl = newiTempLabel(NULL);
3826 size = max(AOP_SIZE(left),AOP_SIZE(right));
3828 DEBUGpic14_AopType(__LINE__,left,right,result);
3832 /* if literal is on the right then swap with left */
3833 if ((AOP_TYPE(right) == AOP_LIT)) {
3834 operand *tmp = right ;
3835 unsigned long mask = (0x100 << (8*(size-1))) - 1;
3836 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3839 lit = (lit - 1) & mask;
3842 rFalseIfx.condition ^= 1;
3845 } else if ((AOP_TYPE(left) == AOP_LIT)) {
3846 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3850 //if(IC_TRUE(ifx) == NULL)
3851 /* if left & right are bit variables */
3852 if (AOP_TYPE(left) == AOP_CRY &&
3853 AOP_TYPE(right) == AOP_CRY ) {
3854 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3855 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3857 /* subtract right from left if at the
3858 end the carry flag is set then we know that
3859 left is greater than right */
3861 symbol *lbl = newiTempLabel(NULL);
3864 if(AOP_TYPE(right) == AOP_LIT) {
3866 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3868 DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
3875 genSkipCond(&rFalseIfx,left,size-1,7);
3877 /* no need to compare to 0...*/
3878 /* NOTE: this is a de-generate compare that most certainly
3879 * creates some dead code. */
3880 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3882 if(ifx) ifx->generated = 1;
3889 //i = (lit >> (size*8)) & 0xff;
3890 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3892 emitpcode(POC_MOVFW, popGet(AOP(left),size));
3894 i = ((0-lit) & 0xff);
3897 /* lit is 0x7f, all signed chars are less than
3898 * this except for 0x7f itself */
3899 emitpcode(POC_XORLW, popGetLit(0x7f));
3900 genSkipz2(&rFalseIfx,0);
3902 emitpcode(POC_ADDLW, popGetLit(0x80));
3903 emitpcode(POC_ADDLW, popGetLit(i^0x80));
3904 genSkipc(&rFalseIfx);
3909 genSkipz2(&rFalseIfx,1);
3911 emitpcode(POC_ADDLW, popGetLit(i));
3912 genSkipc(&rFalseIfx);
3916 if(ifx) ifx->generated = 1;
3920 /* chars are out of the way. now do ints and longs */
3923 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3930 genSkipCond(&rFalseIfx,left,size,7);
3931 if(ifx) ifx->generated = 1;
3936 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3938 //rFalseIfx.condition ^= 1;
3939 //genSkipCond(&rFalseIfx,left,size,7);
3940 //rFalseIfx.condition ^= 1;
3942 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3943 if(rFalseIfx.condition)
3944 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
3946 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
3948 emitpcode(POC_MOVLW, popGetLit(0x100-lit));
3949 emitpcode(POC_ADDFW, popGet(AOP(left),0));
3950 emitpcode(POC_MOVFW, popGet(AOP(left),1));
3953 emitpcode(POC_IORFW, popGet(AOP(left),size--));
3955 if(rFalseIfx.condition) {
3957 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
3963 genSkipc(&rFalseIfx);
3964 emitpLabel(truelbl->key);
3965 if(ifx) ifx->generated = 1;
3972 if( (lit & 0xff) == 0) {
3973 /* lower byte is zero */
3974 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3975 i = ((lit >> 8) & 0xff) ^0x80;
3976 emitpcode(POC_MOVFW, popGet(AOP(left),size));
3977 emitpcode(POC_ADDLW, popGetLit( 0x80));
3978 emitpcode(POC_ADDLW, popGetLit(0x100-i));
3979 genSkipc(&rFalseIfx);
3982 if(ifx) ifx->generated = 1;
3987 /* Special cases for signed longs */
3988 if( (lit & 0xffffff) == 0) {
3989 /* lower byte is zero */
3990 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3991 i = ((lit >> 8*3) & 0xff) ^0x80;
3992 emitpcode(POC_MOVFW, popGet(AOP(left),size));
3993 emitpcode(POC_ADDLW, popGetLit( 0x80));
3994 emitpcode(POC_ADDLW, popGetLit(0x100-i));
3995 genSkipc(&rFalseIfx);
3998 if(ifx) ifx->generated = 1;
4006 if(lit & (0x80 << (size*8))) {
4007 /* lit is negative */
4008 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4010 //genSkipCond(&rFalseIfx,left,size,7);
4012 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4014 if(rFalseIfx.condition)
4015 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4017 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4021 /* lit is positive */
4022 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4023 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4024 if(rFalseIfx.condition)
4025 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4027 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4031 /* There are no more special cases, so perform a general compare */
4033 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4034 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4038 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4040 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4042 //rFalseIfx.condition ^= 1;
4043 genSkipc(&rFalseIfx);
4045 emitpLabel(truelbl->key);
4047 if(ifx) ifx->generated = 1;
4054 /* sign is out of the way. So now do an unsigned compare */
4055 DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4058 /* General case - compare to an unsigned literal on the right.*/
4060 i = (lit >> (size*8)) & 0xff;
4061 emitpcode(POC_MOVLW, popGetLit(i));
4062 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4064 i = (lit >> (size*8)) & 0xff;
4067 emitpcode(POC_MOVLW, popGetLit(i));
4069 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4071 /* this byte of the lit is zero,
4072 *if it's not the last then OR in the variable */
4074 emitpcode(POC_IORFW, popGet(AOP(left),size));
4079 emitpLabel(lbl->key);
4080 //if(emitFinalCheck)
4081 genSkipc(&rFalseIfx);
4083 emitpLabel(truelbl->key);
4085 if(ifx) ifx->generated = 1;
4092 if(AOP_TYPE(left) == AOP_LIT) {
4093 //symbol *lbl = newiTempLabel(NULL);
4095 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4098 DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4101 if((lit == 0) && (sign == 0)){
4104 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4106 emitpcode(POC_IORFW, popGet(AOP(right),--size));
4108 genSkipz2(&rFalseIfx,0);
4109 if(ifx) ifx->generated = 1;
4116 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4117 /* degenerate compare can never be true */
4118 if(rFalseIfx.condition == 0)
4119 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4121 if(ifx) ifx->generated = 1;
4126 /* signed comparisons to a literal byte */
4128 int lp1 = (lit+1) & 0xff;
4130 DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4133 rFalseIfx.condition ^= 1;
4134 genSkipCond(&rFalseIfx,right,0,7);
4137 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4138 emitpcode(POC_XORLW, popGetLit(0x7f));
4139 genSkipz2(&rFalseIfx,1);
4142 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4143 emitpcode(POC_ADDLW, popGetLit(0x80));
4144 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4145 rFalseIfx.condition ^= 1;
4146 genSkipc(&rFalseIfx);
4149 if(ifx) ifx->generated = 1;
4151 /* unsigned comparisons to a literal byte */
4153 switch(lit & 0xff ) {
4155 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4156 genSkipz2(&rFalseIfx,0);
4157 if(ifx) ifx->generated = 1;
4160 genSkipCond(&rFalseIfx,right,0,7);
4161 if(ifx) ifx->generated = 1;
4165 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4166 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4167 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4168 rFalseIfx.condition ^= 1;
4169 if (AOP_TYPE(result) == AOP_CRY) {
4170 genSkipc(&rFalseIfx);
4171 if(ifx) ifx->generated = 1;
4173 DEBUGpic14_emitcode ("; ***","%s %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4174 emitpcode(POC_CLRF, popGet(AOP(result),0));
4175 emitpcode(POC_RLF, popGet(AOP(result),0));
4176 emitpcode(POC_MOVLW, popGetLit(0x01));
4177 emitpcode(POC_XORWF, popGet(AOP(result),0));
4188 /* Size is greater than 1 */
4196 /* this means lit = 0xffffffff, or -1 */
4199 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4200 rFalseIfx.condition ^= 1;
4201 genSkipCond(&rFalseIfx,right,size,7);
4202 if(ifx) ifx->generated = 1;
4209 if(rFalseIfx.condition) {
4210 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4211 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4214 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4216 emitpcode(POC_IORFW, popGet(AOP(right),size));
4220 if(rFalseIfx.condition) {
4221 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4222 emitpLabel(truelbl->key);
4224 rFalseIfx.condition ^= 1;
4225 genSkipCond(&rFalseIfx,right,s,7);
4228 if(ifx) ifx->generated = 1;
4232 if((size == 1) && (0 == (lp1&0xff))) {
4233 /* lower byte of signed word is zero */
4234 DEBUGpic14_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
4235 i = ((lp1 >> 8) & 0xff) ^0x80;
4236 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4237 emitpcode(POC_ADDLW, popGetLit( 0x80));
4238 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4239 rFalseIfx.condition ^= 1;
4240 genSkipc(&rFalseIfx);
4243 if(ifx) ifx->generated = 1;
4247 if(lit & (0x80 << (size*8))) {
4248 /* Lit is less than zero */
4249 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
4250 //rFalseIfx.condition ^= 1;
4251 //genSkipCond(&rFalseIfx,left,size,7);
4252 //rFalseIfx.condition ^= 1;
4253 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4254 //emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4256 if(rFalseIfx.condition)
4257 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4259 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4263 /* Lit is greater than or equal to zero */
4264 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
4265 //rFalseIfx.condition ^= 1;
4266 //genSkipCond(&rFalseIfx,right,size,7);
4267 //rFalseIfx.condition ^= 1;
4269 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4270 //emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4272 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4273 if(rFalseIfx.condition)
4274 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4276 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4281 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4282 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4286 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4288 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4290 rFalseIfx.condition ^= 1;
4291 //rFalseIfx.condition = 1;
4292 genSkipc(&rFalseIfx);
4294 emitpLabel(truelbl->key);
4296 if(ifx) ifx->generated = 1;
4301 /* compare word or long to an unsigned literal on the right.*/
4306 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4309 break; /* handled above */
4312 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4314 emitpcode(POC_IORFW, popGet(AOP(right),size));
4315 genSkipz2(&rFalseIfx,0);
4319 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4321 emitpcode(POC_IORFW, popGet(AOP(right),size));
4324 if(rFalseIfx.condition)
4325 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4327 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4330 emitpcode(POC_MOVLW, popGetLit(lit+1));
4331 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4333 rFalseIfx.condition ^= 1;
4334 genSkipc(&rFalseIfx);
4337 emitpLabel(truelbl->key);
4339 if(ifx) ifx->generated = 1;
4345 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4346 i = (lit >> (size*8)) & 0xff;
4348 emitpcode(POC_MOVLW, popGetLit(i));
4349 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4352 i = (lit >> (size*8)) & 0xff;
4355 emitpcode(POC_MOVLW, popGetLit(i));
4357 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4359 /* this byte of the lit is zero,
4360 *if it's not the last then OR in the variable */
4362 emitpcode(POC_IORFW, popGet(AOP(right),size));
4367 emitpLabel(lbl->key);
4369 rFalseIfx.condition ^= 1;
4370 genSkipc(&rFalseIfx);
4374 emitpLabel(truelbl->key);
4375 if(ifx) ifx->generated = 1;
4379 /* Compare two variables */
4381 DEBUGpic14_emitcode(";sign","%d",sign);
4385 /* Sigh. thus sucks... */
4387 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4388 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4389 emitpcode(POC_MOVLW, popGetLit(0x80));
4390 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4391 emitpcode(POC_XORFW, popGet(AOP(right),size));
4392 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4394 /* Signed char comparison */
4395 /* Special thanks to Nikolai Golovchenko for this snippet */
4396 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4397 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4398 emitpcode(POC_RRFW, popGet(AOP(left),0)); /* could be any register */
4399 emitpcode(POC_XORFW, popGet(AOP(left),0));
4400 emitpcode(POC_XORFW, popGet(AOP(right),0));
4401 emitpcode(POC_ADDLW, popGetLit(0x80));
4403 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4404 genSkipc(&rFalseIfx);
4406 if(ifx) ifx->generated = 1;
4412 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4413 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4417 /* The rest of the bytes of a multi-byte compare */
4421 emitpcode(POC_GOTO, popGetLabel(lbl->key));
4424 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4425 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4430 emitpLabel(lbl->key);
4432 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4433 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
4434 (AOP_TYPE(result) == AOP_REG)) {
4435 emitpcode(POC_CLRF, popGet(AOP(result),0));
4436 emitpcode(POC_RLF, popGet(AOP(result),0));
4438 genSkipc(&rFalseIfx);
4440 //genSkipc(&rFalseIfx);
4441 if(ifx) ifx->generated = 1;
4448 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4449 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4450 pic14_outBitC(result);
4452 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4453 /* if the result is used in the next
4454 ifx conditional branch then generate
4455 code a little differently */
4457 genIfxJump (ifx,"c");
4459 pic14_outBitC(result);
4460 /* leave the result in acc */
4465 /*-----------------------------------------------------------------*/
4466 /* genCmpGt :- greater than comparison */
4467 /*-----------------------------------------------------------------*/
4468 static void genCmpGt (iCode *ic, iCode *ifx)
4470 operand *left, *right, *result;
4471 sym_link *letype , *retype;
4475 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4477 right= IC_RIGHT(ic);
4478 result = IC_RESULT(ic);
4480 letype = getSpec(operandType(left));
4481 retype =getSpec(operandType(right));
4482 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4483 /* assign the amsops */
4484 aopOp (left,ic,FALSE);
4485 aopOp (right,ic,FALSE);
4486 aopOp (result,ic,TRUE);
4488 genCmp(right, left, result, ifx, sign);
4490 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4491 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4492 freeAsmop(result,NULL,ic,TRUE);
4495 /*-----------------------------------------------------------------*/
4496 /* genCmpLt - less than comparisons */
4497 /*-----------------------------------------------------------------*/
4498 static void genCmpLt (iCode *ic, iCode *ifx)
4500 operand *left, *right, *result;
4501 sym_link *letype , *retype;
4505 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4507 right= IC_RIGHT(ic);
4508 result = IC_RESULT(ic);
4510 letype = getSpec(operandType(left));
4511 retype =getSpec(operandType(right));
4512 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4514 /* assign the amsops */
4515 aopOp (left,ic,FALSE);
4516 aopOp (right,ic,FALSE);
4517 aopOp (result,ic,TRUE);
4519 genCmp(left, right, result, ifx, sign);
4521 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4522 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4523 freeAsmop(result,NULL,ic,TRUE);
4526 /*-----------------------------------------------------------------*/
4527 /* genc16bit2lit - compare a 16 bit value to a literal */
4528 /*-----------------------------------------------------------------*/
4529 static void genc16bit2lit(operand *op, int lit, int offset)
4534 DEBUGpic14_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
4535 if( (lit&0xff) == 0)
4540 switch( BYTEofLONG(lit,i)) {
4542 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4545 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4548 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4551 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4552 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4557 switch( BYTEofLONG(lit,i)) {
4559 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4563 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4567 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4570 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4572 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4578 /*-----------------------------------------------------------------*/
4579 /* gencjneshort - compare and jump if not equal */
4580 /*-----------------------------------------------------------------*/
4581 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4583 int size = max(AOP_SIZE(left),AOP_SIZE(right));
4585 int res_offset = 0; /* the result may be a different size then left or right */
4586 int res_size = AOP_SIZE(result);
4590 unsigned long lit = 0L;
4592 if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4593 emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4596 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4597 DEBUGpic14_AopType(__LINE__,left,right,result);
4599 DEBUGpic14_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
4600 resolveIfx(&rIfx,ifx);
4601 lbl = newiTempLabel(NULL);
4604 /* if the left side is a literal or
4605 if the right is in a pointer register and left
4607 if ((AOP_TYPE(left) == AOP_LIT) ||
4608 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4613 if(AOP_TYPE(right) == AOP_LIT)
4614 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4616 /* if the right side is a literal then anything goes */
4617 if (AOP_TYPE(right) == AOP_LIT &&
4618 AOP_TYPE(left) != AOP_DIR ) {
4621 genc16bit2lit(left, lit, 0);
4623 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4628 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4629 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4631 emitpcode(POC_MOVF,popGet(AOP(left),offset));
4635 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4637 if(res_offset < res_size-1)
4645 /* if the right side is in a register or in direct space or
4646 if the left is a pointer register & right is not */
4647 else if (AOP_TYPE(right) == AOP_REG ||
4648 AOP_TYPE(right) == AOP_DIR ||
4649 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4650 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4651 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4652 int lbl_key = lbl->key;
4655 if (AOP_TYPE(result) != AOP_CRY)
4656 emitpcode(POC_CLRF,popGet(AOP(result),res_offset));
4657 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4659 DEBUGpic14_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
4660 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
4661 __FUNCTION__,__LINE__);
4665 /* switch(size) { */
4667 /* genc16bit2lit(left, lit, 0); */
4669 /* emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
4674 if((AOP_TYPE(left) == AOP_DIR) &&
4675 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4677 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4678 emitpcode(POC_XORFW,popGet(AOP(right),offset));
4680 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4682 switch (lit & 0xff) {
4684 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4687 emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4688 emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4689 //emitpcode(POC_GOTO,popGetLabel(lbl->key));
4693 emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4694 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4695 //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4696 emitpcode(POC_GOTO,popGetLabel(lbl_key));
4700 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4701 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4706 emitpcode(POC_MOVF,popGet(AOP(left),offset));
4709 if(AOP_TYPE(result) == AOP_CRY) {
4710 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
4715 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4717 /* fix me. probably need to check result size too */
4718 //emitpcode(POC_CLRF,popGet(AOP(result),0));
4723 emitpcode(POC_GOTO,popGetLabel(lbl_key));
4724 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4731 if(res_offset < res_size-1)
4736 } else if(AOP_TYPE(right) == AOP_REG &&
4737 AOP_TYPE(left) != AOP_DIR){
4740 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4741 emitpcode(POC_XORFW,popGet(AOP(right),offset));
4742 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
4747 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4749 if(res_offset < res_size-1)
4754 /* right is a pointer reg need both a & b */
4756 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4758 pic14_emitcode("mov","b,%s",l);
4759 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4760 pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
4765 emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4767 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4769 emitpLabel(lbl->key);
4771 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4778 /*-----------------------------------------------------------------*/
4779 /* gencjne - compare and jump if not equal */
4780 /*-----------------------------------------------------------------*/
4781 static void gencjne(operand *left, operand *right, iCode *ifx)
4783 symbol *tlbl = newiTempLabel(NULL);
4785 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4786 gencjneshort(left, right, lbl);
4788 pic14_emitcode("mov","a,%s",one);
4789 pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
4790 pic14_emitcode("","%05d_DS_:",lbl->key+100);
4791 pic14_emitcode("clr","a");
4792 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4794 emitpLabel(lbl->key);
4795 emitpLabel(tlbl->key);
4800 /*-----------------------------------------------------------------*/
4801 /* genCmpEq - generates code for equal to */
4802 /*-----------------------------------------------------------------*/
4803 static void genCmpEq (iCode *ic, iCode *ifx)
4805 operand *left, *right, *result;
4806 unsigned long lit = 0L;
4810 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4813 DEBUGpic14_emitcode ("; ifx is non-null","");
4815 DEBUGpic14_emitcode ("; ifx is null","");
4817 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4818 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4819 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4821 size = max(AOP_SIZE(left),AOP_SIZE(right));
4823 DEBUGpic14_AopType(__LINE__,left,right,result);
4825 /* if literal, literal on the right or
4826 if the right is in a pointer register and left
4828 if (aop_isLitLike (AOP(IC_LEFT(ic)))
4829 || (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4830 operand *tmp = right ;
4836 if(ifx && !AOP_SIZE(result)){
4838 /* if they are both bit variables */
4839 if (AOP_TYPE(left) == AOP_CRY &&
4840 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4841 if(AOP_TYPE(right) == AOP_LIT){
4842 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4844 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4845 pic14_emitcode("cpl","c");
4846 } else if(lit == 1L) {
4847 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4849 pic14_emitcode("clr","c");
4851 /* AOP_TYPE(right) == AOP_CRY */
4853 symbol *lbl = newiTempLabel(NULL);
4854 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4855 pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4856 pic14_emitcode("cpl","c");
4857 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4859 /* if true label then we jump if condition
4861 tlbl = newiTempLabel(NULL);
4862 if ( IC_TRUE(ifx) ) {
4863 pic14_emitcode("jnc","%05d_DS_",tlbl->key+100);
4864 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4866 pic14_emitcode("jc","%05d_DS_",tlbl->key+100);
4867 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4869 pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4872 /* left and right are both bit variables, result is carry */
4875 resolveIfx(&rIfx,ifx);
4877 emitpcode(POC_MOVLW,popGet(AOP(left),0));
4878 emitpcode(POC_ANDFW,popGet(AOP(left),0));
4879 emitpcode(POC_BTFSC,popGet(AOP(right),0));
4880 emitpcode(POC_ANDLW,popGet(AOP(left),0));
4885 /* They're not both bit variables. Is the right a literal? */
4886 if(AOP_TYPE(right) == AOP_LIT) {
4887 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4892 switch(lit & 0xff) {
4894 if ( IC_TRUE(ifx) ) {
4895 emitpcode(POC_DECFW,popGet(AOP(left),offset));
4897 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4899 emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4900 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4904 if ( IC_TRUE(ifx) ) {
4905 emitpcode(POC_INCFW,popGet(AOP(left),offset));
4907 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4909 emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4910 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4914 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4916 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4921 /* end of size == 1 */
4925 genc16bit2lit(left,lit,offset);
4928 /* end of size == 2 */
4933 emitpcode(POC_MOVFW,popGet(AOP(left),0));
4934 emitpcode(POC_IORFW,popGet(AOP(left),1));
4935 emitpcode(POC_IORFW,popGet(AOP(left),2));
4936 emitpcode(POC_IORFW,popGet(AOP(left),3));
4940 /* search for patterns that can be optimized */
4942 genc16bit2lit(left,lit,0);
4945 genSkipz(ifx,IC_TRUE(ifx) == NULL);
4947 genc16bit2lit(left,lit,2);
4949 emitpcode(POC_IORFW,popGet(AOP(left),2));
4950 emitpcode(POC_IORFW,popGet(AOP(left),3));
4963 } else if(AOP_TYPE(right) == AOP_CRY ) {
4964 /* we know the left is not a bit, but that the right is */
4965 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4966 emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4967 popGet(AOP(right),offset));
4968 emitpcode(POC_XORLW,popGetLit(1));
4970 /* if the two are equal, then W will be 0 and the Z bit is set
4971 * we could test Z now, or go ahead and check the high order bytes if
4972 * the variable we're comparing is larger than a byte. */
4975 emitpcode(POC_IORFW,popGet(AOP(left),offset));
4977 if ( IC_TRUE(ifx) ) {
4979 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4980 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4983 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4984 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4988 /* They're both variables that are larger than bits */
4991 tlbl = newiTempLabel(NULL);
4994 mov2w (AOP(right),offset); /* right might be litLike() */
4995 emitpcode(POC_XORFW,popGet(AOP(left),offset));
4997 if ( IC_TRUE(ifx) ) {
5000 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
5001 pic14_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
5004 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5005 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5009 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
5010 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5014 if(s>1 && IC_TRUE(ifx)) {
5015 emitpLabel(tlbl->key);
5016 pic14_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);
5020 /* mark the icode as generated */
5025 /* if they are both bit variables */
5026 if (AOP_TYPE(left) == AOP_CRY &&
5027 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5028 if(AOP_TYPE(right) == AOP_LIT){
5029 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5031 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5032 pic14_emitcode("cpl","c");
5033 } else if(lit == 1L) {
5034 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5036 pic14_emitcode("clr","c");
5038 /* AOP_TYPE(right) == AOP_CRY */
5040 symbol *lbl = newiTempLabel(NULL);
5041 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5042 pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5043 pic14_emitcode("cpl","c");
5044 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
5047 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5048 pic14_outBitC(result);
5052 genIfxJump (ifx,"c");
5055 /* if the result is used in an arithmetic operation
5056 then put the result in place */
5057 pic14_outBitC(result);
5060 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5061 gencjne(left,right,result,ifx);
5064 gencjne(left,right,newiTempLabel(NULL));
5066 if(IC_TRUE(ifx)->key)
5067 gencjne(left,right,IC_TRUE(ifx)->key);
5069 gencjne(left,right,IC_FALSE(ifx)->key);
5073 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5074 aopPut(AOP(result),"a",0);
5079 genIfxJump (ifx,"a");
5083 /* if the result is used in an arithmetic operation
5084 then put the result in place */
5086 if (AOP_TYPE(result) != AOP_CRY)
5087 pic14_outAcc(result);
5089 /* leave the result in acc */
5093 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5094 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5095 freeAsmop(result,NULL,ic,TRUE);
5098 /*-----------------------------------------------------------------*/
5099 /* ifxForOp - returns the icode containing the ifx for operand */
5100 /*-----------------------------------------------------------------*/
5101 static iCode *ifxForOp ( operand *op, iCode *ic )
5104 /* if true symbol then needs to be assigned */
5105 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5106 if (IS_TRUE_SYMOP(op))
5109 /* if this has register type condition and
5110 the next instruction is ifx with the same operand
5111 and live to of the operand is upto the ifx only then */
5113 ic->next->op == IFX &&
5114 IC_COND(ic->next)->key == op->key &&
5115 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5119 ic->next->op == IFX &&
5120 IC_COND(ic->next)->key == op->key) {
5121 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5125 DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5127 ic->next->op == IFX)
5128 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5131 ic->next->op == IFX &&
5132 IC_COND(ic->next)->key == op->key) {
5133 DEBUGpic14_emitcode ("; "," key is okay");
5134 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5135 OP_SYMBOL(op)->liveTo,
5142 /*-----------------------------------------------------------------*/
5143 /* genAndOp - for && operation */
5144 /*-----------------------------------------------------------------*/
5145 static void genAndOp (iCode *ic)
5147 operand *left,*right, *result;
5151 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5152 /* note here that && operations that are in an
5153 if statement are taken away by backPatchLabels
5154 only those used in arthmetic operations remain */
5155 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5156 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5157 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5159 DEBUGpic14_AopType(__LINE__,left,right,result);
5161 emitpcode(POC_MOVFW,popGet(AOP(left),0));
5162 emitpcode(POC_ANDFW,popGet(AOP(right),0));
5163 emitpcode(POC_MOVWF,popGet(AOP(result),0));
5165 /* if both are bit variables */
5166 /* if (AOP_TYPE(left) == AOP_CRY && */
5167 /* AOP_TYPE(right) == AOP_CRY ) { */
5168 /* pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5169 /* pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5170 /* pic14_outBitC(result); */
5172 /* tlbl = newiTempLabel(NULL); */
5173 /* pic14_toBoolean(left); */
5174 /* pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5175 /* pic14_toBoolean(right); */
5176 /* pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5177 /* pic14_outBitAcc(result); */
5180 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5181 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5182 freeAsmop(result,NULL,ic,TRUE);
5186 /*-----------------------------------------------------------------*/
5187 /* genOrOp - for || operation */
5188 /*-----------------------------------------------------------------*/
5191 modified this code, but it doesn't appear to ever get called
5194 static void genOrOp (iCode *ic)
5196 operand *left,*right, *result;
5199 /* note here that || operations that are in an
5200 if statement are taken away by backPatchLabels
5201 only those used in arthmetic operations remain */
5203 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5204 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5205 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5206 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5208 DEBUGpic14_AopType(__LINE__,left,right,result);
5210 /* if both are bit variables */
5211 if (AOP_TYPE(left) == AOP_CRY &&
5212 AOP_TYPE(right) == AOP_CRY ) {
5213 pic14_emitcode("clrc","");
5214 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5215 AOP(left)->aopu.aop_dir,
5216 AOP(left)->aopu.aop_dir);
5217 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5218 AOP(right)->aopu.aop_dir,
5219 AOP(right)->aopu.aop_dir);
5220 pic14_emitcode("setc","");
5223 tlbl = newiTempLabel(NULL);
5224 pic14_toBoolean(left);
5226 pic14_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5227 pic14_toBoolean(right);
5228 pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5230 pic14_outBitAcc(result);
5233 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5234 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5235 freeAsmop(result,NULL,ic,TRUE);
5238 /*-----------------------------------------------------------------*/
5239 /* isLiteralBit - test if lit == 2^n */
5240 /*-----------------------------------------------------------------*/
5241 static int isLiteralBit(unsigned long lit)
5243 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5244 0x100L,0x200L,0x400L,0x800L,
5245 0x1000L,0x2000L,0x4000L,0x8000L,
5246 0x10000L,0x20000L,0x40000L,0x80000L,
5247 0x100000L,0x200000L,0x400000L,0x800000L,
5248 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5249 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5253 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5254 for(idx = 0; idx < 32; idx++)
5260 /*-----------------------------------------------------------------*/
5261 /* continueIfTrue - */
5262 /*-----------------------------------------------------------------*/
5263 static void continueIfTrue (iCode *ic)
5266 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5268 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5272 /*-----------------------------------------------------------------*/
5274 /*-----------------------------------------------------------------*/
5275 static void jumpIfTrue (iCode *ic)
5278 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5280 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5284 /*-----------------------------------------------------------------*/
5285 /* jmpTrueOrFalse - */
5286 /*-----------------------------------------------------------------*/
5287 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5290 // ugly but optimized by peephole
5291 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5293 symbol *nlbl = newiTempLabel(NULL);
5294 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5295 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5296 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5297 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5300 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5301 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5306 /*-----------------------------------------------------------------*/
5307 /* genAnd - code for and */
5308 /*-----------------------------------------------------------------*/
5309 static void genAnd (iCode *ic, iCode *ifx)
5311 operand *left, *right, *result;
5313 unsigned long lit = 0L;
5318 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5319 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5320 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5321 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5323 resolveIfx(&rIfx,ifx);
5325 /* if left is a literal & right is not then exchange them */
5326 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5327 AOP_NEEDSACC(left)) {
5328 operand *tmp = right ;
5333 /* if result = right then exchange them */
5334 if(pic14_sameRegs(AOP(result),AOP(right))){
5335 operand *tmp = right ;
5340 /* if right is bit then exchange them */
5341 if (AOP_TYPE(right) == AOP_CRY &&
5342 AOP_TYPE(left) != AOP_CRY){
5343 operand *tmp = right ;
5347 if(AOP_TYPE(right) == AOP_LIT)
5348 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5350 size = AOP_SIZE(result);
5352 DEBUGpic14_AopType(__LINE__,left,right,result);
5355 // result = bit & yy;
5356 if (AOP_TYPE(left) == AOP_CRY){
5357 // c = bit & literal;
5358 if(AOP_TYPE(right) == AOP_LIT){
5360 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5363 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5366 if(size && (AOP_TYPE(result) == AOP_CRY)){
5367 pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5370 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5374 pic14_emitcode("clr","c");
5377 if (AOP_TYPE(right) == AOP_CRY){
5379 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5380 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5383 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5385 pic14_emitcode("rrc","a");
5386 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5392 pic14_outBitC(result);
5394 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5395 genIfxJump(ifx, "c");
5399 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5400 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5401 if((AOP_TYPE(right) == AOP_LIT) &&
5402 (AOP_TYPE(result) == AOP_CRY) &&
5403 (AOP_TYPE(left) != AOP_CRY)){
5404 int posbit = isLiteralBit(lit);
5408 //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5411 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5416 while (posbit > 7) {
5420 emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5421 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5422 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5429 symbol *tlbl = newiTempLabel(NULL);
5430 int sizel = AOP_SIZE(left);
5432 pic14_emitcode("setb","c");
5434 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5435 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5437 if((posbit = isLiteralBit(bytelit)) != 0)
5438 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5440 if(bytelit != 0x0FFL)
5441 pic14_emitcode("anl","a,%s",
5442 aopGet(AOP(right),offset,FALSE,TRUE));
5443 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5448 // bit = left & literal
5450 pic14_emitcode("clr","c");
5451 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5453 // if(left & literal)
5456 jmpTrueOrFalse(ifx, tlbl);
5460 pic14_outBitC(result);
5464 /* if left is same as result */
5465 if(pic14_sameRegs(AOP(result),AOP(left))){
5467 for(;size--; offset++,lit>>=8) {
5468 if(AOP_TYPE(right) == AOP_LIT){
5469 switch(lit & 0xff) {
5471 /* and'ing with 0 has clears the result */
5472 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5475 /* and'ing with 0xff is a nop when the result and left are the same */
5480 int p = my_powof2( (~lit) & 0xff );
5482 /* only one bit is set in the literal, so use a bcf instruction */
5483 emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5486 if(know_W != (int)(lit&0xff))
5487 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5489 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5494 if (AOP_TYPE(left) == AOP_ACC) {
5495 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5497 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5498 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5505 // left & result in different registers
5506 if(AOP_TYPE(result) == AOP_CRY){
5508 // if(size), result in bit
5509 // if(!size && ifx), conditional oper: if(left & right)
5510 symbol *tlbl = newiTempLabel(NULL);
5511 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5513 pic14_emitcode("setb","c");
5515 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5516 pic14_emitcode("anl","a,%s",
5517 aopGet(AOP(left),offset,FALSE,FALSE));
5518 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5523 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5524 pic14_outBitC(result);
5526 jmpTrueOrFalse(ifx, tlbl);
5528 for(;(size--);offset++) {
5530 // result = left & right
5531 if(AOP_TYPE(right) == AOP_LIT){
5532 int t = (lit >> (offset*8)) & 0x0FFL;
5535 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5538 if(AOP_TYPE(left) != AOP_ACC) {
5539 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5541 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5544 if(AOP_TYPE(left) == AOP_ACC) {
5545 emitpcode(POC_ANDLW, popGetLit(t));
5547 emitpcode(POC_MOVLW, popGetLit(t));
5548 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5550 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5555 if (AOP_TYPE(left) == AOP_ACC) {
5556 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5558 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5559 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5561 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5567 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5568 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5569 freeAsmop(result,NULL,ic,TRUE);
5572 /*-----------------------------------------------------------------*/
5573 /* genOr - code for or */
5574 /*-----------------------------------------------------------------*/
5575 static void genOr (iCode *ic, iCode *ifx)
5577 operand *left, *right, *result;
5579 unsigned long lit = 0L;
5582 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5584 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5585 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5586 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5588 DEBUGpic14_AopType(__LINE__,left,right,result);
5590 /* if left is a literal & right is not then exchange them */
5591 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5592 AOP_NEEDSACC(left)) {
5593 operand *tmp = right ;
5598 /* if result = right then exchange them */
5599 if(pic14_sameRegs(AOP(result),AOP(right))){
5600 operand *tmp = right ;
5605 /* if right is bit then exchange them */
5606 if (AOP_TYPE(right) == AOP_CRY &&
5607 AOP_TYPE(left) != AOP_CRY){
5608 operand *tmp = right ;
5613 DEBUGpic14_AopType(__LINE__,left,right,result);
5615 if(AOP_TYPE(right) == AOP_LIT)
5616 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5618 size = AOP_SIZE(result);
5622 if (AOP_TYPE(left) == AOP_CRY){
5623 if(AOP_TYPE(right) == AOP_LIT){
5624 // c = bit & literal;
5626 // lit != 0 => result = 1
5627 if(AOP_TYPE(result) == AOP_CRY){
5629 emitpcode(POC_BSF, popGet(AOP(result),0));
5630 //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5631 // AOP(result)->aopu.aop_dir,
5632 // AOP(result)->aopu.aop_dir);
5634 continueIfTrue(ifx);
5638 // lit == 0 => result = left
5639 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5641 pic14_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5644 if (AOP_TYPE(right) == AOP_CRY){
5645 if(pic14_sameRegs(AOP(result),AOP(left))){
5647 emitpcode(POC_BCF, popGet(AOP(result),0));
5648 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5649 emitpcode(POC_BSF, popGet(AOP(result),0));
5651 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5652 AOP(result)->aopu.aop_dir,
5653 AOP(result)->aopu.aop_dir);
5654 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5655 AOP(right)->aopu.aop_dir,
5656 AOP(right)->aopu.aop_dir);
5657 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5658 AOP(result)->aopu.aop_dir,
5659 AOP(result)->aopu.aop_dir);
5661 if( AOP_TYPE(result) == AOP_ACC) {
5662 emitpcode(POC_MOVLW, popGetLit(0));
5663 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5664 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5665 emitpcode(POC_MOVLW, popGetLit(1));
5669 emitpcode(POC_BCF, popGet(AOP(result),0));
5670 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5671 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5672 emitpcode(POC_BSF, popGet(AOP(result),0));
5674 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5675 AOP(result)->aopu.aop_dir,
5676 AOP(result)->aopu.aop_dir);
5677 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5678 AOP(right)->aopu.aop_dir,
5679 AOP(right)->aopu.aop_dir);
5680 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5681 AOP(left)->aopu.aop_dir,
5682 AOP(left)->aopu.aop_dir);
5683 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5684 AOP(result)->aopu.aop_dir,
5685 AOP(result)->aopu.aop_dir);
5690 symbol *tlbl = newiTempLabel(NULL);
5691 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5694 emitpcode(POC_BCF, popGet(AOP(result),0));
5695 if( AOP_TYPE(right) == AOP_ACC) {
5696 emitpcode(POC_IORLW, popGetLit(0));
5698 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5699 emitpcode(POC_BSF, popGet(AOP(result),0));
5704 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5705 pic14_emitcode(";XXX setb","c");
5706 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5707 AOP(left)->aopu.aop_dir,tlbl->key+100);
5708 pic14_toBoolean(right);
5709 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5710 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5711 jmpTrueOrFalse(ifx, tlbl);
5715 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5722 pic14_outBitC(result);
5724 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5725 genIfxJump(ifx, "c");
5729 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5730 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5731 if((AOP_TYPE(right) == AOP_LIT) &&
5732 (AOP_TYPE(result) == AOP_CRY) &&
5733 (AOP_TYPE(left) != AOP_CRY)){
5735 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5738 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5740 continueIfTrue(ifx);
5743 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5744 // lit = 0, result = boolean(left)
5746 pic14_emitcode(";XXX setb","c");
5747 pic14_toBoolean(right);
5749 symbol *tlbl = newiTempLabel(NULL);
5750 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5752 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5754 genIfxJump (ifx,"a");
5758 pic14_outBitC(result);
5762 /* if left is same as result */
5763 if(pic14_sameRegs(AOP(result),AOP(left))){
5765 for(;size--; offset++,lit>>=8) {
5766 if(AOP_TYPE(right) == AOP_LIT){
5767 if((lit & 0xff) == 0)
5768 /* or'ing with 0 has no effect */
5771 int p = my_powof2(lit & 0xff);
5773 /* only one bit is set in the literal, so use a bsf instruction */
5775 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5777 if(know_W != (int)(lit & 0xff))
5778 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5779 know_W = lit & 0xff;
5780 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5785 if (AOP_TYPE(left) == AOP_ACC) {
5786 emitpcode(POC_IORFW, popGet(AOP(right),offset));
5787 pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5789 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
5790 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5792 pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5793 pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5799 // left & result in different registers
5800 if(AOP_TYPE(result) == AOP_CRY){
5802 // if(size), result in bit
5803 // if(!size && ifx), conditional oper: if(left | right)
5804 symbol *tlbl = newiTempLabel(NULL);
5805 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5806 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5810 pic14_emitcode(";XXX setb","c");
5812 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5813 pic14_emitcode(";XXX orl","a,%s",
5814 aopGet(AOP(left),offset,FALSE,FALSE));
5815 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5820 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5821 pic14_outBitC(result);
5823 jmpTrueOrFalse(ifx, tlbl);
5824 } else for(;(size--);offset++){
5826 // result = left | right
5827 if(AOP_TYPE(right) == AOP_LIT){
5828 int t = (lit >> (offset*8)) & 0x0FFL;
5831 if (AOP_TYPE(left) != AOP_ACC) {
5832 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
5834 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5838 if (AOP_TYPE(left) == AOP_ACC) {
5839 emitpcode(POC_IORLW, popGetLit(t));
5841 emitpcode(POC_MOVLW, popGetLit(t));
5842 emitpcode(POC_IORFW, popGet(AOP(left),offset));
5844 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5849 // faster than result <- left, anl result,right
5850 // and better if result is SFR
5851 if (AOP_TYPE(left) == AOP_ACC) {
5852 emitpcode(POC_IORFW,popGet(AOP(right),offset));
5854 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5855 emitpcode(POC_IORFW,popGet(AOP(left),offset));
5857 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5862 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5863 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5864 freeAsmop(result,NULL,ic,TRUE);
5867 /*-----------------------------------------------------------------*/
5868 /* genXor - code for xclusive or */
5869 /*-----------------------------------------------------------------*/
5870 static void genXor (iCode *ic, iCode *ifx)
5872 operand *left, *right, *result;
5874 unsigned long lit = 0L;
5877 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5879 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5880 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5881 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5883 /* if left is a literal & right is not ||
5884 if left needs acc & right does not */
5885 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5886 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5887 operand *tmp = right ;
5892 /* if result = right then exchange them */
5893 if(pic14_sameRegs(AOP(result),AOP(right))){
5894 operand *tmp = right ;
5899 /* if right is bit then exchange them */
5900 if (AOP_TYPE(right) == AOP_CRY &&
5901 AOP_TYPE(left) != AOP_CRY){
5902 operand *tmp = right ;
5906 if(AOP_TYPE(right) == AOP_LIT)
5907 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5909 size = AOP_SIZE(result);
5913 if (AOP_TYPE(left) == AOP_CRY){
5914 if(AOP_TYPE(right) == AOP_LIT){
5915 // c = bit & literal;
5917 // lit>>1 != 0 => result = 1
5918 if(AOP_TYPE(result) == AOP_CRY){
5920 {emitpcode(POC_BSF, popGet(AOP(result),offset));
5921 pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
5923 continueIfTrue(ifx);
5926 pic14_emitcode("setb","c");
5930 // lit == 0, result = left
5931 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5933 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5935 // lit == 1, result = not(left)
5936 if(size && pic14_sameRegs(AOP(result),AOP(left))){
5937 emitpcode(POC_MOVLW, popGet(AOP(result),offset));
5938 emitpcode(POC_XORWF, popGet(AOP(result),offset));
5939 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5942 assert ( !"incomplete genXor" );
5943 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5944 pic14_emitcode("cpl","c");
5951 symbol *tlbl = newiTempLabel(NULL);
5952 if (AOP_TYPE(right) == AOP_CRY){
5954 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5957 int sizer = AOP_SIZE(right);
5959 // if val>>1 != 0, result = 1
5960 pic14_emitcode("setb","c");
5962 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5964 // test the msb of the lsb
5965 pic14_emitcode("anl","a,#0xfe");
5966 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5970 pic14_emitcode("rrc","a");
5972 pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5973 pic14_emitcode("cpl","c");
5974 pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
5979 pic14_outBitC(result);
5981 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5982 genIfxJump(ifx, "c");
5986 if(pic14_sameRegs(AOP(result),AOP(left))){
5987 /* if left is same as result */
5988 for(;size--; offset++) {
5989 if(AOP_TYPE(right) == AOP_LIT){
5990 int t = (lit >> (offset*8)) & 0x0FFL;
5994 if (IS_AOP_PREG(left)) {
5995 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5996 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5997 aopPut(AOP(result),"a",offset);
5999 emitpcode(POC_MOVLW, popGetLit(t));
6000 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6001 pic14_emitcode("xrl","%s,%s",
6002 aopGet(AOP(left),offset,FALSE,TRUE),
6003 aopGet(AOP(right),offset,FALSE,FALSE));
6006 if (AOP_TYPE(left) == AOP_ACC)
6007 pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6009 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6010 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6012 if (IS_AOP_PREG(left)) {
6013 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6014 aopPut(AOP(result),"a",offset);
6016 pic14_emitcode("xrl","%s,a",
6017 aopGet(AOP(left),offset,FALSE,TRUE));
6023 // left & result in different registers
6024 if(AOP_TYPE(result) == AOP_CRY){
6026 // if(size), result in bit
6027 // if(!size && ifx), conditional oper: if(left ^ right)
6028 symbol *tlbl = newiTempLabel(NULL);
6029 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6031 pic14_emitcode("setb","c");
6033 if((AOP_TYPE(right) == AOP_LIT) &&
6034 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6035 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6037 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6038 pic14_emitcode("xrl","a,%s",
6039 aopGet(AOP(left),offset,FALSE,FALSE));
6041 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6046 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6047 pic14_outBitC(result);
6049 jmpTrueOrFalse(ifx, tlbl);
6050 } else for(;(size--);offset++){
6052 // result = left & right
6053 if(AOP_TYPE(right) == AOP_LIT){
6054 int t = (lit >> (offset*8)) & 0x0FFL;
6057 if (AOP_TYPE(left) != AOP_ACC) {
6058 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6060 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6061 pic14_emitcode("movf","%s,w",
6062 aopGet(AOP(left),offset,FALSE,FALSE));
6063 pic14_emitcode("movwf","%s",
6064 aopGet(AOP(result),offset,FALSE,FALSE));
6067 if (AOP_TYPE(left) == AOP_ACC) {
6068 emitpcode(POC_XORLW, popGetLit(t));
6070 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6072 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6075 if (AOP_TYPE(left) == AOP_ACC) {
6076 emitpcode(POC_XORLW, popGetLit(t));
6078 emitpcode(POC_MOVLW, popGetLit(t));
6079 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6081 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6082 pic14_emitcode("movlw","0x%x",t);
6083 pic14_emitcode("xorwf","%s,w",
6084 aopGet(AOP(left),offset,FALSE,FALSE));
6085 pic14_emitcode("movwf","%s",
6086 aopGet(AOP(result),offset,FALSE,FALSE));
6092 // faster than result <- left, anl result,right
6093 // and better if result is SFR
6094 if (AOP_TYPE(left) == AOP_ACC) {
6095 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6097 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6098 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6100 if ( AOP_TYPE(result) != AOP_ACC){
6101 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6107 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6108 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6109 freeAsmop(result,NULL,ic,TRUE);
6112 /*-----------------------------------------------------------------*/
6113 /* genInline - write the inline code out */
6114 /*-----------------------------------------------------------------*/
6115 static void genInline (iCode *ic)
6117 char *buffer, *bp, *bp1;
6120 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6122 _G.inLine += (!options.asmpeep);
6124 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6125 strcpy(buffer,IC_INLINE(ic));
6127 /* emit each line as a code */
6133 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6141 /* print label, use this special format with NULL directive
6142 * to denote that the argument should not be indented with tab */
6143 addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6150 if ((bp1 != bp) && *bp1)
6151 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6155 _G.inLine -= (!options.asmpeep);
6158 /*-----------------------------------------------------------------*/
6159 /* genRRC - rotate right with carry */
6160 /*-----------------------------------------------------------------*/
6161 static void genRRC (iCode *ic)
6163 operand *left , *result ;
6164 int size, offset = 0, same;
6167 /* rotate right with carry */
6169 result=IC_RESULT(ic);
6170 aopOp (left,ic,FALSE);
6171 aopOp (result,ic,FALSE);
6173 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6175 same = pic14_sameRegs(AOP(result),AOP(left));
6177 size = AOP_SIZE(result);
6179 /* get the lsb and put it into the carry */
6180 emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6187 emitpcode(POC_RRF, popGet(AOP(left),offset));
6189 emitpcode(POC_RRFW, popGet(AOP(left),offset));
6190 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6196 freeAsmop(left,NULL,ic,TRUE);
6197 freeAsmop(result,NULL,ic,TRUE);
6200 /*-----------------------------------------------------------------*/
6201 /* genRLC - generate code for rotate left with carry */
6202 /*-----------------------------------------------------------------*/
6203 static void genRLC (iCode *ic)
6205 operand *left , *result ;
6206 int size, offset = 0;
6210 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6211 /* rotate right with carry */
6213 result=IC_RESULT(ic);
6214 aopOp (left,ic,FALSE);
6215 aopOp (result,ic,FALSE);
6217 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6219 same = pic14_sameRegs(AOP(result),AOP(left));
6221 /* move it to the result */
6222 size = AOP_SIZE(result);
6224 /* get the msb and put it into the carry */
6225 emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6232 emitpcode(POC_RLF, popGet(AOP(left),offset));
6234 emitpcode(POC_RLFW, popGet(AOP(left),offset));
6235 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6242 freeAsmop(left,NULL,ic,TRUE);
6243 freeAsmop(result,NULL,ic,TRUE);
6246 /*-----------------------------------------------------------------*/
6247 /* genGetHbit - generates code get highest order bit */
6248 /*-----------------------------------------------------------------*/
6249 static void genGetHbit (iCode *ic)
6251 operand *left, *result;
6253 result=IC_RESULT(ic);
6254 aopOp (left,ic,FALSE);
6255 aopOp (result,ic,FALSE);
6258 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6259 /* get the highest order byte into a */
6260 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6261 if(AOP_TYPE(result) == AOP_CRY){
6262 pic14_emitcode("rlc","a");
6263 pic14_outBitC(result);
6266 pic14_emitcode("rl","a");
6267 pic14_emitcode("anl","a,#0x01");
6268 pic14_outAcc(result);
6272 freeAsmop(left,NULL,ic,TRUE);
6273 freeAsmop(result,NULL,ic,TRUE);
6276 /*-----------------------------------------------------------------*/
6277 /* AccRol - rotate left accumulator by known count */
6278 /*-----------------------------------------------------------------*/
6279 static void AccRol (operand *op,int offset,int shCount)
6282 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6283 shCount &= 0x0007; // shCount : 0..7
6288 pic14_emitcode("rl","a");
6289 emitpcode(POC_RLF,popGet(AOP(op),offset));
6292 pic14_emitcode("rl","a");
6293 pic14_emitcode("rl","a");
6294 emitpcode(POC_RLF,popGet(AOP(op),offset));
6295 emitpcode(POC_RLF,popGet(AOP(op),offset));
6298 pic14_emitcode("swap","a");
6299 pic14_emitcode("rr","a");
6300 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6301 emitpcode(POC_RRF,popGet(AOP(op),offset));
6304 pic14_emitcode("swap","a");
6305 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6308 pic14_emitcode("swap","a");
6309 pic14_emitcode("rl","a");
6310 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6311 emitpcode(POC_RLF,popGet(AOP(op),offset));
6314 pic14_emitcode("rr","a");
6315 pic14_emitcode("rr","a");
6316 emitpcode(POC_RRF,popGet(AOP(op),offset));
6317 emitpcode(POC_RRF,popGet(AOP(op),offset));
6320 pic14_emitcode("rr","a");
6321 emitpcode(POC_RRF,popGet(AOP(op),offset));
6326 /*-----------------------------------------------------------------*/
6327 /* AccLsh - left shift accumulator by known count */
6328 /*-----------------------------------------------------------------*/
6329 static void AccLsh (operand *op,int offset,int shCount)
6332 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6337 emitpcode (POC_RLF, popGet (AOP(op), 0));
6339 /* rotate left accumulator */
6340 AccRol(op,offset,shCount);
6341 /* and kill the lower order bits */
6342 emitpcode(POC_MOVLW,popGetLit(SLMask[shCount]));
6343 emitpcode (POC_ANDWF, popGet (AOP(op),0));
6348 /*-----------------------------------------------------------------*/
6349 /* AccRsh - right shift accumulator by known count */
6350 /*-----------------------------------------------------------------*/
6351 static void AccRsh (operand *op,int offset,int shCount)
6354 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6358 emitpcode (POC_RRF, popGet (AOP(op), 0));
6360 /* rotate right accumulator */
6361 AccRol(op,offset,8 - shCount);
6362 /* and kill the higher order bits */
6363 emitpcode (POC_MOVLW, popGetLit (SRMask[shCount]));
6364 emitpcode (POC_ANDWF, popGet (AOP(op),0));
6370 /*-----------------------------------------------------------------*/
6371 /* AccSRsh - signed right shift accumulator by known count */
6372 /*-----------------------------------------------------------------*/
6373 static void AccSRsh (int shCount)
6376 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6379 pic14_emitcode("mov","c,acc.7");
6380 pic14_emitcode("rrc","a");
6381 } else if(shCount == 2){
6382 pic14_emitcode("mov","c,acc.7");
6383 pic14_emitcode("rrc","a");
6384 pic14_emitcode("mov","c,acc.7");
6385 pic14_emitcode("rrc","a");
6387 tlbl = newiTempLabel(NULL);
6388 /* rotate right accumulator */
6389 AccRol(8 - shCount);
6390 /* and kill the higher order bits */
6391 pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6392 pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6393 pic14_emitcode("orl","a,#0x%02x",
6394 (unsigned char)~SRMask[shCount]);
6395 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6400 /*-----------------------------------------------------------------*/
6401 /* shiftR1Left2Result - shift right one byte from left to result */
6402 /*-----------------------------------------------------------------*/
6403 static void shiftR1Left2ResultSigned (operand *left, int offl,
6404 operand *result, int offr,
6410 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6412 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6416 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6418 emitpcode(POC_RRF, popGet(AOP(result),offr));
6420 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6421 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6427 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6429 emitpcode(POC_RRF, popGet(AOP(result),offr));
6431 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6432 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6434 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6435 emitpcode(POC_RRF, popGet(AOP(result),offr));
6441 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6443 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6444 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6447 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6448 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6449 emitpcode(POC_ANDLW, popGetLit(0x1f));
6451 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6452 emitpcode(POC_IORLW, popGetLit(0xe0));
6454 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6458 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6459 emitpcode(POC_ANDLW, popGetLit(0x0f));
6460 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6461 emitpcode(POC_IORLW, popGetLit(0xf0));
6462 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6466 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6468 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6469 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6471 emitpcode(POC_RRFW, popGet(AOP(result),offr));
6472 emitpcode(POC_ANDLW, popGetLit(0x07));
6473 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6474 emitpcode(POC_IORLW, popGetLit(0xf8));
6475 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6480 emitpcode(POC_MOVLW, popGetLit(0x00));
6481 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6482 emitpcode(POC_MOVLW, popGetLit(0xfe));
6483 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6484 emitpcode(POC_IORLW, popGetLit(0x01));
6485 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6487 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6488 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6489 emitpcode(POC_DECF, popGet(AOP(result),offr));
6490 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6491 emitpcode(POC_BCF, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6497 emitpcode(POC_MOVLW, popGetLit(0x00));
6498 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6499 emitpcode(POC_MOVLW, popGetLit(0xff));
6500 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6502 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6503 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6504 emitpcode(POC_DECF, popGet(AOP(result),offr));
6512 /*-----------------------------------------------------------------*/
6513 /* shiftR1Left2Result - shift right one byte from left to result */
6514 /*-----------------------------------------------------------------*/
6515 static void shiftR1Left2Result (operand *left, int offl,
6516 operand *result, int offr,
6517 int shCount, int sign)
6522 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6524 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6526 /* Copy the msb into the carry if signed. */
6528 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6538 emitpcode(POC_RRF, popGet(AOP(result),offr));
6540 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6541 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6547 emitpcode(POC_RRF, popGet(AOP(result),offr));
6549 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6550 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6553 emitpcode(POC_RRF, popGet(AOP(result),offr));
6558 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6560 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6561 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6564 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6565 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6566 emitpcode(POC_ANDLW, popGetLit(0x1f));
6567 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6571 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6572 emitpcode(POC_ANDLW, popGetLit(0x0f));
6573 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6577 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6578 emitpcode(POC_ANDLW, popGetLit(0x0f));
6579 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6581 emitpcode(POC_RRF, popGet(AOP(result),offr));
6586 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6587 emitpcode(POC_ANDLW, popGetLit(0x80));
6588 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6589 emitpcode(POC_RLF, popGet(AOP(result),offr));
6590 emitpcode(POC_RLF, popGet(AOP(result),offr));
6595 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6596 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6597 emitpcode(POC_RLF, popGet(AOP(result),offr));
6606 /*-----------------------------------------------------------------*/
6607 /* shiftL1Left2Result - shift left one byte from left to result */
6608 /*-----------------------------------------------------------------*/
6609 static void shiftL1Left2Result (operand *left, int offl,
6610 operand *result, int offr, int shCount)
6616 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6618 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6619 DEBUGpic14_emitcode ("; ***","same = %d",same);
6620 // l = aopGet(AOP(left),offl,FALSE,FALSE);
6622 /* shift left accumulator */
6623 //AccLsh(shCount); // don't comment out just yet...
6624 // aopPut(AOP(result),"a",offr);
6628 /* Shift left 1 bit position */
6629 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6631 emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6633 emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6634 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6638 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6639 emitpcode(POC_ANDLW,popGetLit(0x7e));
6640 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6641 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6644 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6645 emitpcode(POC_ANDLW,popGetLit(0x3e));
6646 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6647 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6648 emitpcode(POC_RLF, popGet(AOP(result),offr));
6651 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6652 emitpcode(POC_ANDLW, popGetLit(0xf0));
6653 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6656 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6657 emitpcode(POC_ANDLW, popGetLit(0xf0));
6658 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6659 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6662 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6663 emitpcode(POC_ANDLW, popGetLit(0x30));
6664 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6665 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6666 emitpcode(POC_RLF, popGet(AOP(result),offr));
6669 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6670 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6671 emitpcode(POC_RRF, popGet(AOP(result),offr));
6675 DEBUGpic14_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6681 /*-----------------------------------------------------------------*/
6682 /* movLeft2Result - move byte from left to result */
6683 /*-----------------------------------------------------------------*/
6684 static void movLeft2Result (operand *left, int offl,
6685 operand *result, int offr)
6689 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6690 if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6691 l = aopGet(AOP(left),offl,FALSE,FALSE);
6693 if (*l == '@' && (IS_AOP_PREG(result))) {
6694 pic14_emitcode("mov","a,%s",l);
6695 aopPut(AOP(result),"a",offr);
6697 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6698 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6703 /*-----------------------------------------------------------------*/
6704 /* shiftLeft_Left2ResultLit - shift left by known count */
6705 /*-----------------------------------------------------------------*/
6707 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6709 int size, same, offr, i;
6711 size = AOP_SIZE(left);
6712 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6714 same = pic14_sameRegs (AOP(left), AOP(result));
6717 shCount = shCount & 0x07;
6723 case 0: /* takes 0 or 2N cycles (for offr==0) */
6724 if (!same || offr) {
6725 for (i=size-1; i >= 0; i--)
6726 movLeft2Result (left, i, result, offr + i);
6730 case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6732 shiftLeft_Left2ResultLit (left, result, 8 * offr);
6733 shiftLeft_Left2ResultLit (result, result, shCount);
6734 return; /* prevent clearing result again */
6737 for (i=0; i < size; i++) {
6738 if (same && !offr) {
6739 emitpcode (POC_RLF, popGet (AOP(left), i));
6741 emitpcode (POC_RLFW, popGet (AOP(left), i));
6742 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6748 case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
6749 /* works in-place/with offr as well */
6750 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
6751 emitpcode (POC_ANDLW, popGetLit (0xF0));
6752 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
6754 for (i = size - 2; i >= 0; i--)
6756 emitpcode (POC_SWAPFW, popGet (AOP(left), i));
6757 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6758 emitpcode (POC_ANDLW, popGetLit (0x0F));
6759 emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
6760 emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
6764 case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
6765 /* works in-place/with offr as well */
6766 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
6767 for (i = size-2; i >= 0; i--) {
6768 emitpcode (POC_RRFW, popGet (AOP(left), i));
6769 emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
6771 emitpcode (POC_CLRF, popGet (AOP(result), offr));
6772 emitpcode (POC_RRF, popGet (AOP(result), offr));
6776 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
6777 shiftLeft_Left2ResultLit (result, result, 1);
6778 return; /* prevent clearing result again */
6784 emitpcode (POC_CLRF, popGet (AOP(result), offr));
6788 /*-----------------------------------------------------------------*/
6789 /* shiftRight_Left2ResultLit - shift right by known count */
6790 /*-----------------------------------------------------------------*/
6792 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
6794 int size, same, offr, i;
6796 size = AOP_SIZE(left);
6797 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6799 same = pic14_sameRegs (AOP(left), AOP(result));
6802 shCount = shCount & 0x07;
6810 case 0: /* takes 0 or 2N cycles (for offr==0) */
6811 if (!same || offr) {
6812 for (i=0; i < size; i++)
6813 movLeft2Result (left, i + offr, result, i);
6817 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
6818 emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
6820 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
6821 shiftRight_Left2ResultLit (result, result, shCount, sign);
6822 return; /* prevent sign-extending result again */
6826 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
6829 for (i = size-1; i >= 0; i--) {
6830 if (same && !offr) {
6831 emitpcode (POC_RRF, popGet (AOP(left), i));
6833 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
6834 emitpcode (POC_MOVWF, popGet (AOP(result), i));
6840 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
6841 /* works in-place/with offr as well */
6842 emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
6843 emitpcode (POC_ANDLW, popGetLit (0x0F));
6844 emitpcode (POC_MOVWF, popGet(AOP(result), 0));
6846 for (i = 1; i < size; i++)
6848 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
6849 emitpcode (POC_MOVWF, popGet (AOP(result), i));
6850 emitpcode (POC_ANDLW, popGetLit (0xF0));
6851 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
6852 emitpcode (POC_XORWF, popGet (AOP(result), i));
6857 emitpcode (POC_MOVLW, popGetLit (0xF0));
6858 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
6859 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
6863 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
6864 /* works in-place/with offr as well */
6865 emitpcode (POC_RLFW, popGet (AOP(left), offr));
6866 for (i = 0; i < size-1; i++) {
6867 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
6868 emitpcode (POC_MOVWF, popGet (AOP(result), i));
6870 emitpcode (POC_CLRF, popGet (AOP(result), size-1));
6872 emitpcode (POC_RLF, popGet (AOP(result), size-1));
6875 emitpcode (POC_DECF, popGet (AOP(result), size-1));
6880 shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
6881 shiftRight_Left2ResultLit (result, result, 1, sign);
6882 return; /* prevent sign extending result again */
6887 addSign (result, size, sign);
6891 /*-----------------------------------------------------------------*/
6892 /* shiftL2Left2Result - shift left two bytes from left to result */
6893 /*-----------------------------------------------------------------*/
6894 static void shiftL2Left2Result (operand *left, int offl,
6895 operand *result, int offr, int shCount)
6899 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6901 if(pic14_sameRegs(AOP(result), AOP(left))) {
6909 emitpcode(POC_MOVFW,popGet(AOP(result),offr));
6910 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6911 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6915 emitpcode(POC_RLF, popGet(AOP(result),offr));
6916 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6922 emitpcode(POC_MOVLW, popGetLit(0x0f));
6923 emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
6924 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6925 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6926 emitpcode(POC_ANDFW, popGet(AOP(result),offr));
6927 emitpcode(POC_XORWF, popGet(AOP(result),offr));
6928 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6930 emitpcode(POC_RLF, popGet(AOP(result),offr));
6931 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6935 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6936 emitpcode(POC_RRF, popGet(AOP(result),offr));
6937 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6938 emitpcode(POC_RRF, popGet(AOP(result),offr));
6939 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6940 emitpcode(POC_ANDLW,popGetLit(0xc0));
6941 emitpcode(POC_XORFW,popGet(AOP(result),offr));
6942 emitpcode(POC_XORWF,popGet(AOP(result),offr));
6943 emitpcode(POC_XORFW,popGet(AOP(result),offr));
6944 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6947 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6948 emitpcode(POC_RRFW, popGet(AOP(result),offr));
6949 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6950 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6951 emitpcode(POC_RRF, popGet(AOP(result),offr));
6961 /* note, use a mov/add for the shift since the mov has a
6962 chance of getting optimized out */
6963 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6964 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6965 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6966 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6967 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6971 emitpcode(POC_RLF, popGet(AOP(result),offr));
6972 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6978 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6979 emitpcode(POC_ANDLW, popGetLit(0xF0));
6980 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6981 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6982 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6983 emitpcode(POC_ANDLW, popGetLit(0xF0));
6984 emitpcode(POC_XORWF, popGet(AOP(result),offr));
6985 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6989 emitpcode(POC_RLF, popGet(AOP(result),offr));
6990 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6994 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6995 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6996 emitpcode(POC_RRFW, popGet(AOP(result),offl));
6997 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6999 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7000 emitpcode(POC_RRF, popGet(AOP(result),offr));
7001 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7002 emitpcode(POC_ANDLW,popGetLit(0xc0));
7003 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7004 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7005 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7006 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7009 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7010 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7011 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7012 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7013 emitpcode(POC_RRF, popGet(AOP(result),offr));
7019 /*-----------------------------------------------------------------*/
7020 /* shiftR2Left2Result - shift right two bytes from left to result */
7021 /*-----------------------------------------------------------------*/
7022 static void shiftR2Left2Result (operand *left, int offl,
7023 operand *result, int offr,
7024 int shCount, int sign)
7029 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7030 same = pic14_sameRegs(AOP(result), AOP(left));
7032 if(same && ((offl + MSB16) == offr)){
7034 /* don't crash result[offr] */
7035 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7036 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7039 movLeft2Result(left,offl, result, offr);
7040 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7043 /* a:x >> shCount (x = lsb(result))*/
7046 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7048 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7057 emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7062 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7063 emitpcode(POC_RRF,popGet(AOP(result),offr));
7065 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7066 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7067 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7068 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7073 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7076 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7077 emitpcode(POC_RRF,popGet(AOP(result),offr));
7084 emitpcode(POC_MOVLW, popGetLit(0xf0));
7085 emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7086 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7088 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7089 emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7090 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7091 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7093 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7094 emitpcode(POC_ANDLW, popGetLit(0x0f));
7095 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7097 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7098 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7099 emitpcode(POC_ANDLW, popGetLit(0xf0));
7100 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7101 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7105 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7106 emitpcode(POC_RRF, popGet(AOP(result),offr));
7110 emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7111 emitpcode(POC_BTFSC,
7112 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7113 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7121 emitpcode(POC_RLF, popGet(AOP(result),offr));
7122 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7124 emitpcode(POC_RLF, popGet(AOP(result),offr));
7125 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7126 emitpcode(POC_RLFW, popGet(AOP(result),offr));
7127 emitpcode(POC_ANDLW,popGetLit(0x03));
7129 emitpcode(POC_BTFSC,
7130 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7131 emitpcode(POC_IORLW,popGetLit(0xfc));
7133 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7134 emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7135 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7136 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7138 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7139 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7140 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7141 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7142 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7143 emitpcode(POC_RLF, popGet(AOP(result),offr));
7144 emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7145 emitpcode(POC_ANDLW,popGetLit(0x03));
7147 emitpcode(POC_BTFSC,
7148 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7149 emitpcode(POC_IORLW,popGetLit(0xfc));
7151 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7152 //emitpcode(POC_RLF, popGet(AOP(result),offr));
7159 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7160 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7161 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7162 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7165 emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7167 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7171 /*-----------------------------------------------------------------*/
7172 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7173 /*-----------------------------------------------------------------*/
7174 static void shiftLLeftOrResult (operand *left, int offl,
7175 operand *result, int offr, int shCount)
7178 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7180 /* shift left accumulator */
7181 AccLsh(left,offl,shCount);
7182 /* or with result */
7183 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7184 assert ( !"broken (modifies left, fails for left==result))" );
7187 /*-----------------------------------------------------------------*/
7188 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7189 /*-----------------------------------------------------------------*/
7190 static void shiftRLeftOrResult (operand *left, int offl,
7191 operand *result, int offr, int shCount)
7194 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7196 /* shift right accumulator */
7197 AccRsh(left,offl,shCount);
7198 /* or with result */
7199 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7200 assert ( !"broken (modifies left, fails for left==result))" );
7203 /*-----------------------------------------------------------------*/
7204 /* genlshOne - left shift a one byte quantity by known count */
7205 /*-----------------------------------------------------------------*/
7206 static void genlshOne (operand *result, operand *left, int shCount)
7209 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7210 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7213 /*-----------------------------------------------------------------*/
7214 /* genlshTwo - left shift two bytes by known amount != 0 */
7215 /*-----------------------------------------------------------------*/
7216 static void genlshTwo (operand *result,operand *left, int shCount)
7221 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7222 size = pic14_getDataSize(result);
7224 /* if shCount >= 8 */
7230 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7232 movLeft2Result(left, LSB, result, MSB16);
7234 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7237 /* 1 <= shCount <= 7 */
7240 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7242 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7246 /*-----------------------------------------------------------------*/
7247 /* shiftLLong - shift left one long from left to result */
7248 /* offl = LSB or MSB16 */
7249 /*-----------------------------------------------------------------*/
7250 static void shiftLLong (operand *left, operand *result, int offr )
7253 int size = AOP_SIZE(result);
7256 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7257 if(size >= LSB+offr){
7258 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7260 pic14_emitcode("add","a,acc");
7261 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7262 size >= MSB16+offr && offr != LSB )
7263 pic14_emitcode("xch","a,%s",
7264 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7266 aopPut(AOP(result),"a",LSB+offr);
7269 if(size >= MSB16+offr){
7270 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7271 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7274 pic14_emitcode("rlc","a");
7275 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7276 size >= MSB24+offr && offr != LSB)
7277 pic14_emitcode("xch","a,%s",
7278 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7280 aopPut(AOP(result),"a",MSB16+offr);
7283 if(size >= MSB24+offr){
7284 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7285 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7288 pic14_emitcode("rlc","a");
7289 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7290 size >= MSB32+offr && offr != LSB )
7291 pic14_emitcode("xch","a,%s",
7292 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7294 aopPut(AOP(result),"a",MSB24+offr);
7297 if(size > MSB32+offr){
7298 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7299 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7302 pic14_emitcode("rlc","a");
7303 aopPut(AOP(result),"a",MSB32+offr);
7306 aopPut(AOP(result),zero,LSB);
7309 /*-----------------------------------------------------------------*/
7310 /* genlshFour - shift four byte by a known amount != 0 */
7311 /*-----------------------------------------------------------------*/
7312 static void genlshFour (operand *result, operand *left, int shCount)
7317 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7318 size = AOP_SIZE(result);
7320 /* if shifting more that 3 bytes */
7321 if (shCount >= 24 ) {
7324 /* lowest order of left goes to the highest
7325 order of the destination */
7326 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7328 movLeft2Result(left, LSB, result, MSB32);
7329 aopPut(AOP(result),zero,LSB);
7330 aopPut(AOP(result),zero,MSB16);
7331 aopPut(AOP(result),zero,MSB32);
7335 /* more than two bytes */
7336 else if ( shCount >= 16 ) {
7337 /* lower order two bytes goes to higher order two bytes */
7339 /* if some more remaining */
7341 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7343 movLeft2Result(left, MSB16, result, MSB32);
7344 movLeft2Result(left, LSB, result, MSB24);
7346 aopPut(AOP(result),zero,MSB16);
7347 aopPut(AOP(result),zero,LSB);
7351 /* if more than 1 byte */
7352 else if ( shCount >= 8 ) {
7353 /* lower order three bytes goes to higher order three bytes */
7357 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7359 movLeft2Result(left, LSB, result, MSB16);
7361 else{ /* size = 4 */
7363 movLeft2Result(left, MSB24, result, MSB32);
7364 movLeft2Result(left, MSB16, result, MSB24);
7365 movLeft2Result(left, LSB, result, MSB16);
7366 aopPut(AOP(result),zero,LSB);
7368 else if(shCount == 1)
7369 shiftLLong(left, result, MSB16);
7371 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7372 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7373 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7374 aopPut(AOP(result),zero,LSB);
7379 /* 1 <= shCount <= 7 */
7380 else if(shCount <= 2){
7381 shiftLLong(left, result, LSB);
7383 shiftLLong(result, result, LSB);
7385 /* 3 <= shCount <= 7, optimize */
7387 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7388 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7389 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7395 /*-----------------------------------------------------------------*/
7396 /* genLeftShiftLiteral - left shifting by known count */
7397 /*-----------------------------------------------------------------*/
7398 static void genLeftShiftLiteral (operand *left,
7403 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7407 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7408 freeAsmop(right,NULL,ic,TRUE);
7410 aopOp(left,ic,FALSE);
7411 aopOp(result,ic,FALSE);
7413 size = getSize(operandType(result));
7416 pic14_emitcode("; shift left ","result %d, left %d",size,
7420 /* I suppose that the left size >= result size */
7423 movLeft2Result(left, size, result, size);
7427 else if(shCount >= (size * 8))
7429 aopPut(AOP(result),zero,size);
7433 genlshOne (result,left,shCount);
7438 genlshTwo (result,left,shCount);
7442 genlshFour (result,left,shCount);
7446 freeAsmop(left,NULL,ic,TRUE);
7447 freeAsmop(result,NULL,ic,TRUE);
7451 /*-----------------------------------------------------------------*
7452 * genMultiAsm - repeat assembly instruction for size of register.
7453 * if endian == 1, then the high byte (i.e base address + size of
7454 * register) is used first else the low byte is used first;
7455 *-----------------------------------------------------------------*/
7456 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7462 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7475 emitpcode(poc, popGet(AOP(reg),offset));
7480 /*-----------------------------------------------------------------*/
7481 /* genLeftShift - generates code for left shifting */
7482 /*-----------------------------------------------------------------*/
7483 static void genLeftShift (iCode *ic)
7485 operand *left,*right, *result;
7487 unsigned long lit = 0L;
7489 symbol *tlbl , *tlbl1;
7493 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7495 right = IC_RIGHT(ic);
7497 result = IC_RESULT(ic);
7499 aopOp(right,ic,FALSE);
7500 aopOp(left,ic,FALSE);
7501 aopOp(result,ic,FALSE);
7504 /* if the shift count is known then do it
7505 as efficiently as possible */
7506 if (AOP_TYPE(right) == AOP_LIT) {
7507 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7511 /* shift count is unknown then we have to form
7512 a loop get the loop count in B : Note: we take
7513 only the lower order byte since shifting
7514 more that 32 bits make no sense anyway, ( the
7515 largest size of an object can be only 32 bits ) */
7518 /* now move the left to the result if they are not the
7520 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
7521 AOP_SIZE(result) > 1) {
7523 size = AOP_SIZE(result);
7526 l = aopGet(AOP(left),offset,FALSE,TRUE);
7527 if (*l == '@' && (IS_AOP_PREG(result))) {
7529 pic14_emitcode("mov","a,%s",l);
7530 aopPut(AOP(result),"a",offset);
7532 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
7533 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7534 //aopPut(AOP(result),l,offset);
7540 if(AOP_TYPE(left) == AOP_LIT)
7541 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7543 size = AOP_SIZE(result);
7545 /* if it is only one byte then */
7547 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7548 emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7549 emitpcode(POC_ANDLW, popGetLit(0xf0));
7550 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7551 emitpcode(POC_MOVFW, popGet(AOP(left),0));
7552 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7553 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7554 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7555 emitpcode(POC_RLFW, popGet(AOP(result),0));
7556 emitpcode(POC_ANDLW, popGetLit(0xfe));
7557 emitpcode(POC_ADDFW, popGet(AOP(result),0));
7558 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7559 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7562 tlbl = newiTempLabel(NULL);
7563 if (!pic14_sameRegs(AOP(left),AOP(result))) {
7564 if (AOP_TYPE(left) == AOP_LIT)
7565 emitpcode(POC_MOVLW, popGetLit(lit));
7567 emitpcode(POC_MOVFW, popGet(AOP(left),0));
7568 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7571 emitpcode(POC_COMFW, popGet(AOP(right),0));
7572 emitpcode(POC_RRF, popGet(AOP(result),0));
7573 emitpLabel(tlbl->key);
7574 emitpcode(POC_RLF, popGet(AOP(result),0));
7575 emitpcode(POC_ADDLW, popGetLit(1));
7577 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7582 if (pic14_sameRegs(AOP(left),AOP(result))) {
7584 tlbl = newiTempLabel(NULL);
7585 emitpcode(POC_COMFW, popGet(AOP(right),0));
7586 genMultiAsm(POC_RRF, result, size,1);
7587 emitpLabel(tlbl->key);
7588 genMultiAsm(POC_RLF, result, size,0);
7589 emitpcode(POC_ADDLW, popGetLit(1));
7591 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7595 //tlbl = newiTempLabel(NULL);
7597 //tlbl1 = newiTempLabel(NULL);
7599 //reAdjustPreg(AOP(result));
7601 //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7602 //pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7603 //l = aopGet(AOP(result),offset,FALSE,FALSE);
7605 //pic14_emitcode("add","a,acc");
7606 //aopPut(AOP(result),"a",offset++);
7608 // l = aopGet(AOP(result),offset,FALSE,FALSE);
7610 // pic14_emitcode("rlc","a");
7611 // aopPut(AOP(result),"a",offset++);
7613 //reAdjustPreg(AOP(result));
7615 //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7616 //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7619 tlbl = newiTempLabel(NULL);
7620 tlbl1= newiTempLabel(NULL);
7622 size = AOP_SIZE(result);
7625 pctemp = popGetTempReg(); /* grab a temporary working register. */
7627 emitpcode(POC_MOVFW, popGet(AOP(right),0));
7629 /* offset should be 0, 1 or 3 */
7630 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7632 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
7634 emitpcode(POC_MOVWF, pctemp);
7637 emitpLabel(tlbl->key);
7640 emitpcode(POC_RLF, popGet(AOP(result),0));
7642 emitpcode(POC_RLF, popGet(AOP(result),offset++));
7644 emitpcode(POC_DECFSZ, pctemp);
7645 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7646 emitpLabel(tlbl1->key);
7648 popReleaseTempReg(pctemp);
7652 freeAsmop (right,NULL,ic,TRUE);
7653 freeAsmop(left,NULL,ic,TRUE);
7654 freeAsmop(result,NULL,ic,TRUE);
7658 /*-----------------------------------------------------------------*/
7659 /* genrshOne - right shift a one byte quantity by known count */
7660 /*-----------------------------------------------------------------*/
7661 static void genrshOne (operand *result, operand *left,
7662 int shCount, int sign)
7665 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7666 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7669 /*-----------------------------------------------------------------*/
7670 /* genrshTwo - right shift two bytes by known amount != 0 */
7671 /*-----------------------------------------------------------------*/
7672 static void genrshTwo (operand *result,operand *left,
7673 int shCount, int sign)
7676 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7677 /* if shCount >= 8 */
7681 shiftR1Left2Result(left, MSB16, result, LSB,
7684 movLeft2Result(left, MSB16, result, LSB);
7686 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7689 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7690 emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7694 /* 1 <= shCount <= 7 */
7696 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
7699 /*-----------------------------------------------------------------*/
7700 /* shiftRLong - shift right one long from left to result */
7701 /* offl = LSB or MSB16 */
7702 /*-----------------------------------------------------------------*/
7703 static void shiftRLong (operand *left, int offl,
7704 operand *result, int sign)
7709 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7711 size = AOP_SIZE(left);
7712 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7715 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7719 assert (offl >= 0 && offl < size);
7721 same = pic14_sameRegs (AOP(left), AOP(result));
7723 /* perform the shift */
7726 if (same && !offl) {
7727 emitpcode (POC_RRF, popGet (AOP(result), size));
7729 emitpcode (POC_RRFW, popGet (AOP(left), size));
7730 emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7734 addSign (result, AOP_SIZE(left) - offl, sign);
7737 /*-----------------------------------------------------------------*/
7738 /* genrshFour - shift four byte by a known amount != 0 */
7739 /*-----------------------------------------------------------------*/
7740 static void genrshFour (operand *result, operand *left,
7741 int shCount, int sign)
7744 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7745 /* if shifting more that 3 bytes */
7746 if(shCount >= 24 ) {
7749 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7751 movLeft2Result(left, MSB32, result, LSB);
7753 addSign(result, MSB16, sign);
7755 else if(shCount >= 16){
7758 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7760 movLeft2Result(left, MSB24, result, LSB);
7761 movLeft2Result(left, MSB32, result, MSB16);
7763 addSign(result, MSB24, sign);
7765 else if(shCount >= 8){
7768 shiftRLong(left, MSB16, result, sign);
7769 else if(shCount == 0){
7770 movLeft2Result(left, MSB16, result, LSB);
7771 movLeft2Result(left, MSB24, result, MSB16);
7772 movLeft2Result(left, MSB32, result, MSB24);
7773 addSign(result, MSB32, sign);
7776 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7777 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7778 /* the last shift is signed */
7779 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7780 addSign(result, MSB32, sign);
7783 else{ /* 1 <= shCount <= 7 */
7785 shiftRLong(left, LSB, result, sign);
7787 shiftRLong(result, LSB, result, sign);
7790 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7791 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7792 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7797 /*-----------------------------------------------------------------*/
7798 /* genRightShiftLiteral - right shifting by known count */
7799 /*-----------------------------------------------------------------*/
7800 static void genRightShiftLiteral (operand *left,
7806 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7810 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7811 freeAsmop(right,NULL,ic,TRUE);
7813 aopOp(left,ic,FALSE);
7814 aopOp(result,ic,FALSE);
7817 pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7821 lsize = pic14_getDataSize(left);
7822 res_size = pic14_getDataSize(result);
7823 /* test the LEFT size !!! */
7825 /* I suppose that the left size >= result size */
7828 movLeft2Result(left, res_size, result, res_size);
7831 else if(shCount >= (lsize * 8)){
7834 emitpcode(POC_CLRF, popGet(AOP(result),LSB));
7836 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7837 emitpcode(POC_DECF, popGet(AOP(result),LSB));
7842 emitpcode(POC_MOVLW, popGetLit(0));
7843 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7844 emitpcode(POC_MOVLW, popGetLit(0xff));
7846 emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
7851 emitpcode(POC_CLRF, popGet(AOP(result),res_size));
7858 genrshOne (result,left,shCount,sign);
7862 genrshTwo (result,left,shCount,sign);
7866 genrshFour (result,left,shCount,sign);
7874 freeAsmop(left,NULL,ic,TRUE);
7875 freeAsmop(result,NULL,ic,TRUE);
7879 /*-----------------------------------------------------------------*/
7880 /* genSignedRightShift - right shift of signed number */
7881 /*-----------------------------------------------------------------*/
7882 static void genSignedRightShift (iCode *ic)
7884 operand *right, *left, *result;
7887 symbol *tlbl, *tlbl1 ;
7890 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7892 /* we do it the hard way put the shift count in b
7893 and loop thru preserving the sign */
7895 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7897 right = IC_RIGHT(ic);
7899 result = IC_RESULT(ic);
7901 aopOp(right,ic,FALSE);
7902 aopOp(left,ic,FALSE);
7903 aopOp(result,ic,FALSE);
7906 if ( AOP_TYPE(right) == AOP_LIT) {
7907 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
7908 //genRightShiftLiteral (left,right,result,ic,1);
7911 /* shift count is unknown then we have to form
7912 a loop get the loop count in B : Note: we take
7913 only the lower order byte since shifting
7914 more that 32 bits make no sense anyway, ( the
7915 largest size of an object can be only 32 bits ) */
7917 //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7918 //pic14_emitcode("inc","b");
7919 //freeAsmop (right,NULL,ic,TRUE);
7920 //aopOp(left,ic,FALSE);
7921 //aopOp(result,ic,FALSE);
7923 /* now move the left to the result if they are not the
7925 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
7926 AOP_SIZE(result) > 1) {
7928 size = AOP_SIZE(result);
7932 l = aopGet(AOP(left),offset,FALSE,TRUE);
7933 if (*l == '@' && IS_AOP_PREG(result)) {
7934 pic14_emitcode("mov","a,%s",l);
7935 aopPut(AOP(result),"a",offset);
7937 aopPut(AOP(result),l,offset);
7939 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
7940 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7946 /* mov the highest order bit to OVR */
7947 tlbl = newiTempLabel(NULL);
7948 tlbl1= newiTempLabel(NULL);
7950 size = AOP_SIZE(result);
7953 pctemp = popGetTempReg(); /* grab a temporary working register. */
7955 emitpcode(POC_MOVFW, popGet(AOP(right),0));
7957 /* offset should be 0, 1 or 3 */
7958 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7960 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
7962 emitpcode(POC_MOVWF, pctemp);
7965 emitpLabel(tlbl->key);
7967 emitpcode(POC_RLFW, popGet(AOP(result),offset));
7968 emitpcode(POC_RRF, popGet(AOP(result),offset));
7971 emitpcode(POC_RRF, popGet(AOP(result),--offset));
7974 emitpcode(POC_DECFSZ, pctemp);
7975 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7976 emitpLabel(tlbl1->key);
7978 popReleaseTempReg(pctemp);
7980 size = AOP_SIZE(result);
7982 pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
7983 pic14_emitcode("rlc","a");
7984 pic14_emitcode("mov","ov,c");
7985 /* if it is only one byte then */
7987 l = aopGet(AOP(left),0,FALSE,FALSE);
7989 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7990 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7991 pic14_emitcode("mov","c,ov");
7992 pic14_emitcode("rrc","a");
7993 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7994 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7995 aopPut(AOP(result),"a",0);
7999 reAdjustPreg(AOP(result));
8000 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8001 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8002 pic14_emitcode("mov","c,ov");
8004 l = aopGet(AOP(result),offset,FALSE,FALSE);
8006 pic14_emitcode("rrc","a");
8007 aopPut(AOP(result),"a",offset--);
8009 reAdjustPreg(AOP(result));
8010 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8011 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8016 freeAsmop(left,NULL,ic,TRUE);
8017 freeAsmop(result,NULL,ic,TRUE);
8018 freeAsmop(right,NULL,ic,TRUE);
8021 /*-----------------------------------------------------------------*/
8022 /* genRightShift - generate code for right shifting */
8023 /*-----------------------------------------------------------------*/
8024 static void genRightShift (iCode *ic)
8026 operand *right, *left, *result;
8030 symbol *tlbl, *tlbl1 ;
8033 /* if signed then we do it the hard way preserve the
8034 sign bit moving it inwards */
8035 retype = getSpec(operandType(IC_RESULT(ic)));
8036 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8038 if (!SPEC_USIGN(retype)) {
8039 genSignedRightShift (ic);
8043 /* signed & unsigned types are treated the same : i.e. the
8044 signed is NOT propagated inwards : quoting from the
8045 ANSI - standard : "for E1 >> E2, is equivalent to division
8046 by 2**E2 if unsigned or if it has a non-negative value,
8047 otherwise the result is implementation defined ", MY definition
8048 is that the sign does not get propagated */
8050 right = IC_RIGHT(ic);
8052 result = IC_RESULT(ic);
8054 aopOp(right,ic,FALSE);
8055 aopOp(left,ic,FALSE);
8056 aopOp(result,ic,FALSE);
8058 /* if the shift count is known then do it
8059 as efficiently as possible */
8060 if (AOP_TYPE(right) == AOP_LIT) {
8061 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 0);
8062 //genRightShiftLiteral (left,right,result,ic, 0);
8066 /* shift count is unknown then we have to form
8067 a loop get the loop count in B : Note: we take
8068 only the lower order byte since shifting
8069 more that 32 bits make no sense anyway, ( the
8070 largest size of an object can be only 32 bits ) */
8072 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8073 pic14_emitcode("inc","b");
8075 /* now move the left to the result if they are not the
8077 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
8078 AOP_SIZE(result) > 1) {
8080 size = AOP_SIZE(result);
8083 l = aopGet(AOP(left),offset,FALSE,TRUE);
8084 if (*l == '@' && IS_AOP_PREG(result)) {
8086 pic14_emitcode("mov","a,%s",l);
8087 aopPut(AOP(result),"a",offset);
8089 aopPut(AOP(result),l,offset);
8094 tlbl = newiTempLabel(NULL);
8095 tlbl1= newiTempLabel(NULL);
8096 size = AOP_SIZE(result);
8099 /* if it is only one byte then */
8102 tlbl = newiTempLabel(NULL);
8103 if (!pic14_sameRegs(AOP(left),AOP(result))) {
8104 emitpcode(POC_MOVFW, popGet(AOP(left),0));
8105 emitpcode(POC_MOVWF, popGet(AOP(result),0));
8108 emitpcode(POC_COMFW, popGet(AOP(right),0));
8109 emitpcode(POC_RLF, popGet(AOP(result),0));
8110 emitpLabel(tlbl->key);
8111 emitpcode(POC_RRF, popGet(AOP(result),0));
8112 emitpcode(POC_ADDLW, popGetLit(1));
8114 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8119 reAdjustPreg(AOP(result));
8120 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8121 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8124 l = aopGet(AOP(result),offset,FALSE,FALSE);
8126 pic14_emitcode("rrc","a");
8127 aopPut(AOP(result),"a",offset--);
8129 reAdjustPreg(AOP(result));
8131 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8132 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8135 freeAsmop(left,NULL,ic,TRUE);
8136 freeAsmop (right,NULL,ic,TRUE);
8137 freeAsmop(result,NULL,ic,TRUE);
8140 /*-----------------------------------------------------------------*/
8141 /* genUnpackBits - generates code for unpacking bits */
8142 /*-----------------------------------------------------------------*/
8143 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype, iCode *ifx)
8146 int offset = 0; /* result byte offset */
8147 int rsize; /* result size */
8148 int rlen = 0; /* remaining bitfield length */
8149 sym_link *etype; /* bitfield type information */
8150 int blen; /* bitfield length */
8151 int bstr; /* bitfield starting bit within byte */
8154 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8155 etype = getSpec(operandType(result));
8156 rsize = getSize (operandType (result));
8157 blen = SPEC_BLEN (etype);
8158 bstr = SPEC_BSTR (etype);
8160 /* single bit field case */
8162 if (ifx) { /* that is for an if statement */
8165 resolveIfx(&rIfx,ifx);
8166 if (ptype == -1) /* direct */
8167 pcop = newpCodeOpBit(AOP(left)->aopu.pcop->name,bstr,0);
8169 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8170 emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8171 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8175 if (ptype == -1) /* direct */
8176 pcop = newpCodeOpBit(AOP(left)->aopu.pcop->name,bstr,0);
8178 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8179 emitpcode(POC_BTFSC,pcop);
8180 emitpcode(POC_BSF,newpCodeOpBit(AOP(result)->aopu.pcop->name,bstr,0));
8182 if (ptype == -1) /* direct */
8183 pcop = newpCodeOpBit(AOP(left)->aopu.pcop->name,bstr,0);
8185 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8186 emitpcode(POC_BTFSS,pcop);
8187 emitpcode(POC_BCF,newpCodeOpBit(AOP(result)->aopu.pcop->name,bstr,0));
8192 /* read the first byte */
8197 // pic14_emitcode("mov","a,@%s",rname);
8198 emitpcode(POC_MOVFW, popCopyReg(&pc_indf));
8202 pic14_emitcode("movx","a,@%s",rname);
8206 pic14_emitcode("movx","a,@dptr");
8210 pic14_emitcode("clr","a");
8211 pic14_emitcode("movc","a","@a+dptr");
8215 pic14_emitcode("lcall","__gptrget");
8219 /* if we have bitdisplacement then it fits */
8220 /* into this byte completely or if length is */
8221 /* less than a byte */
8222 if ((shCnt = SPEC_BSTR(etype)) || blen <= 8) {
8224 /* shift right acc */
8225 AccRsh(left,0,shCnt);
8227 pic14_emitcode("anl","a,#0x%02x",
8228 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
8229 aopPut(AOP(result),"a",offset);
8233 /* bit field did not fit in a byte */
8234 rlen = SPEC_BLEN(etype) - 8;
8235 aopPut(AOP(result),"a",offset++);
8242 pic14_emitcode("inc","%s",rname);
8243 pic14_emitcode("mov","a,@%s",rname);
8247 pic14_emitcode("inc","%s",rname);
8248 pic14_emitcode("movx","a,@%s",rname);
8252 pic14_emitcode("inc","dptr");
8253 pic14_emitcode("movx","a,@dptr");
8257 pic14_emitcode("clr","a");
8258 pic14_emitcode("inc","dptr");
8259 pic14_emitcode("movc","a","@a+dptr");
8263 pic14_emitcode("inc","dptr");
8264 pic14_emitcode("lcall","__gptrget");
8269 /* if we are done */
8273 aopPut(AOP(result),"a",offset++);
8278 pic14_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
8279 aopPut(AOP(result),"a",offset);
8286 /*-----------------------------------------------------------------*/
8287 /* genDataPointerGet - generates code when ptr offset is known */
8288 /*-----------------------------------------------------------------*/
8289 static void genDataPointerGet (operand *left,
8293 int size , offset = 0;
8296 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8299 /* optimization - most of the time, left and result are the same
8300 * address, but different types. for the pic code, we could omit
8303 aopOp(result,ic,TRUE);
8305 if (pic14_sameRegs (AOP(left), AOP(result)))
8308 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8310 //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8312 size = AOP_SIZE(result);
8313 if (size > AOP_SIZE(left)) size = AOP_SIZE(left);
8316 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8317 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8321 freeAsmop(left,NULL,ic,TRUE);
8322 freeAsmop(result,NULL,ic,TRUE);
8325 /*-----------------------------------------------------------------*/
8326 /* genNearPointerGet - pic14_emitcode for near pointer fetch */
8327 /*-----------------------------------------------------------------*/
8328 static void genNearPointerGet (operand *left,
8333 sym_link *ltype = operandType(left);
8334 sym_link *rtype = operandType(result);
8335 sym_link *retype= getSpec(rtype); /* bitfield type information */
8339 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8342 aopOp(left,ic,FALSE);
8344 /* if left is rematerialisable and
8345 result is not bit variable type and
8346 the left is pointer to data space i.e
8347 lower 128 bytes of space */
8348 if (AOP_TYPE(left) == AOP_PCODE && //AOP_TYPE(left) == AOP_IMMD &&
8349 !IS_BITVAR(retype) &&
8350 DCL_TYPE(ltype) == POINTER) {
8351 genDataPointerGet (left,result,ic);
8355 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8356 aopOp (result,ic,FALSE);
8358 /* Check if can access directly instead of via a pointer */
8359 if (PCOP(AOP(left))->type == PO_LITERAL && AOP_SIZE(result) == 1) {
8363 /* If the pointer value is not in a the FSR then need to put it in */
8364 if (!AOP_INPREG(AOP(left)) && !direct) {
8365 /* otherwise get a free pointer register */
8366 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8367 if (PCOP(AOP(result))->type == PO_LITERAL) /* XXX: check me */
8368 emitpcode(POC_MOVLW, popGet(AOP(left),0));
8370 emitpcode(POC_MOVFW, popGet(AOP(left),0));
8371 emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
8376 /* if bitfield then unpack the bits */
8377 if (IS_BITFIELD(retype))
8378 genUnpackBits (result,left,"indf",direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8380 /* we have can just get the values */
8381 int size = AOP_SIZE(result);
8384 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8388 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8390 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8391 if (AOP_TYPE(result) == AOP_LIT) {
8392 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8394 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8396 if (size && !direct)
8397 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8402 /* now some housekeeping stuff */
8404 /* we had to allocate for this iCode */
8405 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8406 freeAsmop(NULL,aop,ic,TRUE);
8408 /* we did not allocate which means left
8409 already in a pointer register, then
8410 if size > 0 && this could be used again
8411 we have to point it back to where it
8413 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8414 if (AOP_SIZE(result) > 1 &&
8415 !OP_SYMBOL(left)->remat &&
8416 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8418 int size = AOP_SIZE(result) - 1;
8420 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8425 freeAsmop(left,NULL,ic,TRUE);
8426 freeAsmop(result,NULL,ic,TRUE);
8430 /*-----------------------------------------------------------------*/
8431 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch */
8432 /*-----------------------------------------------------------------*/
8433 static void genPagedPointerGet (operand *left,
8440 sym_link *rtype, *retype;
8443 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8445 rtype = operandType(result);
8446 retype= getSpec(rtype);
8448 aopOp(left,ic,FALSE);
8450 /* if the value is already in a pointer register
8451 then don't need anything more */
8452 if (!AOP_INPREG(AOP(left))) {
8453 /* otherwise get a free pointer register */
8455 preg = getFreePtr(ic,&aop,FALSE);
8456 pic14_emitcode("mov","%s,%s",
8458 aopGet(AOP(left),0,FALSE,TRUE));
8459 rname = preg->name ;
8461 rname = aopGet(AOP(left),0,FALSE,FALSE);
8463 freeAsmop(left,NULL,ic,TRUE);
8464 aopOp (result,ic,FALSE);
8466 /* if bitfield then unpack the bits */
8467 if (IS_BITFIELD(retype))
8468 genUnpackBits (result,left,rname,PPOINTER,0);
8470 /* we have can just get the values */
8471 int size = AOP_SIZE(result);
8476 pic14_emitcode("movx","a,@%s",rname);
8477 aopPut(AOP(result),"a",offset);
8482 pic14_emitcode("inc","%s",rname);
8486 /* now some housekeeping stuff */
8488 /* we had to allocate for this iCode */
8489 freeAsmop(NULL,aop,ic,TRUE);
8491 /* we did not allocate which means left
8492 already in a pointer register, then
8493 if size > 0 && this could be used again
8494 we have to point it back to where it
8496 if (AOP_SIZE(result) > 1 &&
8497 !OP_SYMBOL(left)->remat &&
8498 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8500 int size = AOP_SIZE(result) - 1;
8502 pic14_emitcode("dec","%s",rname);
8507 freeAsmop(result,NULL,ic,TRUE);
8512 /*-----------------------------------------------------------------*/
8513 /* genFarPointerGet - gget value from far space */
8514 /*-----------------------------------------------------------------*/
8515 static void genFarPointerGet (operand *left,
8516 operand *result, iCode *ic)
8519 sym_link *retype = getSpec(operandType(result));
8522 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8524 aopOp(left,ic,FALSE);
8526 /* if the operand is already in dptr
8527 then we do nothing else we move the value to dptr */
8528 if (AOP_TYPE(left) != AOP_STR) {
8529 /* if this is remateriazable */
8530 if (AOP_TYPE(left) == AOP_IMMD)
8531 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8532 else { /* we need to get it byte by byte */
8533 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8534 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8535 if (options.model == MODEL_FLAT24)
8537 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8541 /* so dptr know contains the address */
8542 freeAsmop(left,NULL,ic,TRUE);
8543 aopOp(result,ic,FALSE);
8545 /* if bit then unpack */
8546 if (IS_BITFIELD(retype))
8547 genUnpackBits(result,left,"dptr",FPOINTER,0);
8549 size = AOP_SIZE(result);
8553 pic14_emitcode("movx","a,@dptr");
8554 aopPut(AOP(result),"a",offset++);
8556 pic14_emitcode("inc","dptr");
8560 freeAsmop(result,NULL,ic,TRUE);
8563 /*-----------------------------------------------------------------*/
8564 /* genCodePointerGet - get value from code space */
8565 /*-----------------------------------------------------------------*/
8566 static void genCodePointerGet (operand *left,
8567 operand *result, iCode *ic)
8570 sym_link *retype = getSpec(operandType(result));
8572 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8574 aopOp(left,ic,FALSE);
8576 /* if the operand is already in dptr
8577 then we do nothing else we move the value to dptr */
8578 if (AOP_TYPE(left) != AOP_STR) {
8579 /* if this is remateriazable */
8580 if (AOP_TYPE(left) == AOP_IMMD)
8581 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8582 else { /* we need to get it byte by byte */
8583 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8584 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8585 if (options.model == MODEL_FLAT24)
8587 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8591 /* so dptr know contains the address */
8592 freeAsmop(left,NULL,ic,TRUE);
8593 aopOp(result,ic,FALSE);
8595 /* if bit then unpack */
8596 if (IS_BITFIELD(retype))
8597 genUnpackBits(result,left,"dptr",CPOINTER,0);
8599 size = AOP_SIZE(result);
8603 pic14_emitcode("clr","a");
8604 pic14_emitcode("movc","a,@a+dptr");
8605 aopPut(AOP(result),"a",offset++);
8607 pic14_emitcode("inc","dptr");
8611 freeAsmop(result,NULL,ic,TRUE);
8614 /*-----------------------------------------------------------------*/
8615 /* genGenPointerGet - gget value from generic pointer space */
8616 /*-----------------------------------------------------------------*/
8617 static void genGenPointerGet (operand *left,
8618 operand *result, iCode *ic)
8621 sym_link *retype = getSpec(operandType(result));
8624 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8625 aopOp(left,ic,FALSE);
8626 aopOp(result,ic,FALSE);
8629 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8631 /* if the operand is already in dptr
8632 then we do nothing else we move the value to dptr */
8633 // if (AOP_TYPE(left) != AOP_STR) {
8634 /* if this is remateriazable */
8635 if (AOP_TYPE(left) == AOP_IMMD) {
8636 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8637 pic14_emitcode("mov","b,#%d",pointerCode(retype));
8639 else { /* we need to get it byte by byte */
8641 emitpcode(POC_MOVFW,popGet(AOP(left),0));
8642 emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8644 size = AOP_SIZE(result);
8648 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8649 emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
8651 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8656 /* so dptr know contains the address */
8658 /* if bit then unpack */
8659 //if (IS_BITFIELD(retype))
8660 // genUnpackBits(result,"dptr",GPOINTER);
8663 freeAsmop(left,NULL,ic,TRUE);
8664 freeAsmop(result,NULL,ic,TRUE);
8668 /*-----------------------------------------------------------------*/
8669 /* genConstPointerGet - get value from const generic pointer space */
8670 /*-----------------------------------------------------------------*/
8671 static void genConstPointerGet (operand *left,
8672 operand *result, iCode *ic)
8674 //sym_link *retype = getSpec(operandType(result));
8675 symbol *albl, *blbl;//, *clbl;
8681 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8682 aopOp(left,ic,FALSE);
8683 aopOp(result,ic,FALSE);
8685 size = AOP_SIZE(result);
8687 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8689 DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
8691 lit = aop_isLitLike (AOP(left));
8692 poc = lit ? POC_MOVLW : POC_MOVFW;
8696 for (i = 0; i < size; i++)
8698 albl = newiTempLabel(NULL);
8699 blbl = newiTempLabel(NULL);
8701 emitpcode(POC_CALL,popGetLabel(albl->key));
8702 pcop = popGetLabel(blbl->key);
8703 emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
8704 emitpcode(POC_GOTO,pcop);
8706 emitpLabel(albl->key);
8707 emitpcode(poc,popGetAddr(AOP(left),1,i));
8708 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
8709 emitpcode(poc,popGetAddr(AOP(left),0,i));
8710 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
8712 emitpLabel(blbl->key);
8713 emitpcode(POC_MOVWF,popGet(AOP(result),i));
8716 albl = newiTempLabel(NULL);
8717 blbl = newiTempLabel(NULL);
8718 //clbl = newiTempLabel(NULL);
8720 emitpcode (POC_GOTO, popGetLabel (blbl->key));
8722 emitpLabel(albl->key);
8723 emitpcode(poc,popGet(AOP(left),1));
8724 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
8725 emitpcode(poc,popGet(AOP(left),0));
8726 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
8728 emitpLabel(blbl->key);
8730 for (i = 0; i < size; i++)
8732 emitpcode(POC_CALL,popGetLabel(albl->key));
8733 /* the next two instructions (plus clbl) might be useless... */
8734 //pcop = popGetLabel(clbl->key);
8735 //emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
8736 //emitpcode(POC_GOTO,pcop);
8737 //emitpLabel(clbl->key);
8740 emitpcode (POC_INCF, popGet (AOP(left), 0));
8742 emitpcode (POC_INCF, popGet (AOP(left), 1));
8744 emitpcode(POC_MOVWF,popGet(AOP(result),i));
8747 /* restore left's value */
8748 emitpcode (POC_MOVLW, popGetLit (size-1));
8749 emitpcode (POC_SUBWF, popGet (AOP(left), 0));
8751 emitpcode (POC_DECF, popGet (AOP(left), 1));
8755 freeAsmop(left,NULL,ic,TRUE);
8756 freeAsmop(result,NULL,ic,TRUE);
8759 /*-----------------------------------------------------------------*/
8760 /* genPointerGet - generate code for pointer get */
8761 /*-----------------------------------------------------------------*/
8762 static void genPointerGet (iCode *ic)
8764 operand *left, *result ;
8765 sym_link *type, *etype;
8769 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8772 result = IC_RESULT(ic) ;
8774 /* depending on the type of pointer we need to
8775 move it to the correct pointer register */
8776 type = operandType(left);
8777 etype = getSpec(type);
8779 if (IS_PTR_CONST(type))
8780 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
8782 /* if left is of type of pointer then it is simple */
8783 if (IS_PTR(type) && !IS_FUNC(type->next))
8784 p_type = DCL_TYPE(type);
8786 /* we have to go by the storage class */
8787 p_type = PTR_TYPE(SPEC_OCLS(etype));
8789 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8791 if (SPEC_OCLS(etype)->codesp ) {
8792 DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
8793 //p_type = CPOINTER ;
8796 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
8797 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
8798 /*p_type = FPOINTER ;*/
8800 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
8801 DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
8802 /* p_type = PPOINTER; */
8804 if (SPEC_OCLS(etype) == idata )
8805 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
8806 /* p_type = IPOINTER; */
8808 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
8809 /* p_type = POINTER ; */
8812 /* now that we have the pointer type we assign
8813 the pointer values */
8818 genNearPointerGet (left,result,ic);
8822 genPagedPointerGet(left,result,ic);
8826 genFarPointerGet (left,result,ic);
8830 genConstPointerGet (left,result,ic);
8831 //pic14_emitcodePointerGet (left,result,ic);
8835 if (IS_CODEPTR(type) || IS_PTR_CONST(type) || SPEC_CONST(etype))
8836 genConstPointerGet (left,result,ic);
8838 genGenPointerGet (left,result,ic);
8841 assert ( !"unhandled pointer type" );
8847 /*-----------------------------------------------------------------*/
8848 /* emitPtrByteGet - for legacy 8051 emits code to get a byte into */
8849 /* A through a pointer register (R0, R1, or DPTR). The original */
8850 /* value of A can be preserved in B. */
8851 /* PIC has to use INDF register. */
8852 /*-----------------------------------------------------------------*/
8854 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
8862 pic14_emitcode ("mov", "b,a");
8863 // pic14_emitcode ("mov", "a,@%s", rname);
8864 emitpcode(POC_MOVFW, popCopyReg(&pc_indf));
8869 pic14_emitcode ("mov", "b,a");
8870 pic14_emitcode ("movx", "a,@%s", rname);
8875 pic14_emitcode ("mov", "b,a");
8876 pic14_emitcode ("movx", "a,@dptr");
8881 pic14_emitcode ("mov", "b,a");
8882 pic14_emitcode ("clr", "a");
8883 pic14_emitcode ("movc", "a,@a+dptr");
8889 pic14_emitcode ("push", "b");
8890 pic14_emitcode ("push", "acc");
8892 pic14_emitcode ("lcall", "__gptrget");
8894 pic14_emitcode ("pop", "b");
8899 /*-----------------------------------------------------------------*/
8900 /* emitPtrByteSet - emits code to set a byte from src through a */
8901 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR). */
8902 /*-----------------------------------------------------------------*/
8904 emitPtrByteSet (char *rname, int p_type, char *src)
8914 pic14_emitcode ("mov", "@%s,a", rname);
8917 // pic14_emitcode ("mov", "@%s,%s", rname, src);
8918 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8923 pic14_emitcode ("movx", "@%s,a", rname);
8928 pic14_emitcode ("movx", "@dptr,a");
8933 pic14_emitcode ("lcall", "__gptrput");
8938 /*-----------------------------------------------------------------*/
8939 /* genPackBits - generates code for packed bit storage */
8940 /*-----------------------------------------------------------------*/
8941 static void genPackBits(sym_link *etype,operand *result,operand *right,char *rname,int p_type)
8943 int offset = 0; /* source byte offset */
8944 int rlen = 0; /* remaining bitfield length */
8945 int blen; /* bitfield length */
8946 int bstr; /* bitfield starting bit within byte */
8947 int litval; /* source literal value (if AOP_LIT) */
8948 unsigned char mask; /* bitmask within current byte */
8951 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8953 blen = SPEC_BLEN (etype);
8954 bstr = SPEC_BSTR (etype);
8956 /* If the bitfield length is less than a byte */
8959 mask = ((unsigned char) (0xFF << (blen + bstr)) |
8960 (unsigned char) (0xFF >> (8 - bstr)));
8962 if (AOP_TYPE (right) == AOP_LIT)
8964 /* Case with a bitfield length <8 and literal source
8966 int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8970 if (AOP(result)->type == AOP_PCODE)
8971 pcop = newpCodeOpBit(AOP(result)->aopu.pcop->name,bstr,0);
8973 pcop = popGet(AOP(result),0);
8974 emitpcode(lit?POC_BSF:POC_BCF,pcop);
8976 emitpcode(lit?POC_BSF:POC_BCF,popCopyReg(&pc_indf));
8980 litval = lit << bstr;
8981 litval &= (~mask) & 0xff;
8983 emitpcode(POC_MOVFW,popGet(AOP(result),0));
8985 emitPtrByteGet (rname, p_type, FALSE);
8986 if ((mask|litval)!=0xff)
8987 emitpcode(POC_ANDLW,popGetLit(mask));
8989 emitpcode(POC_IORLW,popGetLit(litval));
8996 /* 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 */
8997 emitpcode(POC_RLF,popGet(AOP(right),0));
8999 emitpcode(POC_BCF,popGet(AOP(result),0));
9001 emitpcode(POC_BSF,popGet(AOP(result),0));
9002 } else if (p_type!=GPOINTER) {
9003 /* Case with a bitfield length == 1 and no generic pointer
9005 if (AOP_TYPE (right) == AOP_CRY)
9006 pic14_emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9009 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
9010 pic14_emitcode ("rrc","a");
9012 emitPtrByteGet (rname, p_type, FALSE);
9013 pic14_emitcode ("mov","acc.%d,c",bstr);
9019 /* Case with a bitfield length < 8 and arbitrary source
9021 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
9022 /* shift and mask source value */
9023 AccLsh (right,0,bstr);
9024 pic14_emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9025 emitpcode(POC_ANDLW, popGetLit((~mask) & 0xff));
9027 //pushedB = pushB ();
9029 emitpcode(POC_MOVFW,popGet(AOP(result),0));
9031 emitPtrByteGet (rname, p_type, TRUE);
9033 pic14_emitcode ("anl", "a,#0x%02x", mask);
9034 pic14_emitcode ("orl", "a,b");
9035 emitpcode(POC_ANDLW,popGetLit(mask));
9036 emitpcode(POC_IORFW,popGet(AOP(right),0));
9037 if (p_type == GPOINTER)
9038 pic14_emitcode ("pop", "b");
9045 emitpcode(POC_MOVWF,popGet(AOP(result),0));
9047 emitPtrByteSet (rname, p_type, "a");
9051 /* Bit length is greater than 7 bits. In this case, copy */
9052 /* all except the partial byte at the end */
9053 for (rlen=blen;rlen>=8;rlen-=8)
9055 emitPtrByteSet (rname, p_type,
9056 aopGet (AOP (right), offset++, FALSE, TRUE) );
9058 pic14_emitcode ("inc", "%s", rname);
9061 /* If there was a partial byte at the end */
9064 mask = (((unsigned char) -1 << rlen) & 0xff);
9066 if (AOP_TYPE (right) == AOP_LIT)
9068 /* Case with partial byte and literal source
9070 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9071 litval >>= (blen-rlen);
9072 litval &= (~mask) & 0xff;
9073 emitPtrByteGet (rname, p_type, FALSE);
9074 if ((mask|litval)!=0xff)
9075 pic14_emitcode ("anl","a,#0x%02x", mask);
9077 pic14_emitcode ("orl","a,#0x%02x", litval);
9082 /* Case with partial byte and arbitrary source
9084 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
9085 pic14_emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9087 //pushedB = pushB ();
9088 /* transfer A to B and get next byte */
9089 emitPtrByteGet (rname, p_type, TRUE);
9091 pic14_emitcode ("anl", "a,#0x%02x", mask);
9092 pic14_emitcode ("orl", "a,b");
9093 if (p_type == GPOINTER)
9094 pic14_emitcode ("pop", "b");
9098 emitPtrByteSet (rname, p_type, "a");
9103 /*-----------------------------------------------------------------*/
9104 /* SetIrp - Set IRP bit */
9105 /*-----------------------------------------------------------------*/
9106 void SetIrp(operand *result) {
9108 if (AOP_TYPE(result) == AOP_LIT) {
9109 unsigned lit = (unsigned)operandLitValue(result);
9110 emitpcode((lit&0x100)?POC_BSF:POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
9112 if (PCOP(AOP(result))->type == PO_LITERAL) {
9113 int addrs = PCOL(AOP(result))->lit;
9114 emitpcode((addrs&0x100)?POC_BSF:POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
9116 emitpcode(POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT)); /* always ensure this is clear as it may have previouly been set */
9117 if(AOP_SIZE(result) > 1) {
9118 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
9119 emitpcode(POC_BSF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
9125 /*-----------------------------------------------------------------*/
9126 /* genDataPointerSet - remat pointer to data space */
9127 /*-----------------------------------------------------------------*/
9128 static void genDataPointerSet(operand *right,
9132 int size, offset = 0 ;
9133 char *l, buffer[256];
9136 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9137 aopOp(right,ic,FALSE);
9139 l = aopGet(AOP(result),0,FALSE,TRUE);
9140 size = AOP_SIZE(right);
9142 if ( AOP_TYPE(result) == AOP_PCODE) {
9143 fprintf(stderr,"genDataPointerSet %s, %d\n",
9144 AOP(result)->aopu.pcop->name,
9145 PCOI(AOP(result)->aopu.pcop)->offset);
9149 // tsd, was l+1 - the underline `_' prefix was being stripped
9151 emitpComment ("%s:%u: size=%i, offset=%i", __FILE__,__LINE__, size, offset);
9153 sprintf(buffer,"(%s + %d)",l,offset);
9154 fprintf(stderr,"%s:%i: oops %s (%i, AOP_LIT=%i)\n",__FILE__,__LINE__,buffer, AOP_TYPE(right), AOP_LIT);
9156 sprintf(buffer,"%s",l);
9158 if (AOP_TYPE(right) == AOP_LIT) {
9159 unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9160 lit = lit >> (8*offset);
9162 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9163 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9165 emitpcode(POC_CLRF, popGet(AOP(result),offset));
9168 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9169 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9175 freeAsmop(right,NULL,ic,TRUE);
9176 freeAsmop(result,NULL,ic,TRUE);
9179 /*-----------------------------------------------------------------*/
9180 /* genNearPointerSet - pic14_emitcode for near pointer put */
9181 /*-----------------------------------------------------------------*/
9182 static void genNearPointerSet (operand *right,
9187 sym_link *ptype = operandType(result);
9188 sym_link *retype = getSpec(operandType(right));
9189 sym_link *letype = getSpec(ptype);
9194 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9195 aopOp(result,ic,FALSE);
9198 /* if the result is rematerializable &
9199 in data space & not a bit variable */
9200 //if (AOP_TYPE(result) == AOP_IMMD &&
9201 if (AOP_TYPE(result) == AOP_PCODE &&
9202 DCL_TYPE(ptype) == POINTER &&
9203 !IS_BITVAR (retype) &&
9204 !IS_BITVAR (letype)) {
9205 genDataPointerSet (right,result,ic);
9206 freeAsmop(result,NULL,ic,TRUE);
9210 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9211 aopOp(right,ic,FALSE);
9212 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9214 /* Check if can access directly instead of via a pointer */
9215 if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9219 /* If the pointer value is not in a the FSR then need to put it in */
9220 if (!AOP_INPREG(AOP(result)) && !direct) {
9221 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9222 if (PCOP(AOP(result))->type == PO_LITERAL)
9223 emitpcode(POC_MOVLW, popGet(AOP(result),0));
9225 emitpcode(POC_MOVFW, popGet(AOP(result),0));
9226 emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
9229 /* Must set/reset IRP bit for use with FSR. */
9230 /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9234 /* if bitfield then unpack the bits */
9235 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9236 genPackBits ((IS_BITFIELD (retype) ? retype : letype), result, right, "indf", direct?-1:POINTER);
9238 /* we have can just get the values */
9239 int size = AOP_SIZE(right);
9242 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9244 char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9246 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9248 if (AOP_TYPE(right) == AOP_LIT) {
9249 emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9251 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9254 emitpcode(POC_MOVWF,popGet(AOP(result),0));
9256 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9258 if (size && !direct)
9259 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9264 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9265 /* now some housekeeping stuff */
9267 /* we had to allocate for this iCode */
9268 freeAsmop(NULL,aop,ic,TRUE);
9270 /* we did not allocate which means left
9271 already in a pointer register, then
9272 if size > 0 && this could be used again
9273 we have to point it back to where it
9275 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9276 if (AOP_SIZE(right) > 1 &&
9277 !OP_SYMBOL(result)->remat &&
9278 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9280 int size = AOP_SIZE(right) - 1;
9282 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9286 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9289 freeAsmop(right,NULL,ic,TRUE);
9290 freeAsmop(result,NULL,ic,TRUE);
9293 /*-----------------------------------------------------------------*/
9294 /* genPagedPointerSet - pic14_emitcode for Paged pointer put */
9295 /*-----------------------------------------------------------------*/
9296 static void genPagedPointerSet (operand *right,
9306 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9308 retype= getSpec(operandType(right));
9310 aopOp(result,ic,FALSE);
9312 /* if the value is already in a pointer register
9313 then don't need anything more */
9314 if (!AOP_INPREG(AOP(result))) {
9315 /* otherwise get a free pointer register */
9317 preg = getFreePtr(ic,&aop,FALSE);
9318 pic14_emitcode("mov","%s,%s",
9320 aopGet(AOP(result),0,FALSE,TRUE));
9321 rname = preg->name ;
9323 rname = aopGet(AOP(result),0,FALSE,FALSE);
9325 freeAsmop(result,NULL,ic,TRUE);
9326 aopOp (right,ic,FALSE);
9328 /* if bitfield then unpack the bits */
9329 if (IS_BITFIELD(retype))
9330 genPackBits (retype,result,right,rname,PPOINTER);
9332 /* we have can just get the values */
9333 int size = AOP_SIZE(right);
9337 l = aopGet(AOP(right),offset,FALSE,TRUE);
9340 pic14_emitcode("movx","@%s,a",rname);
9343 pic14_emitcode("inc","%s",rname);
9349 /* now some housekeeping stuff */
9351 /* we had to allocate for this iCode */
9352 freeAsmop(NULL,aop,ic,TRUE);
9354 /* we did not allocate which means left
9355 already in a pointer register, then
9356 if size > 0 && this could be used again
9357 we have to point it back to where it
9359 if (AOP_SIZE(right) > 1 &&
9360 !OP_SYMBOL(result)->remat &&
9361 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9363 int size = AOP_SIZE(right) - 1;
9365 pic14_emitcode("dec","%s",rname);
9370 freeAsmop(right,NULL,ic,TRUE);
9375 /*-----------------------------------------------------------------*/
9376 /* genFarPointerSet - set value from far space */
9377 /*-----------------------------------------------------------------*/
9378 static void genFarPointerSet (operand *right,
9379 operand *result, iCode *ic)
9382 sym_link *retype = getSpec(operandType(right));
9385 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9386 aopOp(result,ic,FALSE);
9388 /* if the operand is already in dptr
9389 then we do nothing else we move the value to dptr */
9390 if (AOP_TYPE(result) != AOP_STR) {
9391 /* if this is remateriazable */
9392 if (AOP_TYPE(result) == AOP_IMMD)
9393 pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9394 else { /* we need to get it byte by byte */
9395 pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9396 pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9397 if (options.model == MODEL_FLAT24)
9399 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9403 /* so dptr know contains the address */
9404 freeAsmop(result,NULL,ic,TRUE);
9405 aopOp(right,ic,FALSE);
9407 /* if bit then unpack */
9408 if (IS_BITFIELD(retype))
9409 genPackBits(retype,result,right,"dptr",FPOINTER);
9411 size = AOP_SIZE(right);
9415 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9417 pic14_emitcode("movx","@dptr,a");
9419 pic14_emitcode("inc","dptr");
9423 freeAsmop(right,NULL,ic,TRUE);
9426 /*-----------------------------------------------------------------*/
9427 /* genGenPointerSet - set value from generic pointer space */
9428 /*-----------------------------------------------------------------*/
9429 static void genGenPointerSet (operand *right,
9430 operand *result, iCode *ic)
9432 sym_link *ptype = operandType(result);
9433 sym_link *retype = getSpec(operandType(right));
9434 sym_link *letype = getSpec (ptype);
9437 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9439 aopOp(result,ic,FALSE);
9440 aopOp(right,ic,FALSE);
9442 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9444 /* if the operand is already in dptr
9445 then we do nothing else we move the value to dptr */
9446 if (AOP_TYPE(result) != AOP_STR) {
9447 /* if this is remateriazable */
9448 if (AOP_TYPE(result) == AOP_IMMD) {
9449 pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9450 pic14_emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
9453 emitpcode(POC_MOVFW,popGet(AOP(result),0));
9454 emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
9456 /* Must set/reset IRP bit for use with FSR. */
9457 /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9462 /* if bitfield then unpack the bits */
9463 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9464 genPackBits ((IS_BITFIELD (retype) ? retype : letype),result, right, "indf", POINTER);
9466 /* we have can just get the values */
9467 int size = AOP_SIZE(right);
9470 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9472 char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9474 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9476 if (AOP_TYPE(right) == AOP_LIT) {
9477 emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9479 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9481 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9484 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9489 freeAsmop(right,NULL,ic,TRUE);
9490 freeAsmop(result,NULL,ic,TRUE);
9493 /*-----------------------------------------------------------------*/
9494 /* genPointerSet - stores the value into a pointer location */
9495 /*-----------------------------------------------------------------*/
9496 static void genPointerSet (iCode *ic)
9498 operand *right, *result ;
9499 sym_link *type, *etype;
9503 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9505 right = IC_RIGHT(ic);
9506 result = IC_RESULT(ic) ;
9508 /* depending on the type of pointer we need to
9509 move it to the correct pointer register */
9510 type = operandType(result);
9511 etype = getSpec(type);
9512 /* if left is of type of pointer then it is simple */
9513 if (IS_PTR(type) && !IS_FUNC(type->next)) {
9514 p_type = DCL_TYPE(type);
9517 /* we have to go by the storage class */
9518 p_type = PTR_TYPE(SPEC_OCLS(etype));
9520 /* if (SPEC_OCLS(etype)->codesp ) { */
9521 /* p_type = CPOINTER ; */
9524 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9525 /* p_type = FPOINTER ; */
9527 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9528 /* p_type = PPOINTER ; */
9530 /* if (SPEC_OCLS(etype) == idata ) */
9531 /* p_type = IPOINTER ; */
9533 /* p_type = POINTER ; */
9536 /* now that we have the pointer type we assign
9537 the pointer values */
9542 genNearPointerSet (right,result,ic);
9546 genPagedPointerSet (right,result,ic);
9550 genFarPointerSet (right,result,ic);
9554 genGenPointerSet (right,result,ic);
9558 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9559 "genPointerSet: illegal pointer type");
9563 /*-----------------------------------------------------------------*/
9564 /* genIfx - generate code for Ifx statement */
9565 /*-----------------------------------------------------------------*/
9566 static void genIfx (iCode *ic, iCode *popIc)
9568 operand *cond = IC_COND(ic);
9572 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9574 aopOp(cond,ic,FALSE);
9576 /* get the value into acc */
9577 if (AOP_TYPE(cond) != AOP_CRY)
9578 pic14_toBoolean(cond);
9581 /* the result is now in the accumulator */
9582 freeAsmop(cond,NULL,ic,TRUE);
9584 /* if there was something to be popped then do it */
9588 /* if the condition is a bit variable */
9589 if (isbit && IS_ITEMP(cond) &&
9591 genIfxJump(ic,SPIL_LOC(cond)->rname);
9592 DEBUGpic14_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9595 if (isbit && !IS_ITEMP(cond))
9596 genIfxJump(ic,OP_SYMBOL(cond)->rname);
9604 /*-----------------------------------------------------------------*/
9605 /* genAddrOf - generates code for address of */
9606 /*-----------------------------------------------------------------*/
9607 static void genAddrOf (iCode *ic)
9609 operand *right, *result, *left;
9613 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9616 //aopOp(IC_RESULT(ic),ic,FALSE);
9618 aopOp((left=IC_LEFT(ic)),ic,FALSE);
9619 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9620 aopOp((result=IC_RESULT(ic)),ic,TRUE);
9622 DEBUGpic14_AopType(__LINE__,left,right,result);
9623 assert (IS_SYMOP (left));
9625 /* sanity check: generic pointers to code space are not yet supported,
9626 * pionters to codespace must not be assigned addresses of __data values. */
9628 fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9629 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)));
9630 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)));
9631 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)));
9632 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)));
9635 if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9636 fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9637 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9638 OP_SYMBOL(left)->name);
9639 } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9640 fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9641 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9642 OP_SYMBOL(left)->name);
9645 size = AOP_SIZE(IC_RESULT(ic));
9649 /* fixing bug #863624, reported from (errolv) */
9650 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9651 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9654 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9655 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9660 freeAsmop(left,NULL,ic,FALSE);
9661 freeAsmop(result,NULL,ic,TRUE);
9666 /*-----------------------------------------------------------------*/
9667 /* genFarFarAssign - assignment when both are in far space */
9668 /*-----------------------------------------------------------------*/
9669 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9671 int size = AOP_SIZE(right);
9674 /* first push the right side on to the stack */
9676 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9678 pic14_emitcode ("push","acc");
9681 freeAsmop(right,NULL,ic,FALSE);
9682 /* now assign DPTR to result */
9683 aopOp(result,ic,FALSE);
9684 size = AOP_SIZE(result);
9686 pic14_emitcode ("pop","acc");
9687 aopPut(AOP(result),"a",--offset);
9689 freeAsmop(result,NULL,ic,FALSE);
9694 /*-----------------------------------------------------------------*/
9695 /* genAssign - generate code for assignment */
9696 /*-----------------------------------------------------------------*/
9697 static void genAssign (iCode *ic)
9699 operand *result, *right;
9700 int size, offset,know_W;
9701 unsigned long lit = 0L;
9703 result = IC_RESULT(ic);
9704 right = IC_RIGHT(ic) ;
9707 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9709 /* if they are the same */
9710 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9713 aopOp(right,ic,FALSE);
9714 aopOp(result,ic,TRUE);
9716 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9718 /* if they are the same registers */
9719 if (pic14_sameRegs(AOP(right),AOP(result)))
9722 /* special case: assign from __code */
9723 if (!IS_ITEMP(right) /* --> iTemps never reside in __code */
9724 && IS_SYMOP (right) /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
9725 && !IS_FUNC(OP_SYM_TYPE(right)) /* --> we would want its address instead of the first instruction */
9726 && !IS_CODEPTR(OP_SYM_TYPE(right)) /* --> get symbols address instread */
9727 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
9729 emitpComment ("genAssign from CODESPACE");
9730 genConstPointerGet (right, result, ic);
9734 /* just for symmetry reasons... */
9735 if (!IS_ITEMP(result)
9736 && IS_SYMOP (result)
9737 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
9739 assert ( !"cannot write to CODESPACE" );
9742 /* if the result is a bit */
9743 if (AOP_TYPE(result) == AOP_CRY) {
9745 /* if the right size is a literal then
9746 we know what the value is */
9747 if (AOP_TYPE(right) == AOP_LIT) {
9749 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9750 popGet(AOP(result),0));
9752 if (((int) operandLitValue(right)))
9753 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9754 AOP(result)->aopu.aop_dir,
9755 AOP(result)->aopu.aop_dir);
9757 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9758 AOP(result)->aopu.aop_dir,
9759 AOP(result)->aopu.aop_dir);
9763 /* the right is also a bit variable */
9764 if (AOP_TYPE(right) == AOP_CRY) {
9765 emitpcode(POC_BCF, popGet(AOP(result),0));
9766 emitpcode(POC_BTFSC, popGet(AOP(right),0));
9767 emitpcode(POC_BSF, popGet(AOP(result),0));
9769 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9770 AOP(result)->aopu.aop_dir,
9771 AOP(result)->aopu.aop_dir);
9772 pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
9773 AOP(right)->aopu.aop_dir,
9774 AOP(right)->aopu.aop_dir);
9775 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9776 AOP(result)->aopu.aop_dir,
9777 AOP(result)->aopu.aop_dir);
9782 emitpcode(POC_BCF, popGet(AOP(result),0));
9783 pic14_toBoolean(right);
9785 emitpcode(POC_BSF, popGet(AOP(result),0));
9786 //aopPut(AOP(result),"a",0);
9790 /* bit variables done */
9792 size = AOP_SIZE(result);
9794 if(AOP_TYPE(right) == AOP_LIT)
9795 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9797 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
9798 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9799 if(aopIdx(AOP(result),0) == 4) {
9800 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9801 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9802 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9805 DEBUGpic14_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
9810 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9811 if(AOP_TYPE(right) == AOP_LIT) {
9813 if(know_W != (int)(lit&0xff))
9814 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
9816 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9818 emitpcode(POC_CLRF, popGet(AOP(result),offset));
9822 } else if (AOP_TYPE(right) == AOP_CRY) {
9823 emitpcode(POC_CLRF, popGet(AOP(result),offset));
9825 emitpcode(POC_BTFSS, popGet(AOP(right),0));
9826 emitpcode(POC_INCF, popGet(AOP(result),0));
9829 mov2w (AOP(right), offset);
9830 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9838 freeAsmop (right,NULL,ic,FALSE);
9839 freeAsmop (result,NULL,ic,TRUE);
9842 /*-----------------------------------------------------------------*/
9843 /* genJumpTab - genrates code for jump table */
9844 /*-----------------------------------------------------------------*/
9845 static void genJumpTab (iCode *ic)
9851 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9853 aopOp(IC_JTCOND(ic),ic,FALSE);
9854 /* get the condition into accumulator */
9855 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9857 /* multiply by three */
9858 pic14_emitcode("add","a,acc");
9859 pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9861 jtab = newiTempLabel(NULL);
9862 pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9863 pic14_emitcode("jmp","@a+dptr");
9864 pic14_emitcode("","%05d_DS_:",jtab->key+100);
9866 emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
9867 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
9868 emitpcode(POC_MOVLW, popGetLabel(jtab->key));
9869 emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
9871 emitpcode(POC_INCF, popCopyReg(&pc_pclath));
9872 emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
9873 emitpLabel(jtab->key);
9875 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9877 /* now generate the jump labels */
9878 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9879 jtab = setNextItem(IC_JTLABELS(ic))) {
9880 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
9881 emitpcode(POC_GOTO,popGetLabel(jtab->key));
9887 /*-----------------------------------------------------------------*/
9888 /* genMixedOperation - gen code for operators between mixed types */
9889 /*-----------------------------------------------------------------*/
9891 TSD - Written for the PIC port - but this unfortunately is buggy.
9892 This routine is good in that it is able to efficiently promote
9893 types to different (larger) sizes. Unfortunately, the temporary
9894 variables that are optimized out by this routine are sometimes
9895 used in other places. So until I know how to really parse the
9896 iCode tree, I'm going to not be using this routine :(.
9898 static int genMixedOperation (iCode *ic)
9902 operand *result = IC_RESULT(ic);
9903 sym_link *ctype = operandType(IC_LEFT(ic));
9904 operand *right = IC_RIGHT(ic);
9910 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9912 pic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
9918 nextright = IC_RIGHT(nextic);
9919 nextleft = IC_LEFT(nextic);
9920 nextresult = IC_RESULT(nextic);
9922 aopOp(right,ic,FALSE);
9923 aopOp(result,ic,FALSE);
9924 aopOp(nextright, nextic, FALSE);
9925 aopOp(nextleft, nextic, FALSE);
9926 aopOp(nextresult, nextic, FALSE);
9928 if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9934 pic14_emitcode(";remove right +","");
9936 } else if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9942 pic14_emitcode(";remove left +","");
9946 big = AOP_SIZE(nextleft);
9947 small = AOP_SIZE(nextright);
9949 switch(nextic->op) {
9952 pic14_emitcode(";optimize a +","");
9953 /* if unsigned or not an integral type */
9954 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9955 pic14_emitcode(";add a bit to something","");
9958 pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9960 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9961 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9962 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9964 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9972 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9973 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9974 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9977 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9979 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
9980 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9981 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9982 pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9983 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9986 pic14_emitcode("rlf","known_zero,w");
9993 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9994 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9995 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9997 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10007 freeAsmop(right,NULL,ic,TRUE);
10008 freeAsmop(result,NULL,ic,TRUE);
10009 freeAsmop(nextright,NULL,ic,TRUE);
10010 freeAsmop(nextleft,NULL,ic,TRUE);
10012 nextic->generated = 1;
10019 /*-----------------------------------------------------------------*/
10020 /* genCast - gen code for casting */
10021 /*-----------------------------------------------------------------*/
10022 static void genCast (iCode *ic)
10024 operand *result = IC_RESULT(ic);
10025 sym_link *ctype = operandType(IC_LEFT(ic));
10026 sym_link *rtype = operandType(IC_RIGHT(ic));
10027 operand *right = IC_RIGHT(ic);
10031 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10032 /* if they are equivalent then do nothing */
10033 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10036 aopOp(right,ic,FALSE) ;
10037 aopOp(result,ic,FALSE);
10039 DEBUGpic14_AopType(__LINE__,NULL,right,result);
10041 /* if the result is a bit */
10042 if (AOP_TYPE(result) == AOP_CRY) {
10043 /* if the right size is a literal then
10044 we know what the value is */
10045 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10046 if (AOP_TYPE(right) == AOP_LIT) {
10048 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10049 popGet(AOP(result),0));
10051 if (((int) operandLitValue(right)))
10052 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
10053 AOP(result)->aopu.aop_dir,
10054 AOP(result)->aopu.aop_dir);
10056 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
10057 AOP(result)->aopu.aop_dir,
10058 AOP(result)->aopu.aop_dir);
10063 /* the right is also a bit variable */
10064 if (AOP_TYPE(right) == AOP_CRY) {
10067 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10069 pic14_emitcode("clrc","");
10070 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10071 AOP(right)->aopu.aop_dir,
10072 AOP(right)->aopu.aop_dir);
10073 aopPut(AOP(result),"c",0);
10077 /* we need to or */
10078 if (AOP_TYPE(right) == AOP_REG) {
10079 emitpcode(POC_BCF, popGet(AOP(result),0));
10080 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
10081 emitpcode(POC_BSF, popGet(AOP(result),0));
10083 pic14_toBoolean(right);
10084 aopPut(AOP(result),"a",0);
10088 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10090 size = AOP_SIZE(result);
10092 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10094 emitpcode(POC_CLRF, popGet(AOP(result),0));
10095 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10096 emitpcode(POC_INCF, popGet(AOP(result),0));
10099 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
10104 /* if they are the same size : or less */
10105 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10107 /* if they are in the same place */
10108 if (pic14_sameRegs(AOP(right),AOP(result)))
10111 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10112 if (IS_PTR_CONST(rtype))
10113 DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10114 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10115 DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10117 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10118 emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10119 emitpcode(POC_MOVWF, popGet(AOP(result),0));
10120 emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10121 emitpcode(POC_MOVWF, popGet(AOP(result),1));
10122 if(AOP_SIZE(result) <2)
10123 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10127 /* if they in different places then copy */
10128 size = AOP_SIZE(result);
10131 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10132 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10134 //aopPut(AOP(result),
10135 // aopGet(AOP(right),offset,FALSE,FALSE),
10145 /* if the result is of type pointer */
10146 if (IS_PTR(ctype)) {
10149 sym_link *type = operandType(right);
10150 sym_link *etype = getSpec(type);
10151 DEBUGpic14_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
10153 /* pointer to generic pointer */
10154 if (IS_GENPTR(ctype)) {
10158 p_type = DCL_TYPE(type);
10160 /* we have to go by the storage class */
10161 p_type = PTR_TYPE(SPEC_OCLS(etype));
10163 /* if (SPEC_OCLS(etype)->codesp ) */
10164 /* p_type = CPOINTER ; */
10166 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10167 /* p_type = FPOINTER ; */
10169 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10170 /* p_type = PPOINTER; */
10172 /* if (SPEC_OCLS(etype) == idata ) */
10173 /* p_type = IPOINTER ; */
10175 /* p_type = POINTER ; */
10178 /* the first two bytes are known */
10179 DEBUGpic14_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
10180 size = GPTRSIZE - 1;
10183 if(offset < AOP_SIZE(right)) {
10184 DEBUGpic14_emitcode("; ***","%s %d - pointer cast3",__FUNCTION__,__LINE__);
10185 if ((AOP_TYPE(right) == AOP_PCODE) &&
10186 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10187 emitpcode(POC_MOVLW, popGetAddr(AOP(right),offset,0));
10188 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10190 aopPut(AOP(result),
10191 aopGet(AOP(right),offset,FALSE,FALSE),
10195 emitpcode(POC_CLRF,popGet(AOP(result),offset));
10198 /* the last byte depending on type */
10202 emitpcode(POC_CLRF,popGet(AOP(result),GPTRSIZE - 1));
10205 pic14_emitcode(";BUG!? ","%d",__LINE__);
10209 pic14_emitcode(";BUG!? ","%d",__LINE__);
10213 pic14_emitcode(";BUG!? ","%d",__LINE__);
10218 /* this should never happen */
10219 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10220 "got unknown pointer type");
10223 //aopPut(AOP(result),l, GPTRSIZE - 1);
10227 /* just copy the pointers */
10228 size = AOP_SIZE(result);
10231 aopPut(AOP(result),
10232 aopGet(AOP(right),offset,FALSE,FALSE),
10241 /* so we now know that the size of destination is greater
10242 than the size of the source.
10243 Now, if the next iCode is an operator then we might be
10244 able to optimize the operation without performing a cast.
10246 if(genMixedOperation(ic))
10249 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10251 /* we move to result for the size of source */
10252 size = AOP_SIZE(right);
10255 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10256 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10260 /* now depending on the sign of the destination */
10261 size = AOP_SIZE(result) - AOP_SIZE(right);
10262 /* if unsigned or not an integral type */
10263 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
10265 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
10267 /* we need to extend the sign :{ */
10270 /* Save one instruction of casting char to int */
10271 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10272 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10273 emitpcode(POC_DECF, popGet(AOP(result),offset));
10275 emitpcodeNULLop(POC_CLRW);
10278 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10280 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),offset,FALSE,FALSE),7,0));
10282 emitpcode(POC_MOVLW, popGetLit(0xff));
10285 emitpcode(POC_MOVWF, popGet(AOP(result),offset++));
10290 freeAsmop(right,NULL,ic,TRUE);
10291 freeAsmop(result,NULL,ic,TRUE);
10295 /*-----------------------------------------------------------------*/
10296 /* genDjnz - generate decrement & jump if not zero instrucion */
10297 /*-----------------------------------------------------------------*/
10298 static int genDjnz (iCode *ic, iCode *ifx)
10300 symbol *lbl, *lbl1;
10302 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10307 /* if the if condition has a false label
10308 then we cannot save */
10312 /* if the minus is not of the form
10314 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10315 !IS_OP_LITERAL(IC_RIGHT(ic)))
10318 if (operandLitValue(IC_RIGHT(ic)) != 1)
10321 /* if the size of this greater than one then no
10323 if (getSize(operandType(IC_RESULT(ic))) > 1)
10326 /* otherwise we can save BIG */
10327 lbl = newiTempLabel(NULL);
10328 lbl1= newiTempLabel(NULL);
10330 aopOp(IC_RESULT(ic),ic,FALSE);
10332 if (IS_AOP_PREG(IC_RESULT(ic))) {
10333 pic14_emitcode("dec","%s",
10334 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10335 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10336 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10340 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10341 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10343 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10344 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10347 /* pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10348 /* pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10349 /* pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10350 /* pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10353 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10354 ifx->generated = 1;
10358 /*-----------------------------------------------------------------*/
10359 /* genReceive - generate code for a receive iCode */
10360 /*-----------------------------------------------------------------*/
10361 static void genReceive (iCode *ic)
10364 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10366 if (isOperandInFarSpace(IC_RESULT(ic)) &&
10367 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10368 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10370 int size = getSize(operandType(IC_RESULT(ic)));
10371 int offset = fReturnSizePic - size;
10373 pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10374 fReturn[fReturnSizePic - offset - 1] : "acc"));
10377 aopOp(IC_RESULT(ic),ic,FALSE);
10378 size = AOP_SIZE(IC_RESULT(ic));
10381 pic14_emitcode ("pop","acc");
10382 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10387 aopOp(IC_RESULT(ic),ic,FALSE);
10389 assignResultValue(IC_RESULT(ic));
10392 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10395 /*-----------------------------------------------------------------*/
10396 /* genDummyRead - generate code for dummy read of volatiles */
10397 /*-----------------------------------------------------------------*/
10399 genDummyRead (iCode * ic)
10402 pic14_emitcode ("; genDummyRead","");
10403 pic14_emitcode ("; not implemented","");
10408 /*-----------------------------------------------------------------*/
10409 /* genpic14Code - generate code for pic14 based controllers */
10410 /*-----------------------------------------------------------------*/
10412 * At this point, ralloc.c has gone through the iCode and attempted
10413 * to optimize in a way suitable for a PIC. Now we've got to generate
10414 * PIC instructions that correspond to the iCode.
10416 * Once the instructions are generated, we'll pass through both the
10417 * peep hole optimizer and the pCode optimizer.
10418 *-----------------------------------------------------------------*/
10420 void genpic14Code (iCode *lic)
10427 lineHead = lineCurr = NULL;
10429 pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10432 /* if debug information required */
10433 if (options.debug && currFunc) {
10435 debugFile->writeFunction (currFunc, lic);
10440 for (ic = lic ; ic ; ic = ic->next ) {
10442 //DEBUGpic14_emitcode(";ic","");
10443 //fprintf (stderr, "in ic loop\n");
10444 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10445 //ic->lineno, printCLine(ic->filename, ic->lineno));
10447 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10449 //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10450 cline = printCLine (ic->filename, ic->lineno);
10451 if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10452 addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10453 //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10456 if (options.iCodeInAsm) {
10457 emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10459 /* if the result is marked as
10460 spilt and rematerializable or code for
10461 this has already been generated then
10463 if (resultRemat(ic) || ic->generated )
10466 /* depending on the operation */
10485 /* IPOP happens only when trying to restore a
10486 spilt live range, if there is an ifx statement
10487 following this pop then the if statement might
10488 be using some of the registers being popped which
10489 would destory the contents of the register so
10490 we need to check for this condition and handle it */
10492 ic->next->op == IFX &&
10493 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10494 genIfx (ic->next,ic);
10512 genEndFunction (ic);
10532 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10549 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
10553 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10560 /* note these two are xlated by algebraic equivalence
10561 during parsing SDCC.y */
10562 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10563 "got '>=' or '<=' shouldn't have come here");
10567 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10579 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10583 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10587 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10611 genRightShift (ic);
10614 case GET_VALUE_AT_ADDRESS:
10619 if (POINTER_SET(ic))
10646 addSet(&_G.sendSet,ic);
10649 case DUMMY_READ_VOLATILE:
10659 /* now we are ready to call the
10660 peep hole optimizer */
10661 if (!options.nopeep) {
10662 peepHole (&lineHead);
10664 /* now do the actual printing */
10665 printLine (lineHead,codeOutFile);
10668 DFPRINTF((stderr,"printing pBlock\n\n"));
10669 printpBlock(stdout,pb);
10676 aop_isLitLike (asmop *aop)
10679 if (aop->type == AOP_LIT) return 1;
10680 if (aop->type == AOP_IMMD) return 1;
10681 if ((aop->type == AOP_PCODE) &&
10682 ((aop->aopu.pcop->type == PO_LITERAL) || (aop->aopu.pcop->type == PO_IMMEDIATE)))
10684 /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10685 * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10692 op_isLitLike (operand *op)
10695 if (aop_isLitLike (AOP(op))) return 1;