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)
8 cont'd - Raphael Neider <rneider AT web.de> (2005)
10 This program is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the
12 Free Software Foundation; either version 2, or (at your option) any
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 In other words, you are welcome to use, share and improve this program.
25 You are forbidden to forbid anyone else to use, share and improve
26 what you give them. Help stamp out software-hoarding!
29 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
30 Made everything static
31 -------------------------------------------------------------------------*/
37 #include "SDCCglobl.h"
41 #include "SDCCpeeph.h"
47 /* The PIC port(s) need not differentiate between POINTER and FPOINTER. */
48 #define PIC_IS_DATA_PTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
49 #define PIC_IS_FARPTR(x) (PIC_IS_DATA_PTR(x))
51 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
52 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
53 void genMult8X8_8 (operand *, operand *,operand *);
54 extern void printpBlock(FILE *of, pBlock *pb);
56 static int labelOffset=0;
57 extern int debug_verbose;
58 extern int pic14_hasInterrupt;
59 //static int optimized_for_speed = 0;
61 /* max_key keeps track of the largest label number used in
62 a function. This is then used to adjust the label offset
63 for the next function.
66 static int GpsuedoStkPtr=0;
67 static int pic14_inISR = 0;
69 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
70 extern char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
71 const char *AopType(short type);
73 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0x00ff)
75 /* this is the down and dirty file with all kinds of
76 kludgy & hacky stuff. This is what it is all about
77 CODE GENERATION for a specific MCU . some of the
78 routines may be reusable, will have to see */
80 static char *zero = "0x00";
81 static char *one = "0x01";
82 static char *spname = "sp";
84 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
85 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
86 static char **fReturn = fReturnpic14;
88 //static char *accUse[] = {"a","b"};
90 //static short rbank = -1;
102 /* Resolved ifx structure. This structure stores information
103 about an iCode ifx that makes it easier to generate code.
105 typedef struct resolvedIfx {
106 symbol *lbl; /* pointer to a label */
107 int condition; /* true or false ifx */
108 int generated; /* set true when the code associated with the ifx
112 extern int pic14_ptrRegReq ;
113 extern int pic14_nRegs;
114 extern struct dbuf_s *codeOutBuf;
115 static void saverbank (int, iCode *,bool);
117 static lineNode *lineHead = NULL;
118 static lineNode *lineCurr = NULL;
121 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
122 0xE0, 0xC0, 0x80, 0x00};
123 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
124 0x07, 0x03, 0x01, 0x00};
129 /*-----------------------------------------------------------------*/
130 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
131 /* exponent of 2 is returned, otherwise -1 is */
133 /* note that this is similar to the function `powof2' in SDCCsymt */
137 /*-----------------------------------------------------------------*/
138 static int my_powof2 (unsigned long num)
141 if( (num & (num-1)) == 0) {
154 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
157 DEBUGpic14_emitcode ("; ","line = %d result %s=%s, size=%d, left %s=%s, size=%d, right %s=%s, size=%d",
159 ((result) ? AopType(AOP_TYPE(result)) : "-"),
160 ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
161 ((result) ? AOP_SIZE(result) : 0),
162 ((left) ? AopType(AOP_TYPE(left)) : "-"),
163 ((left) ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
164 ((left) ? AOP_SIZE(left) : 0),
165 ((right) ? AopType(AOP_TYPE(right)) : "-"),
166 ((right) ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
167 ((right) ? AOP_SIZE(right) : 0));
171 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
174 DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
176 ((result) ? AopType(AOP_TYPE(result)) : "-"),
177 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
178 ((left) ? AopType(AOP_TYPE(left)) : "-"),
179 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
180 ((right) ? AopType(AOP_TYPE(right)) : "-"),
181 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
185 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
188 char lb[INITIAL_INLINEASM];
189 unsigned char *lbp = (unsigned char *)lb;
191 if(!debug_verbose && !options.debug)
198 sprintf(lb,"%s\t",inst);
200 sprintf(lb,"%s",inst);
201 vsprintf(lb+(strlen(lb)),fmt,ap);
205 while (isspace(*lbp)) lbp++;
208 lineCurr = (lineCurr ?
209 connectLine(lineCurr,newLineNode(lb)) :
210 (lineHead = newLineNode(lb)));
211 lineCurr->isInline = _G.inLine;
212 lineCurr->isDebug = _G.debugLine;
214 addpCode2pBlock(pb,newpCodeCharP(lb));
219 static void Safe_vsnprintf (char *buf, size_t size, const char *fmt, va_list ap)
221 #if defined (HAVE_VSNPRINTF)
222 vsnprintf (buf, size, fmt, ap);
223 #elif defined (HAVE_VSPRINTF)
224 vsprintf (buf, size, fmt, ap);
225 if (strlen (buf) >= size)
227 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
229 #elif defined (HAVE_SNPRINTF)
230 snprintf (buf, size, "vs(n)printf required");
231 #elif defined (HAVE_SRINTF)
232 sprintf (buf, "vs(n)printf required");
233 if (strlen (buf) >= size)
235 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
238 assert ( !"neither vsnprintf nor vsprintf is present -- unable to proceed" );
242 void emitpComment (const char *fmt, ...)
249 Safe_vsnprintf (buffer, 4096, fmt, va);
250 //fprintf (stderr, "%s\n" ,buffer);
251 addpCode2pBlock (pb, newpCodeCharP (buffer));
254 Safe_vsnprintf (buffer, 4096, fmt, va);
255 fprintf (stderr, "No current pBlock -- discarding comment [%s]\n", buffer);
261 void emitpLabel(int key)
263 addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
266 /* gen.h defines a macro emitpcode that should be used to call emitpcode
267 * as this allows for easy debugging (ever asked the question: where was
268 * this instruction geenrated? Here is the answer... */
269 void emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
272 addpCode2pBlock(pb,newpCode(poc,pcop));
274 static int has_warned = 0;
276 DEBUGpic14_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
279 fprintf( stderr, "WARNING: encountered NULL pcop--this is probably a compiler bug...\n" );
284 void emitpcodeNULLop(PIC_OPCODE poc)
287 addpCode2pBlock(pb,newpCode(poc,NULL));
292 /*-----------------------------------------------------------------*/
293 /* pic14_emitcode - writes the code into a file : for now it is simple */
294 /*-----------------------------------------------------------------*/
295 void pic14_emitcode (char *inst,char *fmt, ...)
298 char lb[INITIAL_INLINEASM];
305 sprintf(lb,"%s\t",inst);
307 sprintf(lb,"%s",inst);
308 vsprintf(lb+(strlen(lb)),fmt,ap);
312 while (isspace(*lbp)) lbp++;
315 lineCurr = (lineCurr ?
316 connectLine(lineCurr,newLineNode(lb)) :
317 (lineHead = newLineNode(lb)));
318 lineCurr->isInline = _G.inLine;
319 lineCurr->isDebug = _G.debugLine;
320 lineCurr->isLabel = (lbp[strlen (lbp) - 1] == ':');
323 addpCode2pBlock(pb,newpCodeCharP(lb));
328 /*-----------------------------------------------------------------*/
329 /* pic14_emitDebuggerSymbol - associate the current code location */
330 /* with a debugger symbol */
331 /*-----------------------------------------------------------------*/
333 pic14_emitDebuggerSymbol (char * debugSym)
336 pic14_emitcode ("", ";%s ==.", debugSym);
341 /*-----------------------------------------------------------------*/
342 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
343 /*-----------------------------------------------------------------*/
344 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
346 bool r0iu = FALSE , r1iu = FALSE;
347 bool r0ou = FALSE , r1ou = FALSE;
349 /* the logic: if r0 & r1 used in the instruction
350 then we are in trouble otherwise */
352 /* first check if r0 & r1 are used by this
353 instruction, in which case we are in trouble */
354 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
355 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
360 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
361 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
363 /* if no usage of r0 then return it */
364 if (!r0iu && !r0ou) {
365 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
366 (*aopp)->type = AOP_R0;
368 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
371 /* if no usage of r1 then return it */
372 if (!r1iu && !r1ou) {
373 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
374 (*aopp)->type = AOP_R1;
376 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
379 /* now we know they both have usage */
380 /* if r0 not used in this instruction */
382 /* push it if not already pushed */
384 //pic14_emitcode ("push","%s",
385 // pic14_regWithIdx(R0_IDX)->dname);
389 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
390 (*aopp)->type = AOP_R0;
392 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
395 /* if r1 not used then */
398 /* push it if not already pushed */
400 //pic14_emitcode ("push","%s",
401 // pic14_regWithIdx(R1_IDX)->dname);
405 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
406 (*aopp)->type = AOP_R1;
407 return pic14_regWithIdx(R1_IDX);
411 /* I said end of world but not quite end of world yet */
412 /* if this is a result then we can push it on the stack*/
414 (*aopp)->type = AOP_STK;
418 /* other wise this is true end of the world */
419 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
420 "getFreePtr should never reach here");
425 /*-----------------------------------------------------------------*/
426 /* newAsmop - creates a new asmOp */
427 /*-----------------------------------------------------------------*/
428 asmop *newAsmop (short type)
432 aop = Safe_calloc(1,sizeof(asmop));
437 static void genSetDPTR(int n)
441 pic14_emitcode(";", "Select standard DPTR");
442 pic14_emitcode("mov", "dps, #0x00");
446 pic14_emitcode(";", "Select alternate DPTR");
447 pic14_emitcode("mov", "dps, #0x01");
451 /*-----------------------------------------------------------------*/
452 /* resolveIfx - converts an iCode ifx into a form more useful for */
453 /* generating code */
454 /*-----------------------------------------------------------------*/
455 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
460 // DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
462 resIfx->condition = 1; /* assume that the ifx is true */
463 resIfx->generated = 0; /* indicate that the ifx has not been used */
466 resIfx->lbl = NULL; /* this is wrong: newiTempLabel(NULL); / * oops, there is no ifx. so create a label */
468 DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
469 __FUNCTION__,__LINE__,resIfx->lbl->key);
473 resIfx->lbl = IC_TRUE(ifx);
475 resIfx->lbl = IC_FALSE(ifx);
476 resIfx->condition = 0;
480 DEBUGpic14_emitcode("; ***","ifx true is non-null");
482 DEBUGpic14_emitcode("; ***","ifx false is non-null");
486 // DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
489 /*-----------------------------------------------------------------*/
490 /* pointerCode - returns the code for a pointer type */
491 /*-----------------------------------------------------------------*/
493 static int pointerCode (sym_link *etype)
496 return PTR_TYPE(SPEC_OCLS(etype));
501 /*-----------------------------------------------------------------*/
502 /* aopForSym - for a true symbol */
503 /*-----------------------------------------------------------------*/
504 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
507 memmap *space= SPEC_OCLS(sym->etype);
509 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
510 /* if already has one */
514 //DEBUGpic14_emitcode(";","%d",__LINE__);
515 /* if it is in direct space */
516 if (IN_DIRSPACE(space)) {
517 sym->aop = aop = newAsmop (AOP_DIR);
518 aop->aopu.aop_dir = sym->rname ;
519 aop->size = getSize(sym->type);
520 DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
524 /* special case for a function */
525 if (IS_FUNC(sym->type)) {
527 sym->aop = aop = newAsmop(AOP_PCODE);
528 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
529 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
530 PCOI(aop->aopu.pcop)->_function = 1;
531 PCOI(aop->aopu.pcop)->index = 0;
532 aop->size = FPTRSIZE;
534 sym->aop = aop = newAsmop(AOP_IMMD);
535 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
536 strcpy(aop->aopu.aop_immd,sym->rname);
537 aop->size = FPTRSIZE;
539 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
543 if (IS_ARRAY(sym->type)) {
544 sym->aop = aop = newAsmop(AOP_PCODE);
545 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
546 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
547 PCOI(aop->aopu.pcop)->_function = 0;
548 PCOI(aop->aopu.pcop)->index = 0;
549 aop->size = getSize(sym->etype) * DCL_ELEM(sym->type);
551 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
555 /* only remaining is far space */
556 /* in which case DPTR gets the address */
557 sym->aop = aop = newAsmop(AOP_PCODE);
559 aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
560 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
561 PCOI(aop->aopu.pcop)->index = 0;
563 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
564 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
566 allocDirReg (IC_LEFT(ic));
568 aop->size = FPTRSIZE;
570 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
571 sym->aop = aop = newAsmop(AOP_DPTR);
572 pic14_emitcode ("mov","dptr,#%s", sym->rname);
573 aop->size = getSize(sym->type);
575 DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
578 /* if it is in code space */
579 if (IN_CODESPACE(space))
585 /*-----------------------------------------------------------------*/
586 /* aopForRemat - rematerialzes an object */
587 /*-----------------------------------------------------------------*/
588 static asmop *aopForRemat (operand *op) // x symbol *sym)
590 symbol *sym = OP_SYMBOL(op);
592 asmop *aop = newAsmop(AOP_PCODE);
596 ic = sym->rematiCode;
598 DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
599 if(IS_OP_POINTER(op)) {
600 DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
604 val += (int) operandLitValue(IC_RIGHT(ic));
605 } else if (ic->op == '-') {
606 val -= (int) operandLitValue(IC_RIGHT(ic));
610 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
613 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
614 aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
615 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
616 PCOI(aop->aopu.pcop)->index = val;
618 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
619 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
620 val, IS_PTR_CONST(operandType(op)));
622 // DEBUGpic14_emitcode(";","aop type %s",AopType(AOP_TYPE(IC_LEFT(ic))));
624 allocDirReg (IC_LEFT(ic));
629 int aopIdx (asmop *aop, int offset)
634 if(aop->type != AOP_REG)
637 return aop->aopu.aop_reg[offset]->rIdx;
640 /*-----------------------------------------------------------------*/
641 /* regsInCommon - two operands have some registers in common */
642 /*-----------------------------------------------------------------*/
643 static bool regsInCommon (operand *op1, operand *op2)
648 /* if they have registers in common */
649 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
652 sym1 = OP_SYMBOL(op1);
653 sym2 = OP_SYMBOL(op2);
655 if (sym1->nRegs == 0 || sym2->nRegs == 0)
658 for (i = 0 ; i < sym1->nRegs ; i++) {
663 for (j = 0 ; j < sym2->nRegs ;j++ ) {
667 if (sym2->regs[j] == sym1->regs[i])
675 /*-----------------------------------------------------------------*/
676 /* operandsEqu - equivalent */
677 /*-----------------------------------------------------------------*/
678 static bool operandsEqu ( operand *op1, operand *op2)
682 /* if they not symbols */
683 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
686 sym1 = OP_SYMBOL(op1);
687 sym2 = OP_SYMBOL(op2);
689 /* if both are itemps & one is spilt
690 and the other is not then false */
691 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
692 sym1->isspilt != sym2->isspilt )
695 /* if they are the same */
699 if (sym1->rname[0] && sym2->rname[0]
700 && strcmp (sym1->rname, sym2->rname) == 0)
704 /* if left is a tmp & right is not */
708 (sym1->usl.spillLoc == sym2))
715 (sym2->usl.spillLoc == sym1))
721 /*-----------------------------------------------------------------*/
722 /* pic14_sameRegs - two asmops have the same registers */
723 /*-----------------------------------------------------------------*/
724 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
731 if (aop1->type != AOP_REG ||
732 aop2->type != AOP_REG )
735 if (aop1->size != aop2->size )
738 for (i = 0 ; i < aop1->size ; i++ )
739 if (aop1->aopu.aop_reg[i] !=
740 aop2->aopu.aop_reg[i] )
746 /*-----------------------------------------------------------------*/
747 /* aopOp - allocates an asmop for an operand : */
748 /*-----------------------------------------------------------------*/
749 void aopOp (operand *op, iCode *ic, bool result)
758 /* if this a literal */
759 if (IS_OP_LITERAL(op)) {
760 op->aop = aop = newAsmop(AOP_LIT);
761 aop->aopu.aop_lit = op->operand.valOperand;
762 aop->size = getSize(operandType(op));
767 sym_link *type = operandType(op);
768 if(IS_PTR_CONST(type))
769 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
772 /* if already has a asmop then continue */
776 /* if the underlying symbol has a aop */
777 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
778 DEBUGpic14_emitcode(";","%d",__LINE__);
779 op->aop = OP_SYMBOL(op)->aop;
783 /* if this is a true symbol */
784 if (IS_TRUE_SYMOP(op)) {
785 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
786 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
790 /* this is a temporary : this has
796 e) can be a return use only */
801 /* if the type is a conditional */
802 if (sym->regType == REG_CND) {
803 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
808 /* if it is spilt then two situations
810 b) has a spill location */
811 if (sym->isspilt || sym->nRegs == 0) {
813 DEBUGpic14_emitcode(";","%d",__LINE__);
814 /* rematerialize it NOW */
817 sym->aop = op->aop = aop = aopForRemat (op);
818 aop->size = getSize(sym->type);
819 //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
824 /* WREG is not usable as an ordinary operand with PIC architecture,
825 * one might introduce a scratch register that can be used to make
826 * WREG accesible as an operand... disable WREG for now */
829 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
830 aop->size = getSize(sym->type);
831 for ( i = 0 ; i < 2 ; i++ )
832 aop->aopu.aop_str[i] = accUse[i];
833 DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
839 if(sym->isptr) { // && sym->uptr
840 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
841 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
843 //PCOI(aop->aopu.pcop)->_const = 0;
844 //PCOI(aop->aopu.pcop)->index = 0;
846 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
847 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
849 //allocDirReg (IC_LEFT(ic));
851 aop->size = getSize(sym->type);
852 DEBUGpic14_emitcode(";","%d",__LINE__);
859 aop = op->aop = sym->aop = newAsmop(AOP_STR);
860 aop->size = getSize(sym->type);
861 for ( i = 0 ; i < fReturnSizePic ; i++ )
862 aop->aopu.aop_str[i] = fReturn[i];
864 DEBUGpic14_emitcode(";","%d",__LINE__);
869 /* else spill location */
870 if (sym->usl.spillLoc)
872 asmop *oldAsmOp = NULL;
874 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
876 /* force a new aop if sizes differ */
877 oldAsmOp = sym->usl.spillLoc->aop;
878 sym->usl.spillLoc->aop = NULL;
880 DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
881 __FUNCTION__,__LINE__,
882 sym->usl.spillLoc->rname,
883 sym->rname, sym->usl.spillLoc->offset);
885 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
886 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
888 /* Don't reuse the new aop, go with the last one */
889 sym->usl.spillLoc->aop = oldAsmOp;
891 //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
892 aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname,
894 sym->usl.spillLoc->offset);
895 aop->size = getSize(sym->type);
902 sym_link *type = operandType(op);
903 if(IS_PTR_CONST(type))
904 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
907 /* must be in a register */
908 DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
909 sym->aop = op->aop = aop = newAsmop(AOP_REG);
910 aop->size = sym->nRegs;
911 for ( i = 0 ; i < sym->nRegs ;i++)
912 aop->aopu.aop_reg[i] = sym->regs[i];
915 /*-----------------------------------------------------------------*/
916 /* freeAsmop - free up the asmop given to an operand */
917 /*----------------------------------------------------------------*/
918 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
935 /* depending on the asmop type only three cases need work AOP_RO
936 , AOP_R1 && AOP_STK */
942 pic14_emitcode ("pop","ar0");
946 bitVectUnSetBit(ic->rUsed,R0_IDX);
952 pic14_emitcode ("pop","ar1");
956 bitVectUnSetBit(ic->rUsed,R1_IDX);
962 int stk = aop->aopu.aop_stk + aop->size;
963 bitVectUnSetBit(ic->rUsed,R0_IDX);
964 bitVectUnSetBit(ic->rUsed,R1_IDX);
966 getFreePtr(ic,&aop,FALSE);
968 if (options.stack10bit)
970 /* I'm not sure what to do here yet... */
973 "*** Warning: probably generating bad code for "
974 "10 bit stack mode.\n");
978 pic14_emitcode ("mov","a,_bp");
979 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
980 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
982 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
986 pic14_emitcode("pop","acc");
987 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
989 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
992 freeAsmop(op,NULL,ic,TRUE);
994 pic14_emitcode("pop","ar0");
999 pic14_emitcode("pop","ar1");
1007 /* all other cases just dealloc */
1011 OP_SYMBOL(op)->aop = NULL;
1012 /* if the symbol has a spill */
1014 SPIL_LOC(op)->aop = NULL;
1019 /*-----------------------------------------------------------------*/
1020 /* aopGet - for fetching value of the aop */
1021 /*-----------------------------------------------------------------*/
1022 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1027 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1028 /* offset is greater than
1031 if (offset > (aop->size - 1) &&
1032 aop->type != AOP_LIT)
1035 /* depending on type */
1036 switch (aop->type) {
1040 DEBUGpic14_emitcode(";","%d",__LINE__);
1041 /* if we need to increment it */
1042 while (offset > aop->coff) {
1043 pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);
1047 while (offset < aop->coff) {
1048 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1052 aop->coff = offset ;
1054 pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1055 return (dname ? "acc" : "a");
1057 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1058 rs = Safe_calloc(1,strlen(s)+1);
1064 DEBUGpic14_emitcode(";","%d",__LINE__);
1065 if (aop->type == AOP_DPTR2)
1070 while (offset > aop->coff) {
1071 pic14_emitcode ("inc","dptr");
1075 while (offset < aop->coff) {
1076 pic14_emitcode("lcall","__decdptr");
1082 pic14_emitcode("clr","a");
1083 pic14_emitcode("movc","a,@a+dptr");
1086 pic14_emitcode("movx","a,@dptr");
1089 if (aop->type == AOP_DPTR2)
1094 return (dname ? "acc" : "a");
1099 sprintf (s,"%s",aop->aopu.aop_immd);
1102 sprintf(s,"(%s >> %d)",
1107 aop->aopu.aop_immd);
1108 DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1109 rs = Safe_calloc(1,strlen(s)+1);
1115 sprintf(s,"(%s + %d)",
1118 DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1120 sprintf(s,"%s",aop->aopu.aop_dir);
1121 rs = Safe_calloc(1,strlen(s)+1);
1127 // return aop->aopu.aop_reg[offset]->dname;
1129 return aop->aopu.aop_reg[offset]->name;
1132 //pic14_emitcode(";","%d",__LINE__);
1133 return aop->aopu.aop_dir;
1136 DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1137 return "AOP_accumulator_bug";
1140 sprintf(s, "0x%02x", pic14aopLiteral (aop->aopu.aop_lit, offset));
1141 rs = Safe_strdup(s);
1145 aop->coff = offset ;
1146 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1149 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1151 return aop->aopu.aop_str[offset];
1155 pCodeOp *pcop = aop->aopu.pcop;
1156 DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1158 if (pcop->type == PO_IMMEDIATE) {
1159 offset += PCOI(pcop)->index;
1162 DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
1163 sprintf(s,"(%s+%d)", pcop->name,offset);
1165 DEBUGpic14_emitcode(";","%s",pcop->name);
1166 sprintf(s,"%s", pcop->name);
1169 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1172 rs = Safe_calloc(1,strlen(s)+1);
1178 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1179 "aopget got unsupported aop->type");
1184 /*-----------------------------------------------------------------*/
1185 /* popGetTempReg - create a new temporary pCodeOp */
1186 /*-----------------------------------------------------------------*/
1187 pCodeOp *popGetTempReg(void)
1192 pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1193 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1194 PCOR(pcop)->r->wasUsed=1;
1195 PCOR(pcop)->r->isFree=0;
1201 /*-----------------------------------------------------------------*/
1202 /* popReleaseTempReg - create a new temporary pCodeOp */
1203 /*-----------------------------------------------------------------*/
1204 void popReleaseTempReg(pCodeOp *pcop)
1207 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1208 PCOR(pcop)->r->isFree = 1;
1211 /*-----------------------------------------------------------------*/
1212 /* popGetLabel - create a new pCodeOp of type PO_LABEL */
1213 /*-----------------------------------------------------------------*/
1214 pCodeOp *popGetLabel(unsigned int key)
1217 DEBUGpic14_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1219 if(key>(unsigned int)max_key)
1222 return newpCodeOpLabel(NULL,key+100+labelOffset);
1225 /*-------------------------------------------------------------------*/
1226 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1227 /*-------------------------------------------------------------------*/
1228 pCodeOp *popGetHighLabel(unsigned int key)
1231 pcop = popGetLabel(key);
1232 PCOLAB(pcop)->offset = 1;
1236 /*-----------------------------------------------------------------*/
1237 /* popGetLit - asm operator to pcode operator conversion */
1238 /*-----------------------------------------------------------------*/
1239 pCodeOp *popGetLit(unsigned int lit)
1242 return newpCodeOpLit((unsigned char)lit);
1245 /*-----------------------------------------------------------------*/
1246 /* popGetImmd - asm operator to pcode immediate conversion */
1247 /*-----------------------------------------------------------------*/
1248 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1251 return newpCodeOpImmd(name, offset,index, 0, is_func);
1254 extern set *externs;
1256 /*-----------------------------------------------------------------*/
1257 /* popGetWithString - asm operator to pcode operator conversion */
1258 /*-----------------------------------------------------------------*/
1259 pCodeOp *popGetWithString(char *str, int isExtern)
1265 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1269 pcop = newpCodeOp(str,PO_STR);
1270 PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1275 pCodeOp *popGetExternal (char *str)
1277 pCodeOp *pcop = popGetWithString (str, 1);
1283 for (sym = setFirstItem (externs); !found && sym; sym = setNextItem (externs))
1285 if (!strcmp (str, sym->rname))
1291 sym = newSymbol(str, 0);
1292 strncpy(sym->rname, str, SDCC_NAME_MAX);
1293 addSet (&externs, sym);
1299 /*-----------------------------------------------------------------*/
1300 /* popRegFromString - */
1301 /*-----------------------------------------------------------------*/
1302 pCodeOp *popRegFromString(char *str, int size, int offset)
1305 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1306 pcop->type = PO_DIR;
1308 DEBUGpic14_emitcode(";","%d",__LINE__);
1313 pcop->name = Safe_calloc(1,strlen(str)+1);
1314 strcpy(pcop->name,str);
1316 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1318 PCOR(pcop)->r = dirregWithName(pcop->name);
1319 if(PCOR(pcop)->r == NULL) {
1320 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1321 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1322 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1324 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1326 PCOR(pcop)->instance = offset;
1331 /*-----------------------------------------------------------------*/
1332 /*-----------------------------------------------------------------*/
1333 pCodeOp *popRegFromIdx(int rIdx)
1337 DEBUGpic14_emitcode ("; ***","%s,%d , rIdx=0x%x",
1338 __FUNCTION__,__LINE__,rIdx);
1340 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1342 PCOR(pcop)->rIdx = rIdx;
1343 PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1344 PCOR(pcop)->r->isFree = 0;
1345 PCOR(pcop)->r->wasUsed = 1;
1347 pcop->type = PCOR(pcop)->r->pc_type;
1353 /*-----------------------------------------------------------------*/
1354 /* popGet - asm operator to pcode operator conversion */
1355 /*-----------------------------------------------------------------*/
1356 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1358 //char *s = buffer ;
1363 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1364 /* offset is greater than
1370 /* XXX: still needed for BIT operands (AOP_CRY) */
1371 if (offset > (aop->size - 1) &&
1372 aop->type != AOP_LIT &&
1373 aop->type != AOP_PCODE)
1375 printf( "%s: (offset[%d] > AOP_SIZE(op)[%d]-1) && AOP_TYPE(op) != AOP_LIT)\n", __FUNCTION__, offset, aop->size);
1376 return NULL; //zero;
1379 /* depending on type */
1380 switch (aop->type) {
1387 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1391 DEBUGpic14_emitcode(";","%d",__LINE__);
1392 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1395 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1397 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1398 pcop->type = PO_DIR;
1400 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1401 strcpy(pcop->name,aop->aopu.aop_dir);
1402 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1403 if(PCOR(pcop)->r == NULL) {
1404 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1405 PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1406 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1408 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1410 PCOR(pcop)->instance = offset;
1418 assert (offset < aop->size);
1419 rIdx = aop->aopu.aop_reg[offset]->rIdx;
1421 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1422 PCOR(pcop)->rIdx = rIdx;
1423 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1424 PCOR(pcop)->r->wasUsed=1;
1425 PCOR(pcop)->r->isFree=0;
1427 PCOR(pcop)->instance = offset;
1428 pcop->type = PCOR(pcop)->r->pc_type;
1429 //rs = aop->aopu.aop_reg[offset]->name;
1430 DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1435 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1436 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1437 //if(PCOR(pcop)->r == NULL)
1438 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1442 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1445 DEBUGpic14_emitcode(";","%d %s",__LINE__,aop->aopu.aop_str[offset]);
1446 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1448 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1449 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1450 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1451 pcop->type = PCOR(pcop)->r->pc_type;
1452 pcop->name = PCOR(pcop)->r->name;
1459 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1461 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1462 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1463 switch (aop->aopu.pcop->type)
1466 pcop = pCodeOpCopy (aop->aopu.pcop);
1467 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1468 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1469 PCOI(pcop)->index += offset;
1470 //PCOI(pcop)->offset = 0;
1473 pcop = pCodeOpCopy (aop->aopu.pcop);
1474 PCOR(pcop)->instance = offset;
1477 assert ( !"unhandled pCode type" );
1483 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1484 "popGet got unsupported aop->type");
1488 /*-----------------------------------------------------------------*/
1489 /* popGetAddr - access the low/high word of a symbol (immediate) */
1490 /* (for non-PO_IMMEDIATEs this is the same as popGet) */
1491 /*-----------------------------------------------------------------*/
1492 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1494 if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1496 pCodeOp *pcop = aop->aopu.pcop;
1497 assert (offset <= GPTRSIZE);
1499 /* special case: index >= 2 should return GPOINTER-style values */
1502 pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1506 pcop = pCodeOpCopy (pcop);
1507 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1508 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1509 PCOI(pcop)->offset += offset;
1510 PCOI(pcop)->index += index;
1511 //fprintf (stderr, "is PO_IMMEDIATE: %s+o%d+i%d (new o%d,i%d)\n", pcop->name,PCOI(pcop)->offset,PCOI(pcop)->index, offset, index);
1514 return popGet (aop, offset + index);
1518 /*-----------------------------------------------------------------*/
1519 /* aopPut - puts a string for a aop */
1520 /*-----------------------------------------------------------------*/
1521 void aopPut (asmop *aop, char *s, int offset)
1526 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1528 if (aop->size && offset > ( aop->size - 1)) {
1529 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1530 "aopPut got offset > aop->size");
1534 /* will assign value to value */
1535 /* depending on where it is ofcourse */
1536 switch (aop->type) {
1539 sprintf(d,"(%s + %d)",
1540 aop->aopu.aop_dir,offset);
1541 fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1544 sprintf(d,"%s",aop->aopu.aop_dir);
1547 DEBUGpic14_emitcode(";","%d",__LINE__);
1549 pic14_emitcode("movf","%s,w",s);
1550 pic14_emitcode("movwf","%s",d);
1553 pic14_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
1554 if(offset >= aop->size) {
1555 emitpcode(POC_CLRF,popGet(aop,offset));
1558 emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
1561 emitpcode(POC_MOVWF,popGet(aop,offset));
1567 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1568 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1571 strcmp(s,"r0") == 0 ||
1572 strcmp(s,"r1") == 0 ||
1573 strcmp(s,"r2") == 0 ||
1574 strcmp(s,"r3") == 0 ||
1575 strcmp(s,"r4") == 0 ||
1576 strcmp(s,"r5") == 0 ||
1577 strcmp(s,"r6") == 0 ||
1578 strcmp(s,"r7") == 0 )
1579 pic14_emitcode("mov","%s,%s ; %d",
1580 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1584 if(strcmp(s,"W")==0 )
1585 pic14_emitcode("movf","%s,w ; %d",s,__LINE__);
1587 pic14_emitcode("movwf","%s",
1588 aop->aopu.aop_reg[offset]->name);
1590 if(strcmp(s,zero)==0) {
1591 emitpcode(POC_CLRF,popGet(aop,offset));
1593 } else if(strcmp(s,"W")==0) {
1594 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1595 pcop->type = PO_GPR_REGISTER;
1597 PCOR(pcop)->rIdx = -1;
1598 PCOR(pcop)->r = NULL;
1600 DEBUGpic14_emitcode(";","%d",__LINE__);
1601 pcop->name = Safe_strdup(s);
1602 emitpcode(POC_MOVFW,pcop);
1603 emitpcode(POC_MOVWF,popGet(aop,offset));
1604 } else if(strcmp(s,one)==0) {
1605 emitpcode(POC_CLRF,popGet(aop,offset));
1606 emitpcode(POC_INCF,popGet(aop,offset));
1608 emitpcode(POC_MOVWF,popGet(aop,offset));
1616 if (aop->type == AOP_DPTR2)
1622 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1623 "aopPut writting to code space");
1627 while (offset > aop->coff) {
1629 pic14_emitcode ("inc","dptr");
1632 while (offset < aop->coff) {
1634 pic14_emitcode("lcall","__decdptr");
1639 /* if not in accumulater */
1642 pic14_emitcode ("movx","@dptr,a");
1644 if (aop->type == AOP_DPTR2)
1652 while (offset > aop->coff) {
1654 pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1656 while (offset < aop->coff) {
1658 pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1664 pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1669 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1671 if (strcmp(s,"r0") == 0 ||
1672 strcmp(s,"r1") == 0 ||
1673 strcmp(s,"r2") == 0 ||
1674 strcmp(s,"r3") == 0 ||
1675 strcmp(s,"r4") == 0 ||
1676 strcmp(s,"r5") == 0 ||
1677 strcmp(s,"r6") == 0 ||
1678 strcmp(s,"r7") == 0 ) {
1680 sprintf(buffer,"a%s",s);
1681 pic14_emitcode("mov","@%s,%s",
1682 aop->aopu.aop_ptr->name,buffer);
1684 pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1689 if (strcmp(s,"a") == 0)
1690 pic14_emitcode("push","acc");
1692 pic14_emitcode("push","%s",s);
1697 /* if bit variable */
1698 if (!aop->aopu.aop_dir) {
1699 pic14_emitcode("clr","a");
1700 pic14_emitcode("rlc","a");
1703 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1706 pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1709 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1711 lbl = newiTempLabel(NULL);
1713 if (strcmp(s,"a")) {
1716 pic14_emitcode("clr","c");
1717 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1718 pic14_emitcode("cpl","c");
1719 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1720 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1727 if (strcmp(aop->aopu.aop_str[offset],s))
1728 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1733 if (!offset && (strcmp(s,"acc") == 0))
1736 if (strcmp(aop->aopu.aop_str[offset],s))
1737 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1741 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1742 "aopPut got unsupported aop->type");
1748 /*-----------------------------------------------------------------*/
1749 /* mov2w_op - generate either a MOVLW or MOVFW based operand type */
1750 /*-----------------------------------------------------------------*/
1751 static void mov2w_op (operand *op, int offset)
1756 /* for PO_IMMEDIATEs: use address or value? */
1757 if (op_isLitLike (op))
1759 /* access address of op */
1760 if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
1761 if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
1763 if (offset == GPTRSIZE-1)
1764 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1766 emitpcode (POC_MOVLW, popGetLit (0));
1769 emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
1771 /* access value stored in op */
1772 mov2w (AOP(op), offset);
1777 /*-----------------------------------------------------------------*/
1778 /* mov2w - generate either a MOVLW or MOVFW based operand type */
1779 /*-----------------------------------------------------------------*/
1780 void mov2w (asmop *aop, int offset)
1786 DEBUGpic14_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
1788 if ( aop_isLitLike (aop) )
1789 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1791 emitpcode(POC_MOVFW,popGet(aop,offset));
1795 static void movwf (asmop *op, int offset)
1797 emitpcode (POC_MOVWF, popGet(op, offset));
1800 static pCodeOp *get_argument_pcop (int idx)
1802 assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1803 return popRegFromIdx (Gstack_base_addr - (idx - 1));
1806 static pCodeOp *get_return_val_pcop (int offset)
1808 assert (offset > 0 && "the most significant byte is returned via WREG");
1809 return popRegFromIdx (Gstack_base_addr - (offset - 1));
1812 static void pass_argument (operand *op, int offset, int idx)
1815 mov2w_op (op, offset);
1817 emitpcode(POC_MOVWF, get_argument_pcop (idx));
1820 static void get_returnvalue (operand *op, int offset, int idx)
1823 emitpcode(POC_MOVFW, get_return_val_pcop (idx));
1824 movwf(AOP(op), offset);
1827 static void call_libraryfunc (char *name)
1829 /* library code might reside in different page... */
1830 emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1831 /* call the library function */
1832 emitpcode (POC_CALL, popGetExternal (name));
1833 /* might return from different page... */
1834 emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1837 /*-----------------------------------------------------------------*/
1838 /* reAdjustPreg - points a register back to where it should */
1839 /*-----------------------------------------------------------------*/
1840 static void reAdjustPreg (asmop *aop)
1844 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1846 if ((size = aop->size) <= 1)
1849 switch (aop->type) {
1853 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1857 if (aop->type == AOP_DPTR2)
1863 pic14_emitcode("lcall","__decdptr");
1866 if (aop->type == AOP_DPTR2)
1879 /*-----------------------------------------------------------------*/
1880 /* opIsGptr: returns non-zero if the passed operand is */
1881 /* a generic pointer type. */
1882 /*-----------------------------------------------------------------*/
1883 static int opIsGptr(operand *op)
1885 sym_link *type = operandType(op);
1887 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1888 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1896 /*-----------------------------------------------------------------*/
1897 /* pic14_getDataSize - get the operand data size */
1898 /*-----------------------------------------------------------------*/
1899 int pic14_getDataSize(operand *op)
1903 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1906 size = getSize(OP_SYM_ETYPE(op));
1908 //return AOP_SIZE(op);
1910 // tsd- in the pic port, the genptr size is 1, so this code here
1911 // fails. ( in the 8051 port, the size was 4).
1913 size = AOP_SIZE(op);
1914 if (IS_GENPTR(OP_SYM_TYPE(op)))
1916 sym_link *type = operandType(op);
1917 if (IS_GENPTR(type))
1919 /* generic pointer; arithmetic operations
1920 * should ignore the high byte (pointer type).
1923 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1930 /*-----------------------------------------------------------------*/
1931 /* pic14_outAcc - output Acc */
1932 /*-----------------------------------------------------------------*/
1933 void pic14_outAcc(operand *result)
1936 DEBUGpic14_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
1937 DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1940 size = pic14_getDataSize(result);
1942 emitpcode(POC_MOVWF,popGet(AOP(result),0));
1945 /* unsigned or positive */
1947 emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1952 /*-----------------------------------------------------------------*/
1953 /* pic14_outBitC - output a bit C */
1954 /*-----------------------------------------------------------------*/
1955 void pic14_outBitC(operand *result)
1958 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1959 /* if the result is bit */
1960 if (AOP_TYPE(result) == AOP_CRY)
1961 aopPut(AOP(result),"c",0);
1963 pic14_emitcode("clr","a ; %d", __LINE__);
1964 pic14_emitcode("rlc","a");
1965 pic14_outAcc(result);
1969 /*-----------------------------------------------------------------*/
1970 /* pic14_toBoolean - emit code for orl a,operator(sizeop) */
1971 /*-----------------------------------------------------------------*/
1972 void pic14_toBoolean(operand *oper)
1974 int size = AOP_SIZE(oper);
1977 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1982 /* MOVFW does not load the flags... */
1983 if (AOP_TYPE(oper) == AOP_ACC) {
1984 emitpcode(POC_IORLW, popGetLit(0));
1987 emitpcode(POC_MOVLW, popGetLit(0));
1991 if ( AOP_TYPE(oper) != AOP_ACC) {
1992 emitpcode(POC_MOVFW,popGet(AOP(oper),0));
1997 while (offset < size) {
1998 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
2000 /* Z is set iff (oper == 0) */
2004 /*-----------------------------------------------------------------*/
2005 /* genNot - generate code for ! operation */
2006 /*-----------------------------------------------------------------*/
2007 static void genNot (iCode *ic)
2014 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2015 /* assign asmOps to operand & result */
2016 aopOp (IC_LEFT(ic),ic,FALSE);
2017 aopOp (IC_RESULT(ic),ic,TRUE);
2019 DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2020 /* if in bit space then a special case */
2021 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2022 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2023 emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
2024 emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
2026 emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
2027 emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
2028 emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
2033 size = AOP_SIZE(IC_LEFT(ic));
2034 mov2w (AOP(IC_LEFT(ic)),0);
2037 if (op_isLitLike (IC_LEFT(ic)))
2038 emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
2040 emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
2042 emitpcode(POC_MOVLW, popGetLit (0));
2044 emitpcode(POC_MOVLW, popGetLit (1));
2045 movwf(AOP(IC_RESULT(ic)), 0);
2047 for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
2049 emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
2054 /* release the aops */
2055 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2056 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2060 /*-----------------------------------------------------------------*/
2061 /* genCpl - generate code for complement */
2062 /*-----------------------------------------------------------------*/
2063 static void genCpl (iCode *ic)
2065 operand *left, *result;
2070 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2071 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2072 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2074 /* if both are in bit space then
2076 if (AOP_TYPE(result) == AOP_CRY &&
2077 AOP_TYPE(left) == AOP_CRY ) {
2079 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir);
2080 pic14_emitcode("cpl","c");
2081 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir);
2085 size = AOP_SIZE(result);
2086 if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
2089 if(AOP_TYPE(left) == AOP_ACC)
2090 emitpcode(POC_XORLW, popGetLit(0xff));
2092 emitpcode(POC_COMFW,popGet(AOP(left),offset));
2094 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
2097 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2101 /* release the aops */
2102 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2103 freeAsmop(result,NULL,ic,TRUE);
2106 /*-----------------------------------------------------------------*/
2107 /* genUminusFloat - unary minus for floating points */
2108 /*-----------------------------------------------------------------*/
2109 static void genUminusFloat(operand *op,operand *result)
2111 int size ,offset =0 ;
2116 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2117 /* for this we just need to flip the
2118 first it then copy the rest in place */
2119 size = AOP_SIZE(op) - 1;
2120 l = aopGet(AOP(op),3,FALSE,FALSE);
2124 pic14_emitcode("cpl","acc.7");
2125 aopPut(AOP(result),"a",3);
2129 aopGet(AOP(op),offset,FALSE,FALSE),
2135 /*-----------------------------------------------------------------*/
2136 /* genUminus - unary minus code generation */
2137 /*-----------------------------------------------------------------*/
2138 static void genUminus (iCode *ic)
2141 sym_link *optype, *rtype;
2145 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2147 aopOp(IC_LEFT(ic),ic,FALSE);
2148 aopOp(IC_RESULT(ic),ic,TRUE);
2150 /* if both in bit space then special
2152 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2153 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2155 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0));
2156 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2157 emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0));
2162 optype = operandType(IC_LEFT(ic));
2163 rtype = operandType(IC_RESULT(ic));
2165 /* if float then do float stuff */
2166 if (IS_FLOAT(optype)) {
2167 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2171 /* otherwise subtract from zero by taking the 2's complement */
2172 size = AOP_SIZE(IC_LEFT(ic));
2174 for(i=0; i<size; i++) {
2175 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2176 emitpcode(POC_COMF, popGet(AOP(IC_LEFT(ic)),i));
2178 emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2179 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2183 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0));
2184 for(i=1; i<size; i++) {
2186 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),i));
2190 /* release the aops */
2191 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2192 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2195 /*-----------------------------------------------------------------*/
2196 /* saveRegisters - will look for a call and save the registers */
2197 /*-----------------------------------------------------------------*/
2198 static void saveRegisters(iCode *lic)
2207 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2209 for (ic = lic ; ic ; ic = ic->next)
2210 if (ic->op == CALL || ic->op == PCALL)
2214 fprintf(stderr,"found parameter push with no function call\n");
2218 /* if the registers have been saved already then
2220 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2223 /* find the registers in use at this time
2224 and push them away to safety */
2225 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2229 if (options.useXstack) {
2230 if (bitVectBitValue(rsave,R0_IDX))
2231 pic14_emitcode("mov","b,r0");
2232 pic14_emitcode("mov","r0,%s",spname);
2233 for (i = 0 ; i < pic14_nRegs ; i++) {
2234 if (bitVectBitValue(rsave,i)) {
2236 pic14_emitcode("mov","a,b");
2238 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2239 pic14_emitcode("movx","@r0,a");
2240 pic14_emitcode("inc","r0");
2243 pic14_emitcode("mov","%s,r0",spname);
2244 if (bitVectBitValue(rsave,R0_IDX))
2245 pic14_emitcode("mov","r0,b");
2247 //for (i = 0 ; i < pic14_nRegs ; i++) {
2248 // if (bitVectBitValue(rsave,i))
2249 // pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2252 dtype = operandType(IC_LEFT(ic));
2253 if (currFunc && dtype &&
2254 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2255 IFFUNC_ISISR(currFunc->type) &&
2258 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2261 /*-----------------------------------------------------------------*/
2262 /* unsaveRegisters - pop the pushed registers */
2263 /*-----------------------------------------------------------------*/
2264 static void unsaveRegisters (iCode *ic)
2271 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2272 /* find the registers in use at this time
2273 and push them away to safety */
2274 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2277 if (options.useXstack) {
2278 pic14_emitcode("mov","r0,%s",spname);
2279 for (i = pic14_nRegs ; i >= 0 ; i--) {
2280 if (bitVectBitValue(rsave,i)) {
2281 pic14_emitcode("dec","r0");
2282 pic14_emitcode("movx","a,@r0");
2284 pic14_emitcode("mov","b,a");
2286 pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2290 pic14_emitcode("mov","%s,r0",spname);
2291 if (bitVectBitValue(rsave,R0_IDX))
2292 pic14_emitcode("mov","r0,b");
2294 //for (i = pic14_nRegs ; i >= 0 ; i--) {
2295 // if (bitVectBitValue(rsave,i))
2296 // pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2302 /*-----------------------------------------------------------------*/
2304 /*-----------------------------------------------------------------*/
2305 static void pushSide(operand * oper, int size)
2309 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2311 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2312 if (AOP_TYPE(oper) != AOP_REG &&
2313 AOP_TYPE(oper) != AOP_DIR &&
2315 pic14_emitcode("mov","a,%s",l);
2316 pic14_emitcode("push","acc");
2318 pic14_emitcode("push","%s",l);
2323 /*-----------------------------------------------------------------*/
2324 /* assignResultValue - */
2325 /*-----------------------------------------------------------------*/
2326 static void assignResultValue(operand * oper)
2328 int size = AOP_SIZE(oper);
2333 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2335 DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2337 /* assign MSB first (passed via WREG) */
2339 get_returnvalue (oper, size, offset + GpsuedoStkPtr);
2345 /*-----------------------------------------------------------------*/
2346 /* genIpush - genrate code for pushing this gets a little complex */
2347 /*-----------------------------------------------------------------*/
2348 static void genIpush (iCode *ic)
2352 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2354 int size, offset = 0 ;
2358 /* if this is not a parm push : ie. it is spill push
2359 and spill push is always done on the local stack */
2360 if (!ic->parmPush) {
2362 /* and the item is spilt then do nothing */
2363 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2366 aopOp(IC_LEFT(ic),ic,FALSE);
2367 size = AOP_SIZE(IC_LEFT(ic));
2368 /* push it on the stack */
2370 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2375 pic14_emitcode("push","%s",l);
2380 /* this is a paramter push: in this case we call
2381 the routine to find the call and save those
2382 registers that need to be saved */
2385 /* then do the push */
2386 aopOp(IC_LEFT(ic),ic,FALSE);
2389 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2390 size = AOP_SIZE(IC_LEFT(ic));
2393 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2394 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
2395 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2397 pic14_emitcode("mov","a,%s",l);
2398 pic14_emitcode("push","acc");
2400 pic14_emitcode("push","%s",l);
2403 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2407 /*-----------------------------------------------------------------*/
2408 /* genIpop - recover the registers: can happen only for spilling */
2409 /*-----------------------------------------------------------------*/
2410 static void genIpop (iCode *ic)
2414 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2415 assert (!"genIpop -- unimplemented");
2420 /* if the temp was not pushed then */
2421 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2424 aopOp(IC_LEFT(ic),ic,FALSE);
2425 size = AOP_SIZE(IC_LEFT(ic));
2428 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2431 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2435 /*-----------------------------------------------------------------*/
2436 /* unsaverbank - restores the resgister bank from stack */
2437 /*-----------------------------------------------------------------*/
2438 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2442 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2448 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2450 if (options.useXstack) {
2452 r = getFreePtr(ic,&aop,FALSE);
2455 pic14_emitcode("mov","%s,_spx",r->name);
2456 pic14_emitcode("movx","a,@%s",r->name);
2457 pic14_emitcode("mov","psw,a");
2458 pic14_emitcode("dec","%s",r->name);
2461 pic14_emitcode ("pop","psw");
2464 for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2465 if (options.useXstack) {
2466 pic14_emitcode("movx","a,@%s",r->name);
2467 //pic14_emitcode("mov","(%s+%d),a",
2468 // regspic14[i].base,8*bank+regspic14[i].offset);
2469 pic14_emitcode("dec","%s",r->name);
2472 pic14_emitcode("pop",""); //"(%s+%d)",
2473 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2476 if (options.useXstack) {
2478 pic14_emitcode("mov","_spx,%s",r->name);
2479 freeAsmop(NULL,aop,ic,TRUE);
2485 /*-----------------------------------------------------------------*/
2486 /* saverbank - saves an entire register bank on the stack */
2487 /*-----------------------------------------------------------------*/
2488 static void saverbank (int bank, iCode *ic, bool pushPsw)
2492 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2498 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2499 if (options.useXstack) {
2502 r = getFreePtr(ic,&aop,FALSE);
2503 pic14_emitcode("mov","%s,_spx",r->name);
2507 for (i = 0 ; i < pic14_nRegs ;i++) {
2508 if (options.useXstack) {
2509 pic14_emitcode("inc","%s",r->name);
2510 //pic14_emitcode("mov","a,(%s+%d)",
2511 // regspic14[i].base,8*bank+regspic14[i].offset);
2512 pic14_emitcode("movx","@%s,a",r->name);
2514 pic14_emitcode("push","");// "(%s+%d)",
2515 //regspic14[i].base,8*bank+regspic14[i].offset);
2519 if (options.useXstack) {
2520 pic14_emitcode("mov","a,psw");
2521 pic14_emitcode("movx","@%s,a",r->name);
2522 pic14_emitcode("inc","%s",r->name);
2523 pic14_emitcode("mov","_spx,%s",r->name);
2524 freeAsmop (NULL,aop,ic,TRUE);
2527 pic14_emitcode("push","psw");
2529 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2535 /*-----------------------------------------------------------------*/
2536 /* genCall - generates a call statement */
2537 /*-----------------------------------------------------------------*/
2538 static void genCall (iCode *ic)
2547 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2549 /* if caller saves & we have not saved then */
2553 /* if we are calling a function that is not using
2554 the same register bank then we need to save the
2555 destination registers on the stack */
2556 dtype = operandType(IC_LEFT(ic));
2557 if (currFunc && dtype &&
2558 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2559 IFFUNC_ISISR(currFunc->type) &&
2562 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2564 /* if send set is not empty the assign */
2567 /* For the Pic port, there is no data stack.
2568 * So parameters passed to functions are stored
2569 * in registers. (The pCode optimizer will get
2570 * rid of most of these :).
2572 int psuedoStkPtr=-1;
2573 int firstTimeThruLoop = 1;
2575 _G.sendSet = reverseSet(_G.sendSet);
2577 /* First figure how many parameters are getting passed */
2578 for (sic = setFirstItem(_G.sendSet) ; sic ;
2579 sic = setNextItem(_G.sendSet)) {
2581 aopOp(IC_LEFT(sic),sic,FALSE);
2582 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2583 freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2586 for (sic = setFirstItem(_G.sendSet) ; sic ;
2587 sic = setNextItem(_G.sendSet)) {
2588 int size, offset = 0;
2590 aopOp(IC_LEFT(sic),sic,FALSE);
2591 size = AOP_SIZE(IC_LEFT(sic));
2594 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2595 AopType(AOP_TYPE(IC_LEFT(sic))));
2597 if(!firstTimeThruLoop) {
2598 /* If this is not the first time we've been through the loop
2599 * then we need to save the parameter in a temporary
2600 * register. The last byte of the last parameter is
2602 emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2605 firstTimeThruLoop=0;
2607 mov2w_op (IC_LEFT(sic), offset);
2610 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2615 sym = OP_SYMBOL(IC_LEFT(ic));
2616 name = sym->rname[0] ? sym->rname : sym->name;
2617 isExtern = IS_EXTERN(sym->etype) || pic14_inISR;
2619 /* Extern functions and ISRs maybe on a different page;
2620 * must call pagesel */
2621 emitpcode(POC_PAGESEL,popGetWithString(name,1));
2623 emitpcode(POC_CALL,popGetWithString(name,isExtern));
2625 /* May have returned from a different page;
2626 * must use pagesel to restore PCLATH before next
2627 * goto or call instruction */
2628 emitpcode(POC_PAGESEL,popGetWithString("$",0));
2631 /* if we need assign a result value */
2632 if ((IS_ITEMP(IC_RESULT(ic)) &&
2633 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2634 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2635 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2638 aopOp(IC_RESULT(ic),ic,FALSE);
2641 assignResultValue(IC_RESULT(ic));
2643 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2644 AopType(AOP_TYPE(IC_RESULT(ic))));
2646 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2649 /* if register bank was saved then pop them */
2651 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2653 /* if we hade saved some registers then unsave them */
2654 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2655 unsaveRegisters (ic);
2660 /*-----------------------------------------------------------------*/
2661 /* genPcall - generates a call by pointer statement */
2662 /*-----------------------------------------------------------------*/
2663 static void genPcall (iCode *ic)
2666 symbol *albl = newiTempLabel(NULL);
2667 symbol *blbl = newiTempLabel(NULL);
2674 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2675 /* if caller saves & we have not saved then */
2679 /* if we are calling a function that is not using
2680 the same register bank then we need to save the
2681 destination registers on the stack */
2682 dtype = operandType(IC_LEFT(ic));
2683 if (currFunc && dtype &&
2684 IFFUNC_ISISR(currFunc->type) &&
2685 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2686 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2689 aopOp(left,ic,FALSE);
2690 DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2692 poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2694 pushSide(IC_LEFT(ic), FPTRSIZE);
2696 /* if send set is not empty, assign parameters */
2699 DEBUGpic14_emitcode ("; ***","%s %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2700 /* no way to pass args - W always gets used to make the call */
2702 /* first idea - factor out a common helper function and call it.
2703 But don't know how to get it generated only once in its own block
2705 if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2708 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2709 DEBUGpic14_emitcode ("; ***","%s %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2710 buffer = Safe_calloc(1,strlen(rname)+16);
2711 sprintf(buffer, "%s_goto_helper", rname);
2712 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2716 emitpcode(POC_CALL,popGetLabel(albl->key));
2717 pcop = popGetLabel(blbl->key);
2718 emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
2719 emitpcode(POC_GOTO,pcop);
2720 emitpLabel(albl->key);
2722 emitpcode(poc,popGetAddr(AOP(left),1,0));
2723 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2724 emitpcode(poc,popGetAddr(AOP(left),0,0));
2725 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2727 emitpLabel(blbl->key);
2729 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2731 /* if we need to assign a result value */
2732 if ((IS_ITEMP(IC_RESULT(ic)) &&
2733 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2734 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2735 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2738 aopOp(IC_RESULT(ic),ic,FALSE);
2743 assignResultValue(IC_RESULT(ic));
2745 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2748 /* if register bank was saved then unsave them */
2749 if (currFunc && dtype &&
2750 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2751 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2753 /* if we hade saved some registers then
2756 unsaveRegisters (ic);
2760 /*-----------------------------------------------------------------*/
2761 /* resultRemat - result is rematerializable */
2762 /*-----------------------------------------------------------------*/
2763 static int resultRemat (iCode *ic)
2765 // DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2768 if (SKIP_IC(ic) || ic->op == IFX)
2771 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2772 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2773 if (sym->remat && !POINTER_SET(ic))
2780 #if defined(__BORLANDC__) || defined(_MSC_VER)
2781 #define STRCASECMP stricmp
2783 #define STRCASECMP strcasecmp
2787 /*-----------------------------------------------------------------*/
2788 /* inExcludeList - return 1 if the string is in exclude Reg list */
2789 /*-----------------------------------------------------------------*/
2790 static bool inExcludeList(char *s)
2792 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2795 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2796 if (options.excludeRegs[i] &&
2797 STRCASECMP(options.excludeRegs[i],"none") == 0)
2800 for ( i = 0 ; options.excludeRegs[i]; i++) {
2801 if (options.excludeRegs[i] &&
2802 STRCASECMP(s,options.excludeRegs[i]) == 0)
2809 /*-----------------------------------------------------------------*/
2810 /* genFunction - generated code for function entry */
2811 /*-----------------------------------------------------------------*/
2812 static void genFunction (iCode *ic)
2819 DEBUGpic14_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2821 labelOffset += (max_key+4);
2825 /* create the function header */
2826 pic14_emitcode(";","-----------------------------------------");
2827 pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2828 pic14_emitcode(";","-----------------------------------------");
2830 /* prevent this symbol from being emitted as 'extern' */
2831 pic14_stringInSet(sym->rname, &pic14_localFunctions, 1);
2833 pic14_emitcode("","%s:",sym->rname);
2834 addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2836 ftype = operandType(IC_LEFT(ic));
2838 /* if critical function then turn interrupts off */
2839 if (IFFUNC_ISCRITICAL(ftype))
2840 pic14_emitcode("clr","ea");
2842 /* here we need to generate the equates for the
2843 register bank if required */
2845 if (FUNC_REGBANK(ftype) != rbank) {
2848 rbank = FUNC_REGBANK(ftype);
2849 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2850 if (strcmp(regspic14[i].base,"0") == 0)
2851 pic14_emitcode("","%s = 0x%02x",
2853 8*rbank+regspic14[i].offset);
2855 pic14_emitcode ("","%s = %s + 0x%02x",
2858 8*rbank+regspic14[i].offset);
2863 /* if this is an interrupt service routine */
2865 if (IFFUNC_ISISR(sym->type)) {
2867 /* already done in pic14createInterruptVect() - delete me
2868 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2869 emitpcodeNULLop(POC_NOP);
2870 emitpcodeNULLop(POC_NOP);
2871 emitpcodeNULLop(POC_NOP);
2873 emitpcode(POC_MOVWF, popCopyReg(&pc_wsave));
2874 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2875 emitpcode(POC_CLRF, popCopyReg(&pc_status));
2876 emitpcode(POC_MOVWF, popCopyReg(&pc_ssave));
2877 emitpcode(POC_MOVFW, popCopyReg(&pc_pclath));
2878 emitpcode(POC_MOVWF, popCopyReg(&pc_psave));
2879 emitpcode(POC_CLRF, popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2881 pBlockConvert2ISR(pb);
2882 pic14_hasInterrupt = 1;
2884 if (!inExcludeList("acc"))
2885 pic14_emitcode ("push","acc");
2886 if (!inExcludeList("b"))
2887 pic14_emitcode ("push","b");
2888 if (!inExcludeList("dpl"))
2889 pic14_emitcode ("push","dpl");
2890 if (!inExcludeList("dph"))
2891 pic14_emitcode ("push","dph");
2892 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2894 pic14_emitcode ("push", "dpx");
2895 /* Make sure we're using standard DPTR */
2896 pic14_emitcode ("push", "dps");
2897 pic14_emitcode ("mov", "dps, #0x00");
2898 if (options.stack10bit)
2900 /* This ISR could conceivably use DPTR2. Better save it. */
2901 pic14_emitcode ("push", "dpl1");
2902 pic14_emitcode ("push", "dph1");
2903 pic14_emitcode ("push", "dpx1");
2906 /* if this isr has no bank i.e. is going to
2907 run with bank 0 , then we need to save more
2909 if (!FUNC_REGBANK(sym->type)) {
2911 /* if this function does not call any other
2912 function then we can be economical and
2913 save only those registers that are used */
2914 if (! IFFUNC_HASFCALL(sym->type)) {
2917 /* if any registers used */
2918 if (sym->regsUsed) {
2919 /* save the registers used */
2920 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2921 if (bitVectBitValue(sym->regsUsed,i) ||
2922 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2923 pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);
2928 /* this function has a function call cannot
2929 determines register usage so we will have the
2931 saverbank(0,ic,FALSE);
2936 /* if callee-save to be used for this function
2937 then save the registers being used in this function */
2938 if (IFFUNC_CALLEESAVES(sym->type)) {
2941 /* if any registers used */
2942 if (sym->regsUsed) {
2943 /* save the registers used */
2944 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2945 if (bitVectBitValue(sym->regsUsed,i) ||
2946 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2947 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2955 /* set the register bank to the desired value */
2956 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2957 pic14_emitcode("push","psw");
2958 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);
2961 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2963 if (options.useXstack) {
2964 pic14_emitcode("mov","r0,%s",spname);
2965 pic14_emitcode("mov","a,_bp");
2966 pic14_emitcode("movx","@r0,a");
2967 pic14_emitcode("inc","%s",spname);
2971 /* set up the stack */
2972 pic14_emitcode ("push","_bp"); /* save the callers stack */
2974 pic14_emitcode ("mov","_bp,%s",spname);
2977 /* adjust the stack for the function */
2982 werror(W_STACK_OVERFLOW,sym->name);
2984 if (i > 3 && sym->recvSize < 4) {
2986 pic14_emitcode ("mov","a,sp");
2987 pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2988 pic14_emitcode ("mov","sp,a");
2993 pic14_emitcode("inc","sp");
2998 pic14_emitcode ("mov","a,_spx");
2999 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3000 pic14_emitcode ("mov","_spx,a");
3005 /*-----------------------------------------------------------------*/
3006 /* genEndFunction - generates epilogue for functions */
3007 /*-----------------------------------------------------------------*/
3008 static void genEndFunction (iCode *ic)
3010 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3014 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3016 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3018 pic14_emitcode ("mov","%s,_bp",spname);
3021 /* if use external stack but some variables were
3022 added to the local stack then decrement the
3024 if (options.useXstack && sym->stack) {
3025 pic14_emitcode("mov","a,sp");
3026 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3027 pic14_emitcode("mov","sp,a");
3031 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3032 if (options.useXstack) {
3033 pic14_emitcode("mov","r0,%s",spname);
3034 pic14_emitcode("movx","a,@r0");
3035 pic14_emitcode("mov","_bp,a");
3036 pic14_emitcode("dec","%s",spname);
3040 pic14_emitcode ("pop","_bp");
3044 /* restore the register bank */
3045 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3046 pic14_emitcode ("pop","psw");
3048 if (IFFUNC_ISISR(sym->type)) {
3050 /* now we need to restore the registers */
3051 /* if this isr has no bank i.e. is going to
3052 run with bank 0 , then we need to save more
3054 if (!FUNC_REGBANK(sym->type)) {
3056 /* if this function does not call any other
3057 function then we can be economical and
3058 save only those registers that are used */
3059 if (! IFFUNC_HASFCALL(sym->type)) {
3062 /* if any registers used */
3063 if (sym->regsUsed) {
3064 /* save the registers used */
3065 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3066 if (bitVectBitValue(sym->regsUsed,i) ||
3067 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3068 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3073 /* this function has a function call cannot
3074 determines register usage so we will have the
3076 unsaverbank(0,ic,FALSE);
3080 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3082 if (options.stack10bit)
3084 pic14_emitcode ("pop", "dpx1");
3085 pic14_emitcode ("pop", "dph1");
3086 pic14_emitcode ("pop", "dpl1");
3088 pic14_emitcode ("pop", "dps");
3089 pic14_emitcode ("pop", "dpx");
3091 if (!inExcludeList("dph"))
3092 pic14_emitcode ("pop","dph");
3093 if (!inExcludeList("dpl"))
3094 pic14_emitcode ("pop","dpl");
3095 if (!inExcludeList("b"))
3096 pic14_emitcode ("pop","b");
3097 if (!inExcludeList("acc"))
3098 pic14_emitcode ("pop","acc");
3100 if (IFFUNC_ISCRITICAL(sym->type))
3101 pic14_emitcode("setb","ea");
3104 /* if debug then send end of function */
3105 /* if (options.debug && currFunc) { */
3107 debugFile->writeEndFunction (currFunc, ic, 1);
3110 pic14_emitcode ("reti","");
3111 emitpcode(POC_MOVFW, popCopyReg(&pc_psave));
3112 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
3113 emitpcode(POC_CLRF, popCopyReg(&pc_status));
3114 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3115 emitpcode(POC_MOVWF, popCopyReg(&pc_status));
3116 emitpcode(POC_SWAPF, popCopyReg(&pc_wsave));
3117 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3118 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3119 emitpcodeNULLop(POC_RETFIE);
3122 if (IFFUNC_ISCRITICAL(sym->type))
3123 pic14_emitcode("setb","ea");
3125 if (IFFUNC_CALLEESAVES(sym->type)) {
3128 /* if any registers used */
3129 if (sym->regsUsed) {
3130 /* save the registers used */
3131 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3132 if (bitVectBitValue(sym->regsUsed,i) ||
3133 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3134 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3140 /* if debug then send end of function */
3142 debugFile->writeEndFunction (currFunc, ic, 1);
3145 pic14_emitcode ("return","");
3146 emitpcodeNULLop(POC_RETURN);
3148 /* Mark the end of a function */
3149 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3154 /*-----------------------------------------------------------------*/
3155 /* genRet - generate code for return statement */
3156 /*-----------------------------------------------------------------*/
3157 static void genRet (iCode *ic)
3159 int size,offset = 0;
3163 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3164 /* if we have no return value then
3165 just generate the "ret" */
3169 /* we have something to return then
3170 move the return value into place */
3171 aopOp(IC_LEFT(ic),ic,FALSE);
3172 size = AOP_SIZE(IC_LEFT(ic));
3174 for (offset = 0; offset < size; offset++)
3176 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
3179 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3182 /* generate a jump to the return label
3183 if the next is not the return statement */
3184 if (!(ic->next && ic->next->op == LABEL &&
3185 IC_LABEL(ic->next) == returnLabel)) {
3187 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3192 /*-----------------------------------------------------------------*/
3193 /* genLabel - generates a label */
3194 /*-----------------------------------------------------------------*/
3195 static void genLabel (iCode *ic)
3199 /* special case never generate */
3200 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3201 if (IC_LABEL(ic) == entryLabel)
3204 emitpLabel(IC_LABEL(ic)->key);
3205 pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3208 /*-----------------------------------------------------------------*/
3209 /* genGoto - generates a goto */
3210 /*-----------------------------------------------------------------*/
3212 static void genGoto (iCode *ic)
3216 emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3217 pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3221 /*-----------------------------------------------------------------*/
3222 /* genMultbits :- multiplication of bits */
3223 /*-----------------------------------------------------------------*/
3224 static void genMultbits (operand *left,
3229 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3231 if(!pic14_sameRegs(AOP(result),AOP(right)))
3232 emitpcode(POC_BSF, popGet(AOP(result),0));
3234 emitpcode(POC_BTFSC,popGet(AOP(right),0));
3235 emitpcode(POC_BTFSS,popGet(AOP(left),0));
3236 emitpcode(POC_BCF, popGet(AOP(result),0));
3241 /*-----------------------------------------------------------------*/
3242 /* genMultOneByte : 8 bit multiplication & division */
3243 /*-----------------------------------------------------------------*/
3244 static void genMultOneByte (operand *left,
3248 char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
3256 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3257 DEBUGpic14_AopType(__LINE__,left,right,result);
3258 DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3260 /* (if two literals, the value is computed before) */
3261 /* if one literal, literal on the right */
3262 if (AOP_TYPE(left) == AOP_LIT){
3268 assert (AOP_SIZE(left) == AOP_SIZE(right));
3270 size = min(AOP_SIZE(result),AOP_SIZE(left));
3271 offset = Gstack_base_addr - (2*size - 1);
3273 /* pass right operand as argument */
3274 for (i=0; i < size; i++)
3276 mov2w (AOP(right), i);
3277 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3280 /* pass left operand as argument */
3281 for (i=0; i < size; i++)
3283 mov2w (AOP(left), i);
3284 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3286 assert (offset == Gstack_base_addr);
3288 /* call library routine */
3289 assert (size > 0 && size <= 4);
3290 call_libraryfunc (func[size]);
3293 movwf (AOP(result), size-1);
3294 for (i=0; i < size - 1; i++)
3296 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
3297 movwf (AOP(result), size - 2 - i);
3300 /* now (zero-/sign) extend the result to its size */
3301 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
3304 /*-----------------------------------------------------------------*/
3305 /* genMult - generates code for multiplication */
3306 /*-----------------------------------------------------------------*/
3307 static void genMult (iCode *ic)
3309 operand *left = IC_LEFT(ic);
3310 operand *right = IC_RIGHT(ic);
3311 operand *result= IC_RESULT(ic);
3315 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3316 /* assign the amsops */
3317 aopOp (left,ic,FALSE);
3318 aopOp (right,ic,FALSE);
3319 aopOp (result,ic,TRUE);
3321 DEBUGpic14_AopType(__LINE__,left,right,result);
3323 /* special cases first */
3325 if (AOP_TYPE(left) == AOP_CRY &&
3326 AOP_TYPE(right)== AOP_CRY) {
3327 genMultbits(left,right,result);
3331 /* if both are of size == 1 */
3332 if (AOP_SIZE(left) == 1 &&
3333 AOP_SIZE(right) == 1 ) {
3334 genMultOneByte(left,right,result);
3338 /* should have been converted to function call */
3342 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3343 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3344 freeAsmop(result,NULL,ic,TRUE);
3347 /*-----------------------------------------------------------------*/
3348 /* genDivbits :- division of bits */
3349 /*-----------------------------------------------------------------*/
3350 static void genDivbits (operand *left,
3359 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3360 /* the result must be bit */
3361 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3362 l = aopGet(AOP(left),0,FALSE,FALSE);
3366 pic14_emitcode("div","ab");
3367 pic14_emitcode("rrc","a");
3368 aopPut(AOP(result),"c",0);
3371 /*-----------------------------------------------------------------*/
3372 /* genDivOneByte : 8 bit division */
3373 /*-----------------------------------------------------------------*/
3374 static void genDivOneByte (operand *left,
3382 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3384 assert (AOP_SIZE(right) == 1);
3385 assert (AOP_SIZE(left) == 1);
3387 size = min(AOP_SIZE(result),AOP_SIZE(left));
3388 sign = !(SPEC_USIGN(operandType(left))
3389 && SPEC_USIGN(operandType(right)));
3391 if (AOP_TYPE(right) == AOP_LIT)
3393 /* XXX: might add specialized code */
3398 /* unsigned division */
3400 mov2w(AOP(right),0);
3401 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3403 call_libraryfunc("__divuchar");
3404 movwf(AOP(result),0);
3409 temp = popGetTempReg();
3410 lbl = newiTempLabel(NULL);
3412 /* XXX: improve this naive approach:
3413 [result] = [a] / [b]
3414 ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
3418 movwf temp // temp <-- left
3419 movf right,W // W <-- right
3423 subwf temp,F // temp <-- temp - W
3424 skipNC // subwf clears CARRY (i.e. sets BORROW) if temp < W
3426 decf result // we just subtract once too often
3429 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3430 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
3433 emitpcode(POC_MOVWF, temp);
3434 mov2w(AOP(right),0);
3435 emitpcode(POC_CLRF, popGet(AOP(result),0));
3437 emitpLabel(lbl->key);
3438 emitpcode(POC_INCF, popGet(AOP(result),0));
3439 emitpcode(POC_SUBWF, temp);
3441 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3442 emitpcode(POC_DECF, popGet(AOP(result),0));
3447 /* signed division */
3448 mov2w(AOP(right),0);
3449 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3451 call_libraryfunc("__divschar");
3452 movwf(AOP(result),0);
3455 /* now performed the signed/unsigned division -- extend result */
3456 addSign(result, 1, sign);
3459 /*-----------------------------------------------------------------*/
3460 /* genDiv - generates code for division */
3461 /*-----------------------------------------------------------------*/
3462 static void genDiv (iCode *ic)
3464 operand *left = IC_LEFT(ic);
3465 operand *right = IC_RIGHT(ic);
3466 operand *result= IC_RESULT(ic);
3469 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3470 /* assign the amsops */
3471 aopOp (left,ic,FALSE);
3472 aopOp (right,ic,FALSE);
3473 aopOp (result,ic,TRUE);
3475 /* special cases first */
3477 if (AOP_TYPE(left) == AOP_CRY &&
3478 AOP_TYPE(right)== AOP_CRY) {
3479 genDivbits(left,right,result);
3483 /* if both are of size == 1 */
3484 if (AOP_SIZE(left) == 1 &&
3485 AOP_SIZE(right) == 1 ) {
3486 genDivOneByte(left,right,result);
3490 /* should have been converted to function call */
3493 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3494 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3495 freeAsmop(result,NULL,ic,TRUE);
3498 /*-----------------------------------------------------------------*/
3499 /* genModOneByte : 8 bit modulus */
3500 /*-----------------------------------------------------------------*/
3501 static void genModOneByte (operand *left,
3509 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3511 assert (AOP_SIZE(right) == 1);
3512 assert (AOP_SIZE(left) == 1);
3514 size = min(AOP_SIZE(result),AOP_SIZE(left));
3515 sign = !(SPEC_USIGN(operandType(left))
3516 && SPEC_USIGN(operandType(right)));
3518 if (AOP_TYPE(right) == AOP_LIT)
3520 /* XXX: might add specialized code */
3525 /* unsigned division */
3527 mov2w(AOP(right),0);
3528 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3530 call_libraryfunc("__moduchar");
3531 movwf(AOP(result),0);
3536 lbl = newiTempLabel(NULL);
3538 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3540 /* XXX: improve this naive approach:
3541 [result] = [a] % [b]
3542 ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3546 movwf result // result <-- left
3547 movf right,W // W <-- right
3549 subwf result,F // result <-- result - W
3550 skipNC // subwf clears CARRY (i.e. sets BORROW) if result < W
3552 addwf result, F // we just subtract once too often
3555 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3556 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3558 if (!pic14_sameRegs(AOP(left), AOP(result)))
3561 emitpcode(POC_MOVWF, popGet(AOP(result),0));
3563 mov2w(AOP(right),0);
3565 emitpLabel(lbl->key);
3566 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3568 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3569 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3574 /* signed division */
3575 mov2w(AOP(right),0);
3576 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3578 call_libraryfunc("__modschar");
3579 movwf(AOP(result),0);
3582 /* now we performed the signed/unsigned modulus -- extend result */
3583 addSign(result, 1, sign);
3586 /*-----------------------------------------------------------------*/
3587 /* genMod - generates code for division */
3588 /*-----------------------------------------------------------------*/
3589 static void genMod (iCode *ic)
3591 operand *left = IC_LEFT(ic);
3592 operand *right = IC_RIGHT(ic);
3593 operand *result= IC_RESULT(ic);
3596 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3597 /* assign the amsops */
3598 aopOp (left,ic,FALSE);
3599 aopOp (right,ic,FALSE);
3600 aopOp (result,ic,TRUE);
3602 /* if both are of size == 1 */
3603 if (AOP_SIZE(left) == 1 &&
3604 AOP_SIZE(right) == 1 ) {
3605 genModOneByte(left,right,result);
3609 /* should have been converted to function call */
3613 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3614 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3615 freeAsmop(result,NULL,ic,TRUE);
3618 /*-----------------------------------------------------------------*/
3619 /* genIfxJump :- will create a jump depending on the ifx */
3620 /*-----------------------------------------------------------------*/
3622 note: May need to add parameter to indicate when a variable is in bit space.
3624 static void genIfxJump (iCode *ic, char *jval)
3628 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3629 /* if true label then we jump if condition
3631 if ( IC_TRUE(ic) ) {
3633 if(strcmp(jval,"a") == 0)
3635 else if (strcmp(jval,"c") == 0)
3638 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3639 emitpcode(POC_BTFSC, newpCodeOpBit(jval,-1,1));
3642 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3643 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3647 /* false label is present */
3648 if(strcmp(jval,"a") == 0)
3650 else if (strcmp(jval,"c") == 0)
3653 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3654 emitpcode(POC_BTFSS, newpCodeOpBit(jval,-1,1));
3657 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3658 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3663 /* mark the icode as generated */
3668 /*-----------------------------------------------------------------*/
3670 /*-----------------------------------------------------------------*/
3671 static void genSkip(iCode *ifx,int status_bit)
3677 if ( IC_TRUE(ifx) ) {
3678 switch(status_bit) {
3693 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3694 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3698 switch(status_bit) {
3712 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3713 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3720 /*-----------------------------------------------------------------*/
3722 /*-----------------------------------------------------------------*/
3723 static void genSkipc(resolvedIfx *rifx)
3734 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3735 emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3736 rifx->generated = 1;
3740 /*-----------------------------------------------------------------*/
3742 /*-----------------------------------------------------------------*/
3743 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3749 if( (rifx->condition ^ invert_condition) & 1)
3754 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3755 rifx->generated = 1;
3760 /*-----------------------------------------------------------------*/
3762 /*-----------------------------------------------------------------*/
3763 static void genSkipz(iCode *ifx, int condition)
3766 assert (ifx != NULL);
3774 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3776 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3779 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3781 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3787 /*-----------------------------------------------------------------*/
3789 /*-----------------------------------------------------------------*/
3790 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3797 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3799 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3802 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3803 rifx->generated = 1;
3808 /*-----------------------------------------------------------------*/
3809 /* genChkZeroes :- greater or less than comparison */
3810 /* For each byte in a literal that is zero, inclusive or the */
3811 /* the corresponding byte in the operand with W */
3812 /* returns true if any of the bytes are zero */
3813 /*-----------------------------------------------------------------*/
3814 static int genChkZeroes(operand *op, int lit, int size)
3821 i = (lit >> (size*8)) & 0xff;
3825 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3827 emitpcode(POC_IORFW, popGet(AOP(op),size));
3837 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3838 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
3839 #define DEBUGpc emitpComment
3841 /*-----------------------------------------------------------------*/
3842 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
3843 /* aop (if it's NOT a literal) or from lit (if */
3844 /* aop is a literal) */
3845 /*-----------------------------------------------------------------*/
3846 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3847 if (aop->type == AOP_LIT) {
3848 emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3850 emitpcode (POC_MOVFW, popGet (aop, offset));
3854 /* genCmp performs a left < right comparison, stores
3855 * the outcome in result (if != NULL) and generates
3856 * control flow code for the ifx (if != NULL).
3858 * This version leaves in sequences like
3859 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3860 * which should be optmized by the peephole
3861 * optimizer - RN 2005-01-01 */
3862 static void genCmp (operand *left,operand *right,
3863 operand *result, iCode *ifx, int sign)
3873 int invert_result = 0;
3877 assert (AOP_SIZE(left) == AOP_SIZE(right));
3878 assert (left && right);
3880 size = AOP_SIZE(right) - 1;
3881 mask = (0x100UL << (size*8)) - 1;
3882 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3887 resolveIfx (&rIfx, ifx);
3889 /**********************************************************************
3890 * handle bits - bit compares are promoted to int compares seemingly! *
3891 **********************************************************************/
3893 // THIS IS COMPLETELY UNTESTED!
3894 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3895 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3896 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3897 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3900 // 1 < {0,1} is false --> clear C by skipping the next instruction
3901 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3902 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3903 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3904 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3905 emitCLRC; // only skipped for left=0 && right=1
3907 goto correct_result_in_carry;
3911 /*************************************************
3912 * make sure that left is register (or the like) *
3913 *************************************************/
3914 if (!isAOP_REGlike(left)) {
3915 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
3916 assert (isAOP_LIT(left));
3917 assert (isAOP_REGlike(right));
3918 // swap left and right
3919 // left < right <==> right > left <==> (right >= left + 1)
3920 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3922 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
3923 // MAXVALUE < right? always false
3924 if (performedLt) emitCLRC; else emitSETC;
3925 goto correct_result_in_carry;
3928 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
3929 // that's why we handled it above.
3936 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
3937 } else if (isAOP_LIT(right)) {
3938 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3941 assert (isAOP_REGlike(left)); // left must be register or the like
3942 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
3944 /*************************************************
3945 * special cases go here *
3946 *************************************************/
3948 if (isAOP_LIT(right)) {
3950 // unsigned comparison to a literal
3951 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
3953 // unsigned left < 0? always false
3954 if (performedLt) emitCLRC; else emitSETC;
3955 goto correct_result_in_carry;
3958 // signed comparison to a literal
3959 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
3960 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
3961 // signed left < 0x80000000? always false
3962 if (performedLt) emitCLRC; else emitSETC;
3963 goto correct_result_in_carry;
3964 } else if (lit == 0) {
3965 // compare left < 0; set CARRY if SIGNBIT(left) is set
3966 if (performedLt) emitSETC; else emitCLRC;
3967 emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
3968 if (performedLt) emitCLRC; else emitSETC;
3969 goto correct_result_in_carry;
3972 } // right is literal
3974 /*************************************************
3975 * perform a general case comparison *
3976 * make sure we get CARRY==1 <==> left >= right *
3977 *************************************************/
3978 // compare most significant bytes
3979 //DEBUGpc ("comparing bytes at offset %d", size);
3981 // unsigned comparison
3982 pic14_mov2w_regOrLit (AOP(right), lit, size);
3983 emitpcode (POC_SUBFW, popGet (AOP(left), size));
3985 // signed comparison
3986 // (add 2^n to both operands then perform an unsigned comparison)
3987 if (isAOP_LIT(right)) {
3988 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
3989 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
3991 if (litbyte == 0x80) {
3992 // left >= 0x80 -- always true, but more bytes to come
3993 mov2w (AOP(left), size);
3994 emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
3997 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
3998 mov2w (AOP(left), size);
3999 emitpcode (POC_ADDLW, popGetLit (0x80));
4000 emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4003 pCodeOp *pctemp = popGetTempReg();
4004 mov2w (AOP(left), size);
4005 emitpcode (POC_ADDLW, popGetLit (0x80));
4006 emitpcode (POC_MOVWF, pctemp);
4007 mov2w (AOP(right), size);
4008 emitpcode (POC_ADDLW, popGetLit (0x80));
4009 emitpcode (POC_SUBFW, pctemp);
4010 popReleaseTempReg(pctemp);
4014 // compare remaining bytes (treat as unsigned case from above)
4015 templbl = newiTempLabel ( NULL );
4018 //DEBUGpc ("comparing bytes at offset %d", offs);
4020 emitpcode (POC_GOTO, popGetLabel (templbl->key));
4021 pic14_mov2w_regOrLit (AOP(right), lit, offs);
4022 emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4024 emitpLabel (templbl->key);
4025 goto result_in_carry;
4029 /****************************************************
4030 * now CARRY contains the result of the comparison: *
4031 * SUBWF sets CARRY iff *
4032 * F-W >= 0 <==> F >= W <==> !(F < W) *
4033 * (F=left, W=right) *
4034 ****************************************************/
4038 // value will be used in the following genSkipc()
4039 rIfx.condition ^= 1;
4042 correct_result_in_carry:
4044 // assign result to variable (if neccessary)
4045 if (result && AOP_TYPE(result) != AOP_CRY) {
4046 //DEBUGpc ("assign result");
4047 size = AOP_SIZE(result);
4049 emitpcode (POC_CLRF, popGet (AOP(result), size));
4051 if (invert_result) {
4053 emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4055 emitpcode (POC_RLF, popGet (AOP(result), 0));
4059 // perform conditional jump
4061 //DEBUGpc ("generate control flow");
4069 /* OLD VERSION -- BUGGY, DO NOT USE */
4071 /*-----------------------------------------------------------------*/
4072 /* genCmp :- greater or less than comparison */
4073 /*-----------------------------------------------------------------*/
4074 static void genCmp (operand *left,operand *right,
4075 operand *result, iCode *ifx, int sign)
4077 int size; //, offset = 0 ;
4078 unsigned long lit = 0L,i = 0;
4079 resolvedIfx rFalseIfx;
4080 // resolvedIfx rTrueIfx;
4084 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4087 DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4088 DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4092 resolveIfx(&rFalseIfx,ifx);
4093 truelbl = newiTempLabel(NULL);
4094 size = max(AOP_SIZE(left),AOP_SIZE(right));
4096 DEBUGpic14_AopType(__LINE__,left,right,result);
4100 /* if literal is on the right then swap with left */
4101 if ((AOP_TYPE(right) == AOP_LIT)) {
4102 operand *tmp = right ;
4103 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4104 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4107 lit = (lit - 1) & mask;
4110 rFalseIfx.condition ^= 1;
4113 } else if ((AOP_TYPE(left) == AOP_LIT)) {
4114 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4118 //if(IC_TRUE(ifx) == NULL)
4119 /* if left & right are bit variables */
4120 if (AOP_TYPE(left) == AOP_CRY &&
4121 AOP_TYPE(right) == AOP_CRY ) {
4122 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4123 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4125 /* subtract right from left if at the
4126 end the carry flag is set then we know that
4127 left is greater than right */
4129 symbol *lbl = newiTempLabel(NULL);
4132 if(AOP_TYPE(right) == AOP_LIT) {
4134 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4136 DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4143 genSkipCond(&rFalseIfx,left,size-1,7);
4145 /* no need to compare to 0...*/
4146 /* NOTE: this is a de-generate compare that most certainly
4147 * creates some dead code. */
4148 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4150 if(ifx) ifx->generated = 1;
4157 //i = (lit >> (size*8)) & 0xff;
4158 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4160 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4162 i = ((0-lit) & 0xff);
4165 /* lit is 0x7f, all signed chars are less than
4166 * this except for 0x7f itself */
4167 emitpcode(POC_XORLW, popGetLit(0x7f));
4168 genSkipz2(&rFalseIfx,0);
4170 emitpcode(POC_ADDLW, popGetLit(0x80));
4171 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4172 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4177 genSkipz2(&rFalseIfx,1);
4179 emitpcode(POC_ADDLW, popGetLit(i));
4180 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4184 if(ifx) ifx->generated = 1;
4188 /* chars are out of the way. now do ints and longs */
4191 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4198 genSkipCond(&rFalseIfx,left,size,7);
4199 if(ifx) ifx->generated = 1;
4204 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4206 //rFalseIfx.condition ^= 1;
4207 //genSkipCond(&rFalseIfx,left,size,7);
4208 //rFalseIfx.condition ^= 1;
4210 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4211 if(rFalseIfx.condition)
4212 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4214 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4216 emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4217 emitpcode(POC_ADDFW, popGet(AOP(left),0));
4218 emitpcode(POC_MOVFW, popGet(AOP(left),1));
4221 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4223 if(rFalseIfx.condition) {
4225 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4231 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4232 emitpLabel(truelbl->key);
4233 if(ifx) ifx->generated = 1;
4240 if( (lit & 0xff) == 0) {
4241 /* lower byte is zero */
4242 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4243 i = ((lit >> 8) & 0xff) ^0x80;
4244 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4245 emitpcode(POC_ADDLW, popGetLit( 0x80));
4246 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4247 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4250 if(ifx) ifx->generated = 1;
4255 /* Special cases for signed longs */
4256 if( (lit & 0xffffff) == 0) {
4257 /* lower byte is zero */
4258 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4259 i = ((lit >> 8*3) & 0xff) ^0x80;
4260 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4261 emitpcode(POC_ADDLW, popGetLit( 0x80));
4262 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4263 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4266 if(ifx) ifx->generated = 1;
4274 if(lit & (0x80 << (size*8))) {
4275 /* lit is negative */
4276 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4278 //genSkipCond(&rFalseIfx,left,size,7);
4280 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4282 if(rFalseIfx.condition)
4283 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4285 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4289 /* lit is positive */
4290 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4291 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4292 if(rFalseIfx.condition)
4293 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4295 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4299 /* There are no more special cases, so perform a general compare */
4301 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4302 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4306 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4308 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4310 //rFalseIfx.condition ^= 1;
4311 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4313 emitpLabel(truelbl->key);
4315 if(ifx) ifx->generated = 1;
4322 /* sign is out of the way. So now do an unsigned compare */
4323 DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4326 /* General case - compare to an unsigned literal on the right.*/
4328 i = (lit >> (size*8)) & 0xff;
4329 emitpcode(POC_MOVLW, popGetLit(i));
4330 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4332 i = (lit >> (size*8)) & 0xff;
4335 emitpcode(POC_MOVLW, popGetLit(i));
4337 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4339 /* this byte of the lit is zero,
4340 *if it's not the last then OR in the variable */
4342 emitpcode(POC_IORFW, popGet(AOP(left),size));
4347 emitpLabel(lbl->key);
4348 //if(emitFinalCheck)
4349 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4351 emitpLabel(truelbl->key);
4353 if(ifx) ifx->generated = 1;
4360 if(AOP_TYPE(left) == AOP_LIT) {
4361 //symbol *lbl = newiTempLabel(NULL);
4363 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4366 DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4369 if((lit == 0) && (sign == 0)){
4372 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4374 emitpcode(POC_IORFW, popGet(AOP(right),--size));
4376 genSkipz2(&rFalseIfx,0);
4377 if(ifx) ifx->generated = 1;
4384 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4385 /* degenerate compare can never be true */
4386 if(rFalseIfx.condition == 0)
4387 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4389 if(ifx) ifx->generated = 1;
4394 /* signed comparisons to a literal byte */
4396 int lp1 = (lit+1) & 0xff;
4398 DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4401 rFalseIfx.condition ^= 1;
4402 genSkipCond(&rFalseIfx,right,0,7);
4405 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4406 emitpcode(POC_XORLW, popGetLit(0x7f));
4407 genSkipz2(&rFalseIfx,1);
4410 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4411 emitpcode(POC_ADDLW, popGetLit(0x80));
4412 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4413 rFalseIfx.condition ^= 1;
4414 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4417 if(ifx) ifx->generated = 1;
4419 /* unsigned comparisons to a literal byte */
4421 switch(lit & 0xff ) {
4423 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4424 genSkipz2(&rFalseIfx,0);
4425 if(ifx) ifx->generated = 1;
4428 genSkipCond(&rFalseIfx,right,0,7);
4429 if(ifx) ifx->generated = 1;
4433 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4434 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4435 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4436 rFalseIfx.condition ^= 1;
4437 if (AOP_TYPE(result) == AOP_CRY) {
4438 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4439 if(ifx) ifx->generated = 1;
4441 DEBUGpic14_emitcode ("; ***","%s %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4442 emitpcode(POC_CLRF, popGet(AOP(result),0));
4443 emitpcode(POC_RLF, popGet(AOP(result),0));
4444 emitpcode(POC_MOVLW, popGetLit(0x01));
4445 emitpcode(POC_XORWF, popGet(AOP(result),0));
4456 /* Size is greater than 1 */
4464 /* this means lit = 0xffffffff, or -1 */
4467 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4468 rFalseIfx.condition ^= 1;
4469 genSkipCond(&rFalseIfx,right,size,7);
4470 if(ifx) ifx->generated = 1;
4477 if(rFalseIfx.condition) {
4478 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4479 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4482 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4484 emitpcode(POC_IORFW, popGet(AOP(right),size));
4488 if(rFalseIfx.condition) {
4489 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4490 emitpLabel(truelbl->key);
4492 rFalseIfx.condition ^= 1;
4493 genSkipCond(&rFalseIfx,right,s,7);
4496 if(ifx) ifx->generated = 1;
4500 if((size == 1) && (0 == (lp1&0xff))) {
4501 /* lower byte of signed word is zero */
4502 DEBUGpic14_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
4503 i = ((lp1 >> 8) & 0xff) ^0x80;
4504 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4505 emitpcode(POC_ADDLW, popGetLit( 0x80));
4506 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4507 rFalseIfx.condition ^= 1;
4508 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4511 if(ifx) ifx->generated = 1;
4515 if(lit & (0x80 << (size*8))) {
4516 /* Lit is less than zero */
4517 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
4518 //rFalseIfx.condition ^= 1;
4519 //genSkipCond(&rFalseIfx,left,size,7);
4520 //rFalseIfx.condition ^= 1;
4521 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4522 //emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4524 if(rFalseIfx.condition)
4525 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4527 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4531 /* Lit is greater than or equal to zero */
4532 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
4533 //rFalseIfx.condition ^= 1;
4534 //genSkipCond(&rFalseIfx,right,size,7);
4535 //rFalseIfx.condition ^= 1;
4537 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4538 //emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4540 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4541 if(rFalseIfx.condition)
4542 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4544 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4549 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4550 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4554 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4556 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4558 rFalseIfx.condition ^= 1;
4559 //rFalseIfx.condition = 1;
4560 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4562 emitpLabel(truelbl->key);
4564 if(ifx) ifx->generated = 1;
4569 /* compare word or long to an unsigned literal on the right.*/
4574 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4577 break; /* handled above */
4580 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4582 emitpcode(POC_IORFW, popGet(AOP(right),size));
4583 genSkipz2(&rFalseIfx,0);
4587 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4589 emitpcode(POC_IORFW, popGet(AOP(right),size));
4592 if(rFalseIfx.condition)
4593 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4595 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4598 emitpcode(POC_MOVLW, popGetLit(lit+1));
4599 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4601 rFalseIfx.condition ^= 1;
4602 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4605 emitpLabel(truelbl->key);
4607 if(ifx) ifx->generated = 1;
4613 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4614 i = (lit >> (size*8)) & 0xff;
4616 emitpcode(POC_MOVLW, popGetLit(i));
4617 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4620 i = (lit >> (size*8)) & 0xff;
4623 emitpcode(POC_MOVLW, popGetLit(i));
4625 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4627 /* this byte of the lit is zero,
4628 *if it's not the last then OR in the variable */
4630 emitpcode(POC_IORFW, popGet(AOP(right),size));
4635 emitpLabel(lbl->key);
4637 rFalseIfx.condition ^= 1;
4638 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4642 emitpLabel(truelbl->key);
4643 if(ifx) ifx->generated = 1;
4647 /* Compare two variables */
4649 DEBUGpic14_emitcode(";sign","%d",sign);
4653 /* Sigh. thus sucks... */
4655 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4656 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4657 emitpcode(POC_MOVLW, popGetLit(0x80));
4658 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4659 emitpcode(POC_XORFW, popGet(AOP(right),size));
4660 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4662 /* Signed char comparison */
4663 /* Special thanks to Nikolai Golovchenko for this snippet */
4664 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4665 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4666 emitpcode(POC_RRFW, popGet(AOP(left),0)); /* could be any register */
4667 emitpcode(POC_XORFW, popGet(AOP(left),0));
4668 emitpcode(POC_XORFW, popGet(AOP(right),0));
4669 emitpcode(POC_ADDLW, popGetLit(0x80));
4671 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4672 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4674 if(ifx) ifx->generated = 1;
4680 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4681 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4685 /* The rest of the bytes of a multi-byte compare */
4689 emitpcode(POC_GOTO, popGetLabel(lbl->key));
4692 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4693 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4698 emitpLabel(lbl->key);
4700 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4701 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
4702 (AOP_TYPE(result) == AOP_REG)) {
4703 emitpcode(POC_CLRF, popGet(AOP(result),0));
4704 emitpcode(POC_RLF, popGet(AOP(result),0));
4706 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4708 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4709 if(ifx) ifx->generated = 1;
4716 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4717 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4718 pic14_outBitC(result);
4720 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4721 /* if the result is used in the next
4722 ifx conditional branch then generate
4723 code a little differently */
4725 genIfxJump (ifx,"c");
4727 pic14_outBitC(result);
4728 /* leave the result in acc */
4734 /*-----------------------------------------------------------------*/
4735 /* genCmpGt :- greater than comparison */
4736 /*-----------------------------------------------------------------*/
4737 static void genCmpGt (iCode *ic, iCode *ifx)
4739 operand *left, *right, *result;
4740 sym_link *letype , *retype;
4744 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4746 right= IC_RIGHT(ic);
4747 result = IC_RESULT(ic);
4749 letype = getSpec(operandType(left));
4750 retype =getSpec(operandType(right));
4751 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4752 /* assign the amsops */
4753 aopOp (left,ic,FALSE);
4754 aopOp (right,ic,FALSE);
4755 aopOp (result,ic,TRUE);
4757 genCmp(right, left, result, ifx, sign);
4759 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4760 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4761 freeAsmop(result,NULL,ic,TRUE);
4764 /*-----------------------------------------------------------------*/
4765 /* genCmpLt - less than comparisons */
4766 /*-----------------------------------------------------------------*/
4767 static void genCmpLt (iCode *ic, iCode *ifx)
4769 operand *left, *right, *result;
4770 sym_link *letype , *retype;
4774 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4776 right= IC_RIGHT(ic);
4777 result = IC_RESULT(ic);
4779 letype = getSpec(operandType(left));
4780 retype =getSpec(operandType(right));
4781 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4783 /* assign the amsops */
4784 aopOp (left,ic,FALSE);
4785 aopOp (right,ic,FALSE);
4786 aopOp (result,ic,TRUE);
4788 genCmp(left, right, result, ifx, sign);
4790 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4791 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4792 freeAsmop(result,NULL,ic,TRUE);
4796 /*-----------------------------------------------------------------*/
4797 /* genc16bit2lit - compare a 16 bit value to a literal */
4798 /*-----------------------------------------------------------------*/
4799 static void genc16bit2lit(operand *op, int lit, int offset)
4804 DEBUGpic14_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
4805 if( (lit&0xff) == 0)
4810 switch( BYTEofLONG(lit,i)) {
4812 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4815 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4818 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4821 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4822 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4827 switch( BYTEofLONG(lit,i)) {
4829 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4833 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4837 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4840 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4842 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4850 /*-----------------------------------------------------------------*/
4851 /* gencjneshort - compare and jump if not equal */
4852 /*-----------------------------------------------------------------*/
4853 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4855 int size = min(AOP_SIZE(left),AOP_SIZE(right));
4860 //unsigned long lit = 0L;
4862 if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4863 emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4866 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4867 DEBUGpic14_AopType(__LINE__,left,right,result);
4869 assert (!pic14_sameRegs (AOP(left), AOP(result)));
4870 assert (!pic14_sameRegs (AOP(right), AOP(result)));
4871 if (AOP_SIZE(result)) {
4872 for (offset = 0; offset < AOP_SIZE(result); offset++)
4873 emitpcode (POC_CLRF, popGet (AOP(result), offset));
4876 assert (AOP_SIZE(left) == AOP_SIZE(right));
4877 //resolveIfx(&rIfx,ifx);
4878 lbl = newiTempLabel (NULL);
4881 mov2w (AOP(right),size);
4882 emitpcode (POC_XORFW, popGet (AOP(left), size));
4886 emitpcode (POC_GOTO, popGetLabel (lbl->key));
4889 emitpLabel (lbl->key);
4890 if (AOP_SIZE(result)) {
4892 emitpcode (POC_INCF, popGet (AOP(result), 0));
4895 genSkipz (ifx, NULL != IC_TRUE(ifx));
4902 DEBUGpic14_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
4903 assert (!pic14_sameRegs (AOP(result), AOP(left)));
4904 assert (!pic14_sameRegs (AOP(result), AOP(right)));
4905 for (offset=0; offset < AOP_SIZE(result); offset++)
4907 emitpcode (POC_CLRF, popGet (AOP(result), offset));
4912 /* if the left side is a literal or
4913 if the right is in a pointer register and left
4915 if ((AOP_TYPE(left) == AOP_LIT) ||
4916 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4921 if(AOP_TYPE(right) == AOP_LIT)
4922 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4924 /* if the right side is a literal then anything goes */
4925 if (AOP_TYPE(right) == AOP_LIT &&
4926 AOP_TYPE(left) != AOP_DIR ) {
4929 genc16bit2lit(left, lit, 0);
4931 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4937 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4938 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4940 emitpcode(POC_MOVF,popGet(AOP(left),offset));
4944 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4952 /* if the right side is in a register or in direct space or
4953 if the left is a pointer register & right is not */
4954 else if (AOP_TYPE(right) == AOP_REG ||
4955 AOP_TYPE(right) == AOP_DIR ||
4956 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4957 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4958 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4959 int lbl_key = lbl->key;
4962 DEBUGpic14_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
4963 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
4964 __FUNCTION__,__LINE__);
4968 /* switch(size) { */
4970 /* genc16bit2lit(left, lit, 0); */
4972 /* emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
4978 if((AOP_TYPE(left) == AOP_DIR) &&
4979 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4981 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4982 emitpcode(POC_XORFW,popGet(AOP(right),offset));
4984 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4986 switch (lit & 0xff) {
4988 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4991 emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4992 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4993 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4997 emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4998 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4999 //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5000 emitpcode(POC_GOTO,popGetLabel(lbl_key));
5004 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5005 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5010 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5013 if(AOP_TYPE(result) == AOP_CRY) {
5014 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5019 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5021 /* fix me. probably need to check result size too */
5022 //emitpcode(POC_CLRF,popGet(AOP(result),0));
5027 emitpcode(POC_GOTO,popGetLabel(lbl_key));
5037 } else if(AOP_TYPE(right) == AOP_REG &&
5038 AOP_TYPE(left) != AOP_DIR){
5042 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5043 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5044 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5049 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5054 /* right is a pointer reg need both a & b */
5057 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5059 pic14_emitcode("mov","b,%s",l);
5060 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5061 pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
5066 emitpcode(POC_INCF,popGet(AOP(result),0));
5068 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5070 emitpLabel(lbl->key);
5072 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5081 /*-----------------------------------------------------------------*/
5082 /* gencjne - compare and jump if not equal */
5083 /*-----------------------------------------------------------------*/
5084 static void gencjne(operand *left, operand *right, iCode *ifx)
5086 symbol *tlbl = newiTempLabel(NULL);
5088 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5089 gencjneshort(left, right, lbl);
5091 pic14_emitcode("mov","a,%s",one);
5092 pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5093 pic14_emitcode("","%05d_DS_:",lbl->key+100);
5094 pic14_emitcode("clr","a");
5095 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5097 emitpLabel(lbl->key);
5098 emitpLabel(tlbl->key);
5103 /*-----------------------------------------------------------------*/
5104 /* genCmpEq - generates code for equal to */
5105 /*-----------------------------------------------------------------*/
5106 static void genCmpEq (iCode *ic, iCode *ifx)
5108 operand *left, *right, *result;
5110 symbol *false_label;
5113 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5116 DEBUGpic14_emitcode ("; ifx is non-null","");
5118 DEBUGpic14_emitcode ("; ifx is null","");
5120 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5121 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5122 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5124 DEBUGpic14_AopType(__LINE__,left,right,result);
5126 /* if literal, move literal to right */
5127 if (op_isLitLike (IC_LEFT(ic))) {
5128 operand *tmp = right ;
5134 if (ifx && !IC_TRUE(ifx))
5136 assert (IC_FALSE(ifx));
5137 false_label = IC_FALSE(ifx);
5140 size = min(AOP_SIZE(left),AOP_SIZE(right));
5141 assert(!pic14_sameRegs(AOP(result),AOP(left)));
5142 assert(!pic14_sameRegs(AOP(result),AOP(right)));
5144 /* assume left != right */
5147 for (i=0; i < AOP_SIZE(result); i++)
5149 emitpcode(POC_CLRF, popGet(AOP(result),i));
5153 if (AOP_TYPE(right) == AOP_LIT)
5155 unsigned long lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
5157 size = AOP_SIZE(left);
5158 assert(!op_isLitLike(left));
5163 mov2w(AOP(left), 0);
5164 for (i=1; i < size; i++)
5165 emitpcode(POC_IORFW,popGet(AOP(left),i));
5166 /* now Z is set iff `left == right' */
5168 if (!false_label) false_label = newiTempLabel(NULL);
5169 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5173 for (i=0; i < size; i++)
5176 emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
5177 /* now Z is cleared if `left != right' */
5179 if (!false_label) false_label = newiTempLabel(NULL);
5180 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5187 /* right is no literal */
5190 for (i=0; i < size; i++)
5192 mov2w(AOP(right),i);
5193 emitpcode(POC_XORFW,popGet(AOP(left),i));
5194 /* now Z is cleared if `left != right' */
5196 if (!false_label) false_label = newiTempLabel(NULL);
5197 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5201 /* if we reach here, left == right */
5203 if (AOP_SIZE(result) > 0)
5205 emitpcode(POC_INCF, popGet(AOP(result),0));
5208 if (ifx && IC_TRUE(ifx))
5210 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5213 if (false_label && (!ifx || IC_TRUE(ifx)))
5214 emitpLabel(false_label->key);
5216 if (ifx) ifx->generated = 1;
5218 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5219 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5220 freeAsmop(result,NULL,ic,TRUE);
5223 /*-----------------------------------------------------------------*/
5224 /* ifxForOp - returns the icode containing the ifx for operand */
5225 /*-----------------------------------------------------------------*/
5226 static iCode *ifxForOp ( operand *op, iCode *ic )
5229 /* if true symbol then needs to be assigned */
5230 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5231 if (IS_TRUE_SYMOP(op))
5234 /* if this has register type condition and
5235 the next instruction is ifx with the same operand
5236 and live to of the operand is upto the ifx only then */
5238 ic->next->op == IFX &&
5239 IC_COND(ic->next)->key == op->key &&
5240 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5244 ic->next->op == IFX &&
5245 IC_COND(ic->next)->key == op->key) {
5246 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5250 DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5252 ic->next->op == IFX)
5253 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5256 ic->next->op == IFX &&
5257 IC_COND(ic->next)->key == op->key) {
5258 DEBUGpic14_emitcode ("; "," key is okay");
5259 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5260 OP_SYMBOL(op)->liveTo,
5267 /*-----------------------------------------------------------------*/
5268 /* genAndOp - for && operation */
5269 /*-----------------------------------------------------------------*/
5270 static void genAndOp (iCode *ic)
5272 operand *left,*right, *result;
5276 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5277 /* note here that && operations that are in an
5278 if statement are taken away by backPatchLabels
5279 only those used in arthmetic operations remain */
5280 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5281 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5282 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5284 DEBUGpic14_AopType(__LINE__,left,right,result);
5286 emitpcode(POC_MOVFW,popGet(AOP(left),0));
5287 emitpcode(POC_ANDFW,popGet(AOP(right),0));
5288 emitpcode(POC_MOVWF,popGet(AOP(result),0));
5290 /* if both are bit variables */
5291 /* if (AOP_TYPE(left) == AOP_CRY && */
5292 /* AOP_TYPE(right) == AOP_CRY ) { */
5293 /* pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5294 /* pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5295 /* pic14_outBitC(result); */
5297 /* tlbl = newiTempLabel(NULL); */
5298 /* pic14_toBoolean(left); */
5299 /* pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5300 /* pic14_toBoolean(right); */
5301 /* pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5302 /* pic14_outBitAcc(result); */
5305 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5306 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5307 freeAsmop(result,NULL,ic,TRUE);
5311 /*-----------------------------------------------------------------*/
5312 /* genOrOp - for || operation */
5313 /*-----------------------------------------------------------------*/
5316 modified this code, but it doesn't appear to ever get called
5319 static void genOrOp (iCode *ic)
5321 operand *left,*right, *result;
5325 /* note here that || operations that are in an
5326 if statement are taken away by backPatchLabels
5327 only those used in arthmetic operations remain */
5329 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5330 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5331 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5332 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5334 DEBUGpic14_AopType(__LINE__,left,right,result);
5336 for (i=0; i < AOP_SIZE(result); i++)
5338 emitpcode(POC_CLRF, popGet(AOP(result), i));
5341 tlbl = newiTempLabel(NULL);
5342 pic14_toBoolean(left);
5344 emitpcode(POC_GOTO, popGetLabel(tlbl->key));
5345 pic14_toBoolean(right);
5346 emitpLabel(tlbl->key);
5347 /* here Z is clear IFF `left || right' */
5349 emitpcode(POC_INCF, popGet(AOP(result), 0));
5351 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5352 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5353 freeAsmop(result,NULL,ic,TRUE);
5356 /*-----------------------------------------------------------------*/
5357 /* isLiteralBit - test if lit == 2^n */
5358 /*-----------------------------------------------------------------*/
5359 static int isLiteralBit(unsigned long lit)
5361 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5362 0x100L,0x200L,0x400L,0x800L,
5363 0x1000L,0x2000L,0x4000L,0x8000L,
5364 0x10000L,0x20000L,0x40000L,0x80000L,
5365 0x100000L,0x200000L,0x400000L,0x800000L,
5366 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5367 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5371 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5372 for(idx = 0; idx < 32; idx++)
5378 /*-----------------------------------------------------------------*/
5379 /* continueIfTrue - */
5380 /*-----------------------------------------------------------------*/
5381 static void continueIfTrue (iCode *ic)
5384 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5388 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
5389 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5394 /*-----------------------------------------------------------------*/
5396 /*-----------------------------------------------------------------*/
5397 static void jumpIfTrue (iCode *ic)
5400 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5404 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
5405 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5410 /*-----------------------------------------------------------------*/
5411 /* jmpTrueOrFalse - */
5412 /*-----------------------------------------------------------------*/
5413 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5416 // ugly but optimized by peephole
5417 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5419 symbol *nlbl = newiTempLabel(NULL);
5420 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5421 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5422 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5423 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5426 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5427 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5432 /*-----------------------------------------------------------------*/
5433 /* genAnd - code for and */
5434 /*-----------------------------------------------------------------*/
5435 static void genAnd (iCode *ic, iCode *ifx)
5437 operand *left, *right, *result;
5439 unsigned long lit = 0L;
5444 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5445 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5446 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5447 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5449 resolveIfx(&rIfx,ifx);
5451 /* if left is a literal & right is not then exchange them */
5452 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5453 AOP_NEEDSACC(left)) {
5454 operand *tmp = right ;
5459 /* if result = right then exchange them */
5460 if(pic14_sameRegs(AOP(result),AOP(right))){
5461 operand *tmp = right ;
5466 /* if right is bit then exchange them */
5467 if (AOP_TYPE(right) == AOP_CRY &&
5468 AOP_TYPE(left) != AOP_CRY){
5469 operand *tmp = right ;
5473 if(AOP_TYPE(right) == AOP_LIT)
5474 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5476 size = AOP_SIZE(result);
5478 DEBUGpic14_AopType(__LINE__,left,right,result);
5481 // result = bit & yy;
5482 if (AOP_TYPE(left) == AOP_CRY){
5483 // c = bit & literal;
5484 if(AOP_TYPE(right) == AOP_LIT){
5486 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5489 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5492 if(size && (AOP_TYPE(result) == AOP_CRY)){
5493 pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5496 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5500 pic14_emitcode("clr","c");
5503 if (AOP_TYPE(right) == AOP_CRY){
5505 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5506 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5509 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5511 pic14_emitcode("rrc","a");
5512 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5518 pic14_outBitC(result);
5520 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5521 genIfxJump(ifx, "c");
5525 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5526 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5527 if((AOP_TYPE(right) == AOP_LIT) &&
5528 (AOP_TYPE(result) == AOP_CRY) &&
5529 (AOP_TYPE(left) != AOP_CRY)){
5530 int posbit = isLiteralBit(lit);
5534 //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5537 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5542 while (posbit > 7) {
5546 emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5547 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5548 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5555 symbol *tlbl = newiTempLabel(NULL);
5556 int sizel = AOP_SIZE(left);
5558 pic14_emitcode("setb","c");
5560 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5561 mov2w( AOP(left), offset);
5563 if((posbit = isLiteralBit(bytelit)) != 0) {
5564 emitpcode(rIfx.condition ? POC_BTFSC : POC_BTFSS, // XXX: or the other way round?
5565 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit - 1, 0));
5566 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5569 emitpcode(POC_ANDLW, newpCodeOpLit(bytelit & 0x0ff));
5570 if (rIfx.condition) emitSKPZ;
5573 if(bytelit != 0x0FFL)
5575 pic14_emitcode("anl","a,%s",
5576 aopGet(AOP(right),offset,FALSE,TRUE));
5578 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5581 emitpcode(POC_GOTO, popGetLabel(rIfx.lbl->key));
5587 // bit = left & literal
5589 pic14_emitcode("clr","c");
5590 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5592 // if(left & literal)
5595 jmpTrueOrFalse(ifx, tlbl);
5599 pic14_outBitC(result);
5603 /* if left is same as result */
5604 if(pic14_sameRegs(AOP(result),AOP(left))){
5606 for(;size--; offset++,lit>>=8) {
5607 if(AOP_TYPE(right) == AOP_LIT){
5608 switch(lit & 0xff) {
5610 /* and'ing with 0 has clears the result */
5611 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5614 /* and'ing with 0xff is a nop when the result and left are the same */
5619 int p = my_powof2( (~lit) & 0xff );
5621 /* only one bit is set in the literal, so use a bcf instruction */
5622 emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5625 if(know_W != (int)(lit&0xff))
5626 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5628 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5633 if (AOP_TYPE(left) == AOP_ACC) {
5634 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5636 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5637 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5644 // left & result in different registers
5645 if(AOP_TYPE(result) == AOP_CRY){
5647 // if(size), result in bit
5648 // if(!size && ifx), conditional oper: if(left & right)
5649 symbol *tlbl = newiTempLabel(NULL);
5650 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5652 pic14_emitcode("setb","c");
5654 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5655 pic14_emitcode("anl","a,%s",
5656 aopGet(AOP(left),offset,FALSE,FALSE));
5657 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5662 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5663 pic14_outBitC(result);
5665 jmpTrueOrFalse(ifx, tlbl);
5667 for(;(size--);offset++) {
5669 // result = left & right
5670 if(AOP_TYPE(right) == AOP_LIT){
5671 int t = (lit >> (offset*8)) & 0x0FFL;
5674 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5677 if(AOP_TYPE(left) != AOP_ACC) {
5678 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5680 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5683 if(AOP_TYPE(left) == AOP_ACC) {
5684 emitpcode(POC_ANDLW, popGetLit(t));
5686 emitpcode(POC_MOVLW, popGetLit(t));
5687 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5689 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5694 if (AOP_TYPE(left) == AOP_ACC) {
5695 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5697 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5698 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5700 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5706 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5707 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5708 freeAsmop(result,NULL,ic,TRUE);
5711 /*-----------------------------------------------------------------*/
5712 /* genOr - code for or */
5713 /*-----------------------------------------------------------------*/
5714 static void genOr (iCode *ic, iCode *ifx)
5716 operand *left, *right, *result;
5718 unsigned long lit = 0L;
5721 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5723 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5724 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5725 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5727 DEBUGpic14_AopType(__LINE__,left,right,result);
5729 /* if left is a literal & right is not then exchange them */
5730 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5731 AOP_NEEDSACC(left)) {
5732 operand *tmp = right ;
5737 /* if result = right then exchange them */
5738 if(pic14_sameRegs(AOP(result),AOP(right))){
5739 operand *tmp = right ;
5744 /* if right is bit then exchange them */
5745 if (AOP_TYPE(right) == AOP_CRY &&
5746 AOP_TYPE(left) != AOP_CRY){
5747 operand *tmp = right ;
5752 DEBUGpic14_AopType(__LINE__,left,right,result);
5754 if(AOP_TYPE(right) == AOP_LIT)
5755 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5757 size = AOP_SIZE(result);
5761 if (AOP_TYPE(left) == AOP_CRY){
5762 if(AOP_TYPE(right) == AOP_LIT){
5763 // c = bit & literal;
5765 // lit != 0 => result = 1
5766 if(AOP_TYPE(result) == AOP_CRY){
5768 emitpcode(POC_BSF, popGet(AOP(result),0));
5769 //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5770 // AOP(result)->aopu.aop_dir,
5771 // AOP(result)->aopu.aop_dir);
5773 continueIfTrue(ifx);
5777 // lit == 0 => result = left
5778 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5780 pic14_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5783 if (AOP_TYPE(right) == AOP_CRY){
5784 if(pic14_sameRegs(AOP(result),AOP(left))){
5786 emitpcode(POC_BCF, popGet(AOP(result),0));
5787 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5788 emitpcode(POC_BSF, popGet(AOP(result),0));
5790 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5791 AOP(result)->aopu.aop_dir,
5792 AOP(result)->aopu.aop_dir);
5793 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5794 AOP(right)->aopu.aop_dir,
5795 AOP(right)->aopu.aop_dir);
5796 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5797 AOP(result)->aopu.aop_dir,
5798 AOP(result)->aopu.aop_dir);
5800 if( AOP_TYPE(result) == AOP_ACC) {
5801 emitpcode(POC_MOVLW, popGetLit(0));
5802 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5803 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5804 emitpcode(POC_MOVLW, popGetLit(1));
5808 emitpcode(POC_BCF, popGet(AOP(result),0));
5809 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5810 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5811 emitpcode(POC_BSF, popGet(AOP(result),0));
5813 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5814 AOP(result)->aopu.aop_dir,
5815 AOP(result)->aopu.aop_dir);
5816 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5817 AOP(right)->aopu.aop_dir,
5818 AOP(right)->aopu.aop_dir);
5819 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5820 AOP(left)->aopu.aop_dir,
5821 AOP(left)->aopu.aop_dir);
5822 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5823 AOP(result)->aopu.aop_dir,
5824 AOP(result)->aopu.aop_dir);
5829 symbol *tlbl = newiTempLabel(NULL);
5830 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5833 emitpcode(POC_BCF, popGet(AOP(result),0));
5834 if( AOP_TYPE(right) == AOP_ACC) {
5835 emitpcode(POC_IORLW, popGetLit(0));
5837 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5838 emitpcode(POC_BSF, popGet(AOP(result),0));
5843 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5844 pic14_emitcode(";XXX setb","c");
5845 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5846 AOP(left)->aopu.aop_dir,tlbl->key+100);
5847 pic14_toBoolean(right);
5848 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5849 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5850 jmpTrueOrFalse(ifx, tlbl);
5854 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5861 pic14_outBitC(result);
5863 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5864 genIfxJump(ifx, "c");
5868 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5869 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5870 if((AOP_TYPE(right) == AOP_LIT) &&
5871 (AOP_TYPE(result) == AOP_CRY) &&
5872 (AOP_TYPE(left) != AOP_CRY)){
5874 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5877 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5879 continueIfTrue(ifx);
5882 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5883 // lit = 0, result = boolean(left)
5885 pic14_emitcode(";XXX setb","c");
5886 pic14_toBoolean(right);
5888 symbol *tlbl = newiTempLabel(NULL);
5889 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5891 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5893 genIfxJump (ifx,"a");
5897 pic14_outBitC(result);
5901 /* if left is same as result */
5902 if(pic14_sameRegs(AOP(result),AOP(left))){
5904 for(;size--; offset++,lit>>=8) {
5905 if(AOP_TYPE(right) == AOP_LIT){
5906 if((lit & 0xff) == 0)
5907 /* or'ing with 0 has no effect */
5910 int p = my_powof2(lit & 0xff);
5912 /* only one bit is set in the literal, so use a bsf instruction */
5914 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5916 if(know_W != (int)(lit & 0xff))
5917 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5918 know_W = lit & 0xff;
5919 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5924 if (AOP_TYPE(left) == AOP_ACC) {
5925 emitpcode(POC_IORFW, popGet(AOP(right),offset));
5926 pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5928 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
5929 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5931 pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5932 pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5938 // left & result in different registers
5939 if(AOP_TYPE(result) == AOP_CRY){
5941 // if(size), result in bit
5942 // if(!size && ifx), conditional oper: if(left | right)
5943 symbol *tlbl = newiTempLabel(NULL);
5944 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5945 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5949 pic14_emitcode(";XXX setb","c");
5951 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5952 pic14_emitcode(";XXX orl","a,%s",
5953 aopGet(AOP(left),offset,FALSE,FALSE));
5954 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5959 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5960 pic14_outBitC(result);
5962 jmpTrueOrFalse(ifx, tlbl);
5963 } else for(;(size--);offset++){
5965 // result = left | right
5966 if(AOP_TYPE(right) == AOP_LIT){
5967 int t = (lit >> (offset*8)) & 0x0FFL;
5970 if (AOP_TYPE(left) != AOP_ACC) {
5971 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
5973 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5977 if (AOP_TYPE(left) == AOP_ACC) {
5978 emitpcode(POC_IORLW, popGetLit(t));
5980 emitpcode(POC_MOVLW, popGetLit(t));
5981 emitpcode(POC_IORFW, popGet(AOP(left),offset));
5983 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5988 // faster than result <- left, anl result,right
5989 // and better if result is SFR
5990 if (AOP_TYPE(left) == AOP_ACC) {
5991 emitpcode(POC_IORFW,popGet(AOP(right),offset));
5993 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5994 emitpcode(POC_IORFW,popGet(AOP(left),offset));
5996 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6001 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6002 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6003 freeAsmop(result,NULL,ic,TRUE);
6006 /*-----------------------------------------------------------------*/
6007 /* genXor - code for xclusive or */
6008 /*-----------------------------------------------------------------*/
6009 static void genXor (iCode *ic, iCode *ifx)
6011 operand *left, *right, *result;
6013 unsigned long lit = 0L;
6016 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6018 aopOp((left = IC_LEFT(ic)),ic,FALSE);
6019 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6020 aopOp((result=IC_RESULT(ic)),ic,TRUE);
6022 /* if left is a literal & right is not ||
6023 if left needs acc & right does not */
6024 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6025 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6026 operand *tmp = right ;
6031 /* if result = right then exchange them */
6032 if(pic14_sameRegs(AOP(result),AOP(right))){
6033 operand *tmp = right ;
6038 /* if right is bit then exchange them */
6039 if (AOP_TYPE(right) == AOP_CRY &&
6040 AOP_TYPE(left) != AOP_CRY){
6041 operand *tmp = right ;
6045 if(AOP_TYPE(right) == AOP_LIT)
6046 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6048 size = AOP_SIZE(result);
6052 if (AOP_TYPE(left) == AOP_CRY){
6053 if(AOP_TYPE(right) == AOP_LIT){
6054 // c = bit & literal;
6056 // lit>>1 != 0 => result = 1
6057 if(AOP_TYPE(result) == AOP_CRY){
6059 {emitpcode(POC_BSF, popGet(AOP(result),offset));
6060 pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6062 continueIfTrue(ifx);
6065 pic14_emitcode("setb","c");
6069 // lit == 0, result = left
6070 if(size && pic14_sameRegs(AOP(result),AOP(left)))
6072 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6074 // lit == 1, result = not(left)
6075 if(size && pic14_sameRegs(AOP(result),AOP(left))){
6076 emitpcode(POC_MOVLW, popGet(AOP(result),offset));
6077 emitpcode(POC_XORWF, popGet(AOP(result),offset));
6078 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6081 assert ( !"incomplete genXor" );
6082 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6083 pic14_emitcode("cpl","c");
6090 symbol *tlbl = newiTempLabel(NULL);
6091 if (AOP_TYPE(right) == AOP_CRY){
6093 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6096 int sizer = AOP_SIZE(right);
6098 // if val>>1 != 0, result = 1
6099 pic14_emitcode("setb","c");
6101 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6103 // test the msb of the lsb
6104 pic14_emitcode("anl","a,#0xfe");
6105 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6109 pic14_emitcode("rrc","a");
6111 pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6112 pic14_emitcode("cpl","c");
6113 pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6118 pic14_outBitC(result);
6120 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6121 genIfxJump(ifx, "c");
6125 if(pic14_sameRegs(AOP(result),AOP(left))){
6126 /* if left is same as result */
6127 for(;size--; offset++) {
6128 if(AOP_TYPE(right) == AOP_LIT){
6129 int t = (lit >> (offset*8)) & 0x0FFL;
6133 if (IS_AOP_PREG(left)) {
6134 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6135 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6136 aopPut(AOP(result),"a",offset);
6138 emitpcode(POC_MOVLW, popGetLit(t));
6139 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6140 pic14_emitcode("xrl","%s,%s",
6141 aopGet(AOP(left),offset,FALSE,TRUE),
6142 aopGet(AOP(right),offset,FALSE,FALSE));
6145 if (AOP_TYPE(left) == AOP_ACC)
6146 pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6148 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6149 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6151 if (IS_AOP_PREG(left)) {
6152 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6153 aopPut(AOP(result),"a",offset);
6155 pic14_emitcode("xrl","%s,a",
6156 aopGet(AOP(left),offset,FALSE,TRUE));
6162 // left & result in different registers
6163 if(AOP_TYPE(result) == AOP_CRY){
6165 // if(size), result in bit
6166 // if(!size && ifx), conditional oper: if(left ^ right)
6167 symbol *tlbl = newiTempLabel(NULL);
6168 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6170 pic14_emitcode("setb","c");
6172 if((AOP_TYPE(right) == AOP_LIT) &&
6173 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6174 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6176 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6177 pic14_emitcode("xrl","a,%s",
6178 aopGet(AOP(left),offset,FALSE,FALSE));
6180 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6185 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6186 pic14_outBitC(result);
6188 jmpTrueOrFalse(ifx, tlbl);
6189 } else for(;(size--);offset++){
6191 // result = left & right
6192 if(AOP_TYPE(right) == AOP_LIT){
6193 int t = (lit >> (offset*8)) & 0x0FFL;
6196 if (AOP_TYPE(left) != AOP_ACC) {
6197 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6199 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6200 pic14_emitcode("movf","%s,w",
6201 aopGet(AOP(left),offset,FALSE,FALSE));
6202 pic14_emitcode("movwf","%s",
6203 aopGet(AOP(result),offset,FALSE,FALSE));
6206 if (AOP_TYPE(left) == AOP_ACC) {
6207 emitpcode(POC_XORLW, popGetLit(t));
6209 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6211 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6214 if (AOP_TYPE(left) == AOP_ACC) {
6215 emitpcode(POC_XORLW, popGetLit(t));
6217 emitpcode(POC_MOVLW, popGetLit(t));
6218 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6220 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6221 pic14_emitcode("movlw","0x%x",t);
6222 pic14_emitcode("xorwf","%s,w",
6223 aopGet(AOP(left),offset,FALSE,FALSE));
6224 pic14_emitcode("movwf","%s",
6225 aopGet(AOP(result),offset,FALSE,FALSE));
6231 // faster than result <- left, anl result,right
6232 // and better if result is SFR
6233 if (AOP_TYPE(left) == AOP_ACC) {
6234 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6236 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6237 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6239 if ( AOP_TYPE(result) != AOP_ACC){
6240 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6246 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6247 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6248 freeAsmop(result,NULL,ic,TRUE);
6251 /*-----------------------------------------------------------------*/
6252 /* genInline - write the inline code out */
6253 /*-----------------------------------------------------------------*/
6254 static void genInline (iCode *ic)
6256 char *buffer, *bp, *bp1;
6259 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6261 _G.inLine += (!options.asmpeep);
6263 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6264 strcpy(buffer,IC_INLINE(ic));
6266 /* emit each line as a code */
6272 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6280 /* print label, use this special format with NULL directive
6281 * to denote that the argument should not be indented with tab */
6282 addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6289 if ((bp1 != bp) && *bp1)
6290 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6294 _G.inLine -= (!options.asmpeep);
6297 /*-----------------------------------------------------------------*/
6298 /* genRRC - rotate right with carry */
6299 /*-----------------------------------------------------------------*/
6300 static void genRRC (iCode *ic)
6302 operand *left , *result ;
6303 int size, offset = 0, same;
6306 /* rotate right with carry */
6308 result=IC_RESULT(ic);
6309 aopOp (left,ic,FALSE);
6310 aopOp (result,ic,FALSE);
6312 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6314 same = pic14_sameRegs(AOP(result),AOP(left));
6316 size = AOP_SIZE(result);
6318 /* get the lsb and put it into the carry */
6319 emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6326 emitpcode(POC_RRF, popGet(AOP(left),offset));
6328 emitpcode(POC_RRFW, popGet(AOP(left),offset));
6329 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6335 freeAsmop(left,NULL,ic,TRUE);
6336 freeAsmop(result,NULL,ic,TRUE);
6339 /*-----------------------------------------------------------------*/
6340 /* genRLC - generate code for rotate left with carry */
6341 /*-----------------------------------------------------------------*/
6342 static void genRLC (iCode *ic)
6344 operand *left , *result ;
6345 int size, offset = 0;
6349 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6350 /* rotate right with carry */
6352 result=IC_RESULT(ic);
6353 aopOp (left,ic,FALSE);
6354 aopOp (result,ic,FALSE);
6356 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6358 same = pic14_sameRegs(AOP(result),AOP(left));
6360 /* move it to the result */
6361 size = AOP_SIZE(result);
6363 /* get the msb and put it into the carry */
6364 emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6371 emitpcode(POC_RLF, popGet(AOP(left),offset));
6373 emitpcode(POC_RLFW, popGet(AOP(left),offset));
6374 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6381 freeAsmop(left,NULL,ic,TRUE);
6382 freeAsmop(result,NULL,ic,TRUE);
6385 /*-----------------------------------------------------------------*/
6386 /* genGetHbit - generates code get highest order bit */
6387 /*-----------------------------------------------------------------*/
6388 static void genGetHbit (iCode *ic)
6390 operand *left, *result;
6392 result=IC_RESULT(ic);
6393 aopOp (left,ic,FALSE);
6394 aopOp (result,ic,FALSE);
6397 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6398 /* get the highest order byte into a */
6399 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6400 if(AOP_TYPE(result) == AOP_CRY){
6401 pic14_emitcode("rlc","a");
6402 pic14_outBitC(result);
6405 pic14_emitcode("rl","a");
6406 pic14_emitcode("anl","a,#0x01");
6407 pic14_outAcc(result);
6411 freeAsmop(left,NULL,ic,TRUE);
6412 freeAsmop(result,NULL,ic,TRUE);
6415 /*-----------------------------------------------------------------*/
6416 /* AccLsh - shift left accumulator by known count */
6417 /* MARK: pic14 always rotates through CARRY! */
6418 /*-----------------------------------------------------------------*/
6419 static void AccLsh (pCodeOp *pcop,int shCount)
6422 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6423 shCount &= 0x0007; // shCount : 0..7
6430 emitpcode(POC_RLF,pcop);
6434 emitpcode(POC_RLF,pcop);
6435 emitpcode(POC_RLF,pcop);
6438 emitpcode(POC_RLF,pcop);
6439 emitpcode(POC_RLF,pcop);
6440 emitpcode(POC_RLF,pcop);
6443 emitpcode(POC_SWAPF,pcop);
6446 emitpcode(POC_SWAPF,pcop);
6447 emitpcode(POC_RLF,pcop);
6450 emitpcode(POC_SWAPF,pcop);
6451 emitpcode(POC_RLF,pcop);
6452 emitpcode(POC_RLF,pcop);
6455 emitpcode(POC_RRFW,pcop);
6456 emitpcode(POC_RRF,pcop);
6459 /* clear invalid bits */
6460 emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6461 emitpcode(POC_ANDWF, pcop);
6464 /*-----------------------------------------------------------------*/
6465 /* AccRsh - shift right accumulator by known count */
6466 /* MARK: pic14 always rotates through CARRY! */
6467 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6468 /* 1: mask out invalid bits (zero-extend) */
6469 /* 2: sign-extend result (pretty slow) */
6470 /*-----------------------------------------------------------------*/
6471 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6474 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6475 shCount &= 0x0007; // shCount : 0..7
6481 /* load sign if needed */
6482 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6483 else if (mask_mode == 1) emitCLRC;
6484 emitpcode(POC_RRF,pcop);
6488 /* load sign if needed */
6489 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6490 emitpcode(POC_RRF,pcop);
6491 /* load sign if needed */
6492 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6493 emitpcode(POC_RRF,pcop);
6494 if (mask_mode == 2) return;
6497 /* load sign if needed */
6498 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6499 emitpcode(POC_RRF,pcop);
6500 /* load sign if needed */
6501 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6502 emitpcode(POC_RRF,pcop);
6503 /* load sign if needed */
6504 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6505 emitpcode(POC_RRF,pcop);
6506 if (mask_mode == 2) return;
6509 emitpcode(POC_SWAPF,pcop);
6512 emitpcode(POC_SWAPF,pcop);
6513 emitpcode(POC_RRF,pcop);
6516 emitpcode(POC_SWAPF,pcop);
6517 emitpcode(POC_RRF,pcop);
6518 emitpcode(POC_RRF,pcop);
6524 emitpcode(POC_RLFW,pcop);
6525 emitpcode(POC_CLRF,pcop);
6527 emitpcode(POC_COMF,pcop);
6530 emitpcode(POC_RLFW,pcop);
6531 emitpcode(POC_RLF,pcop);
6538 /* leave invalid bits undefined */
6542 /* clear invalid bits -- zero-extend */
6543 emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6544 emitpcode(POC_ANDWF, pcop);
6546 if (mask_mode == 2) {
6548 emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6549 emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6550 emitpcode(POC_IORWF, pcop);
6555 /*-----------------------------------------------------------------*/
6556 /* AccSRsh - signed right shift accumulator by known count */
6557 /*-----------------------------------------------------------------*/
6558 static void AccSRsh (int shCount)
6561 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6564 pic14_emitcode("mov","c,acc.7");
6565 pic14_emitcode("rrc","a");
6566 } else if(shCount == 2){
6567 pic14_emitcode("mov","c,acc.7");
6568 pic14_emitcode("rrc","a");
6569 pic14_emitcode("mov","c,acc.7");
6570 pic14_emitcode("rrc","a");
6572 tlbl = newiTempLabel(NULL);
6573 /* rotate right accumulator */
6574 AccRol(8 - shCount);
6575 /* and kill the higher order bits */
6576 pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6577 pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6578 pic14_emitcode("orl","a,#0x%02x",
6579 (unsigned char)~SRMask[shCount]);
6580 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6585 /*-----------------------------------------------------------------*/
6586 /* shiftR1Left2Result - shift right one byte from left to result */
6587 /*-----------------------------------------------------------------*/
6588 static void shiftR1Left2ResultSigned (operand *left, int offl,
6589 operand *result, int offr,
6595 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6597 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6601 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6603 emitpcode(POC_RRF, popGet(AOP(result),offr));
6605 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6606 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6612 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6614 emitpcode(POC_RRF, popGet(AOP(result),offr));
6616 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6617 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6619 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6620 emitpcode(POC_RRF, popGet(AOP(result),offr));
6626 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6628 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6629 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6632 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6633 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6634 emitpcode(POC_ANDLW, popGetLit(0x1f));
6636 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6637 emitpcode(POC_IORLW, popGetLit(0xe0));
6639 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6643 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6644 emitpcode(POC_ANDLW, popGetLit(0x0f));
6645 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6646 emitpcode(POC_IORLW, popGetLit(0xf0));
6647 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6651 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6653 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6654 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6656 emitpcode(POC_RRFW, popGet(AOP(result),offr));
6657 emitpcode(POC_ANDLW, popGetLit(0x07));
6658 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6659 emitpcode(POC_IORLW, popGetLit(0xf8));
6660 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6665 emitpcode(POC_MOVLW, popGetLit(0x00));
6666 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6667 emitpcode(POC_MOVLW, popGetLit(0xfe));
6668 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6669 emitpcode(POC_IORLW, popGetLit(0x01));
6670 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6672 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6673 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6674 emitpcode(POC_DECF, popGet(AOP(result),offr));
6675 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6676 emitpcode(POC_BCF, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6682 emitpcode(POC_MOVLW, popGetLit(0x00));
6683 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6684 emitpcode(POC_MOVLW, popGetLit(0xff));
6685 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6687 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6688 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6689 emitpcode(POC_DECF, popGet(AOP(result),offr));
6697 /*-----------------------------------------------------------------*/
6698 /* shiftR1Left2Result - shift right one byte from left to result */
6699 /*-----------------------------------------------------------------*/
6700 static void shiftR1Left2Result (operand *left, int offl,
6701 operand *result, int offr,
6702 int shCount, int sign)
6707 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6709 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6711 /* Copy the msb into the carry if signed. */
6713 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6723 emitpcode(POC_RRF, popGet(AOP(result),offr));
6725 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6726 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6732 emitpcode(POC_RRF, popGet(AOP(result),offr));
6734 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6735 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6738 emitpcode(POC_RRF, popGet(AOP(result),offr));
6743 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6745 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6746 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6749 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6750 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6751 emitpcode(POC_ANDLW, popGetLit(0x1f));
6752 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6756 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6757 emitpcode(POC_ANDLW, popGetLit(0x0f));
6758 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6762 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6763 emitpcode(POC_ANDLW, popGetLit(0x0f));
6764 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6766 emitpcode(POC_RRF, popGet(AOP(result),offr));
6771 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6772 emitpcode(POC_ANDLW, popGetLit(0x80));
6773 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6774 emitpcode(POC_RLF, popGet(AOP(result),offr));
6775 emitpcode(POC_RLF, popGet(AOP(result),offr));
6780 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6781 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6782 emitpcode(POC_RLF, popGet(AOP(result),offr));
6791 /*-----------------------------------------------------------------*/
6792 /* shiftL1Left2Result - shift left one byte from left to result */
6793 /*-----------------------------------------------------------------*/
6794 static void shiftL1Left2Result (operand *left, int offl,
6795 operand *result, int offr, int shCount)
6801 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6803 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6804 DEBUGpic14_emitcode ("; ***","same = %d",same);
6805 // l = aopGet(AOP(left),offl,FALSE,FALSE);
6807 /* shift left accumulator */
6808 //AccLsh(shCount); // don't comment out just yet...
6809 // aopPut(AOP(result),"a",offr);
6813 /* Shift left 1 bit position */
6814 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6816 emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6818 emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6819 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6823 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6824 emitpcode(POC_ANDLW,popGetLit(0x7e));
6825 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6826 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6829 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6830 emitpcode(POC_ANDLW,popGetLit(0x3e));
6831 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6832 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6833 emitpcode(POC_RLF, popGet(AOP(result),offr));
6836 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6837 emitpcode(POC_ANDLW, popGetLit(0xf0));
6838 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6841 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6842 emitpcode(POC_ANDLW, popGetLit(0xf0));
6843 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6844 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6847 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6848 emitpcode(POC_ANDLW, popGetLit(0x30));
6849 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6850 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6851 emitpcode(POC_RLF, popGet(AOP(result),offr));
6854 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6855 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6856 emitpcode(POC_RRF, popGet(AOP(result),offr));
6860 DEBUGpic14_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6866 /*-----------------------------------------------------------------*/
6867 /* movLeft2Result - move byte from left to result */
6868 /*-----------------------------------------------------------------*/
6869 static void movLeft2Result (operand *left, int offl,
6870 operand *result, int offr)
6874 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6875 if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6876 l = aopGet(AOP(left),offl,FALSE,FALSE);
6878 if (*l == '@' && (IS_AOP_PREG(result))) {
6879 pic14_emitcode("mov","a,%s",l);
6880 aopPut(AOP(result),"a",offr);
6882 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6883 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6888 /*-----------------------------------------------------------------*/
6889 /* shiftLeft_Left2ResultLit - shift left by known count */
6890 /*-----------------------------------------------------------------*/
6892 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6894 int size, same, offr, i;
6896 size = AOP_SIZE(left);
6897 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6899 same = pic14_sameRegs (AOP(left), AOP(result));
6902 shCount = shCount & 0x07;
6908 case 0: /* takes 0 or 2N cycles (for offr==0) */
6909 if (!same || offr) {
6910 for (i=size-1; i >= 0; i--)
6911 movLeft2Result (left, i, result, offr + i);
6915 case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6917 shiftLeft_Left2ResultLit (left, result, 8 * offr);
6918 shiftLeft_Left2ResultLit (result, result, shCount);
6919 return; /* prevent clearing result again */
6922 for (i=0; i < size; i++) {
6923 if (same && !offr) {
6924 emitpcode (POC_RLF, popGet (AOP(left), i));
6926 emitpcode (POC_RLFW, popGet (AOP(left), i));
6927 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6933 case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
6934 /* works in-place/with offr as well */
6935 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
6936 emitpcode (POC_ANDLW, popGetLit (0xF0));
6937 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
6939 for (i = size - 2; i >= 0; i--)
6941 emitpcode (POC_SWAPFW, popGet (AOP(left), i));
6942 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6943 emitpcode (POC_ANDLW, popGetLit (0x0F));
6944 emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
6945 emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
6949 case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
6950 /* works in-place/with offr as well */
6951 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
6952 for (i = size-2; i >= 0; i--) {
6953 emitpcode (POC_RRFW, popGet (AOP(left), i));
6954 emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
6956 emitpcode (POC_CLRF, popGet (AOP(result), offr));
6957 emitpcode (POC_RRF, popGet (AOP(result), offr));
6961 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
6962 shiftLeft_Left2ResultLit (result, result, 1);
6963 return; /* prevent clearing result again */
6969 emitpcode (POC_CLRF, popGet (AOP(result), offr));
6973 /*-----------------------------------------------------------------*/
6974 /* shiftRight_Left2ResultLit - shift right by known count */
6975 /*-----------------------------------------------------------------*/
6977 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
6979 int size, same, offr, i;
6981 size = AOP_SIZE(left);
6982 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6984 same = pic14_sameRegs (AOP(left), AOP(result));
6987 shCount = shCount & 0x07;
6995 case 0: /* takes 0 or 2N cycles (for offr==0) */
6996 if (!same || offr) {
6997 for (i=0; i < size; i++)
6998 movLeft2Result (left, i + offr, result, i);
7002 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7003 emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7005 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7006 shiftRight_Left2ResultLit (result, result, shCount, sign);
7007 return; /* prevent sign-extending result again */
7011 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7014 for (i = size-1; i >= 0; i--) {
7015 if (same && !offr) {
7016 emitpcode (POC_RRF, popGet (AOP(left), i));
7018 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7019 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7025 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7026 /* works in-place/with offr as well */
7027 emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7028 emitpcode (POC_ANDLW, popGetLit (0x0F));
7029 emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7031 for (i = 1; i < size; i++)
7033 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7034 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7035 emitpcode (POC_ANDLW, popGetLit (0xF0));
7036 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7037 emitpcode (POC_XORWF, popGet (AOP(result), i));
7042 emitpcode (POC_MOVLW, popGetLit (0xF0));
7043 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7044 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7048 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7049 /* works in-place/with offr as well */
7050 emitpcode (POC_RLFW, popGet (AOP(left), offr));
7051 for (i = 0; i < size-1; i++) {
7052 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7053 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7055 emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7057 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7060 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7065 shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7066 shiftRight_Left2ResultLit (result, result, 1, sign);
7067 return; /* prevent sign extending result again */
7072 addSign (result, size, sign);
7076 /*-----------------------------------------------------------------*/
7077 /* shiftL2Left2Result - shift left two bytes from left to result */
7078 /*-----------------------------------------------------------------*/
7079 static void shiftL2Left2Result (operand *left, int offl,
7080 operand *result, int offr, int shCount)
7084 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7086 if(pic14_sameRegs(AOP(result), AOP(left))) {
7094 emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7095 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7096 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7100 emitpcode(POC_RLF, popGet(AOP(result),offr));
7101 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7107 emitpcode(POC_MOVLW, popGetLit(0x0f));
7108 emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7109 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7110 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7111 emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7112 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7113 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7115 emitpcode(POC_RLF, popGet(AOP(result),offr));
7116 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7120 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7121 emitpcode(POC_RRF, popGet(AOP(result),offr));
7122 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7123 emitpcode(POC_RRF, popGet(AOP(result),offr));
7124 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7125 emitpcode(POC_ANDLW,popGetLit(0xc0));
7126 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7127 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7128 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7129 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7132 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7133 emitpcode(POC_RRFW, popGet(AOP(result),offr));
7134 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7135 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7136 emitpcode(POC_RRF, popGet(AOP(result),offr));
7146 /* note, use a mov/add for the shift since the mov has a
7147 chance of getting optimized out */
7148 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7149 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7150 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7151 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7152 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7156 emitpcode(POC_RLF, popGet(AOP(result),offr));
7157 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7163 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7164 emitpcode(POC_ANDLW, popGetLit(0xF0));
7165 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7166 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7167 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7168 emitpcode(POC_ANDLW, popGetLit(0xF0));
7169 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7170 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7174 emitpcode(POC_RLF, popGet(AOP(result),offr));
7175 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7179 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7180 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7181 emitpcode(POC_RRFW, popGet(AOP(result),offl));
7182 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7184 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7185 emitpcode(POC_RRF, popGet(AOP(result),offr));
7186 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7187 emitpcode(POC_ANDLW,popGetLit(0xc0));
7188 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7189 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7190 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7191 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7194 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7195 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7196 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7197 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7198 emitpcode(POC_RRF, popGet(AOP(result),offr));
7204 /*-----------------------------------------------------------------*/
7205 /* shiftR2Left2Result - shift right two bytes from left to result */
7206 /*-----------------------------------------------------------------*/
7207 static void shiftR2Left2Result (operand *left, int offl,
7208 operand *result, int offr,
7209 int shCount, int sign)
7214 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7215 same = pic14_sameRegs(AOP(result), AOP(left));
7217 if(same && ((offl + MSB16) == offr)){
7219 /* don't crash result[offr] */
7220 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7221 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7224 movLeft2Result(left,offl, result, offr);
7225 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7228 /* a:x >> shCount (x = lsb(result))*/
7231 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7233 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7242 emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7247 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7248 emitpcode(POC_RRF,popGet(AOP(result),offr));
7250 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7251 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7252 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7253 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7258 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7261 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7262 emitpcode(POC_RRF,popGet(AOP(result),offr));
7269 emitpcode(POC_MOVLW, popGetLit(0xf0));
7270 emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7271 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7273 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7274 emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7275 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7276 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7278 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7279 emitpcode(POC_ANDLW, popGetLit(0x0f));
7280 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7282 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7283 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7284 emitpcode(POC_ANDLW, popGetLit(0xf0));
7285 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7286 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7290 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7291 emitpcode(POC_RRF, popGet(AOP(result),offr));
7295 emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7296 emitpcode(POC_BTFSC,
7297 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7298 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7306 emitpcode(POC_RLF, popGet(AOP(result),offr));
7307 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7309 emitpcode(POC_RLF, popGet(AOP(result),offr));
7310 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7311 emitpcode(POC_RLFW, popGet(AOP(result),offr));
7312 emitpcode(POC_ANDLW,popGetLit(0x03));
7314 emitpcode(POC_BTFSC,
7315 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7316 emitpcode(POC_IORLW,popGetLit(0xfc));
7318 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7319 emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7320 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7321 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7323 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7324 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7325 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7326 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7327 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7328 emitpcode(POC_RLF, popGet(AOP(result),offr));
7329 emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7330 emitpcode(POC_ANDLW,popGetLit(0x03));
7332 emitpcode(POC_BTFSC,
7333 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7334 emitpcode(POC_IORLW,popGetLit(0xfc));
7336 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7337 //emitpcode(POC_RLF, popGet(AOP(result),offr));
7344 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7345 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7346 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7347 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7350 emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7352 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7356 /*-----------------------------------------------------------------*/
7357 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7358 /*-----------------------------------------------------------------*/
7359 static void shiftLLeftOrResult (operand *left, int offl,
7360 operand *result, int offr, int shCount)
7363 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7365 /* shift left accumulator */
7366 AccLsh(left,offl,shCount);
7367 /* or with result */
7368 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7369 assert ( !"broken (modifies left, fails for left==result))" );
7372 /*-----------------------------------------------------------------*/
7373 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7374 /*-----------------------------------------------------------------*/
7375 static void shiftRLeftOrResult (operand *left, int offl,
7376 operand *result, int offr, int shCount)
7379 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7381 /* shift right accumulator */
7382 AccRsh(left,offl,shCount);
7383 /* or with result */
7384 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7385 assert ( !"broken (modifies left, fails for left==result))" );
7388 /*-----------------------------------------------------------------*/
7389 /* genlshOne - left shift a one byte quantity by known count */
7390 /*-----------------------------------------------------------------*/
7391 static void genlshOne (operand *result, operand *left, int shCount)
7394 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7395 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7398 /*-----------------------------------------------------------------*/
7399 /* genlshTwo - left shift two bytes by known amount != 0 */
7400 /*-----------------------------------------------------------------*/
7401 static void genlshTwo (operand *result,operand *left, int shCount)
7406 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7407 size = pic14_getDataSize(result);
7409 /* if shCount >= 8 */
7415 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7417 movLeft2Result(left, LSB, result, MSB16);
7419 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7422 /* 1 <= shCount <= 7 */
7425 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7427 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7431 /*-----------------------------------------------------------------*/
7432 /* shiftLLong - shift left one long from left to result */
7433 /* offl = LSB or MSB16 */
7434 /*-----------------------------------------------------------------*/
7435 static void shiftLLong (operand *left, operand *result, int offr )
7438 int size = AOP_SIZE(result);
7441 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7442 if(size >= LSB+offr){
7443 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7445 pic14_emitcode("add","a,acc");
7446 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7447 size >= MSB16+offr && offr != LSB )
7448 pic14_emitcode("xch","a,%s",
7449 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7451 aopPut(AOP(result),"a",LSB+offr);
7454 if(size >= MSB16+offr){
7455 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7456 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7459 pic14_emitcode("rlc","a");
7460 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7461 size >= MSB24+offr && offr != LSB)
7462 pic14_emitcode("xch","a,%s",
7463 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7465 aopPut(AOP(result),"a",MSB16+offr);
7468 if(size >= MSB24+offr){
7469 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7470 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7473 pic14_emitcode("rlc","a");
7474 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7475 size >= MSB32+offr && offr != LSB )
7476 pic14_emitcode("xch","a,%s",
7477 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7479 aopPut(AOP(result),"a",MSB24+offr);
7482 if(size > MSB32+offr){
7483 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7484 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7487 pic14_emitcode("rlc","a");
7488 aopPut(AOP(result),"a",MSB32+offr);
7491 aopPut(AOP(result),zero,LSB);
7494 /*-----------------------------------------------------------------*/
7495 /* genlshFour - shift four byte by a known amount != 0 */
7496 /*-----------------------------------------------------------------*/
7497 static void genlshFour (operand *result, operand *left, int shCount)
7502 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7503 size = AOP_SIZE(result);
7505 /* if shifting more that 3 bytes */
7506 if (shCount >= 24 ) {
7509 /* lowest order of left goes to the highest
7510 order of the destination */
7511 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7513 movLeft2Result(left, LSB, result, MSB32);
7514 aopPut(AOP(result),zero,LSB);
7515 aopPut(AOP(result),zero,MSB16);
7516 aopPut(AOP(result),zero,MSB32);
7520 /* more than two bytes */
7521 else if ( shCount >= 16 ) {
7522 /* lower order two bytes goes to higher order two bytes */
7524 /* if some more remaining */
7526 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7528 movLeft2Result(left, MSB16, result, MSB32);
7529 movLeft2Result(left, LSB, result, MSB24);
7531 aopPut(AOP(result),zero,MSB16);
7532 aopPut(AOP(result),zero,LSB);
7536 /* if more than 1 byte */
7537 else if ( shCount >= 8 ) {
7538 /* lower order three bytes goes to higher order three bytes */
7542 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7544 movLeft2Result(left, LSB, result, MSB16);
7546 else{ /* size = 4 */
7548 movLeft2Result(left, MSB24, result, MSB32);
7549 movLeft2Result(left, MSB16, result, MSB24);
7550 movLeft2Result(left, LSB, result, MSB16);
7551 aopPut(AOP(result),zero,LSB);
7553 else if(shCount == 1)
7554 shiftLLong(left, result, MSB16);
7556 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7557 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7558 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7559 aopPut(AOP(result),zero,LSB);
7564 /* 1 <= shCount <= 7 */
7565 else if(shCount <= 2){
7566 shiftLLong(left, result, LSB);
7568 shiftLLong(result, result, LSB);
7570 /* 3 <= shCount <= 7, optimize */
7572 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7573 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7574 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7580 /*-----------------------------------------------------------------*/
7581 /* genLeftShiftLiteral - left shifting by known count */
7582 /*-----------------------------------------------------------------*/
7583 static void genLeftShiftLiteral (operand *left,
7588 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7592 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7593 freeAsmop(right,NULL,ic,TRUE);
7595 aopOp(left,ic,FALSE);
7596 aopOp(result,ic,FALSE);
7598 size = getSize(operandType(result));
7601 pic14_emitcode("; shift left ","result %d, left %d",size,
7605 /* I suppose that the left size >= result size */
7608 movLeft2Result(left, size, result, size);
7612 else if(shCount >= (size * 8))
7614 aopPut(AOP(result),zero,size);
7618 genlshOne (result,left,shCount);
7623 genlshTwo (result,left,shCount);
7627 genlshFour (result,left,shCount);
7631 freeAsmop(left,NULL,ic,TRUE);
7632 freeAsmop(result,NULL,ic,TRUE);
7636 /*-----------------------------------------------------------------*
7637 * genMultiAsm - repeat assembly instruction for size of register.
7638 * if endian == 1, then the high byte (i.e base address + size of
7639 * register) is used first else the low byte is used first;
7640 *-----------------------------------------------------------------*/
7641 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7647 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7660 emitpcode(poc, popGet(AOP(reg),offset));
7667 /*-----------------------------------------------------------------*/
7668 /* genLeftShift - generates code for left shifting */
7669 /*-----------------------------------------------------------------*/
7670 static void genLeftShift (iCode *ic)
7672 operand *left,*right, *result;
7674 unsigned long lit = 0L;
7676 symbol *tlbl , *tlbl1;
7680 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7682 right = IC_RIGHT(ic);
7684 result = IC_RESULT(ic);
7686 aopOp(right,ic,FALSE);
7687 aopOp(left,ic,FALSE);
7688 aopOp(result,ic,FALSE);
7691 /* if the shift count is known then do it
7692 as efficiently as possible */
7693 if (AOP_TYPE(right) == AOP_LIT) {
7694 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7698 /* shift count is unknown then we have to form
7699 a loop get the loop count in B : Note: we take
7700 only the lower order byte since shifting
7701 more that 32 bits make no sense anyway, ( the
7702 largest size of an object can be only 32 bits ) */
7704 /* this code fails for RIGHT == RESULT */
7705 assert (!pic14_sameRegs (AOP(right), AOP(result)));
7707 /* now move the left to the result if they are not the
7709 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
7710 AOP_SIZE(result) > 1) {
7712 size = AOP_SIZE(result);
7715 l = aopGet(AOP(left),offset,FALSE,TRUE);
7716 if (*l == '@' && (IS_AOP_PREG(result))) {
7718 pic14_emitcode("mov","a,%s",l);
7719 aopPut(AOP(result),"a",offset);
7721 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
7722 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7723 //aopPut(AOP(result),l,offset);
7729 if(AOP_TYPE(left) == AOP_LIT)
7730 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7732 size = AOP_SIZE(result);
7734 /* if it is only one byte then */
7736 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7737 emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7738 emitpcode(POC_ANDLW, popGetLit(0xf0));
7739 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7740 emitpcode(POC_MOVFW, popGet(AOP(left),0));
7741 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7742 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7743 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7744 emitpcode(POC_RLFW, popGet(AOP(result),0));
7745 emitpcode(POC_ANDLW, popGetLit(0xfe));
7746 emitpcode(POC_ADDFW, popGet(AOP(result),0));
7747 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7748 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7751 tlbl = newiTempLabel(NULL);
7752 if (!pic14_sameRegs(AOP(left),AOP(result))) {
7753 mov2w (AOP(left), 0);
7754 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7757 emitpcode(POC_COMFW, popGet(AOP(right),0));
7758 emitpcode(POC_RRF, popGet(AOP(result),0));
7759 emitpLabel(tlbl->key);
7760 emitpcode(POC_RLF, popGet(AOP(result),0));
7761 emitpcode(POC_ADDLW, popGetLit(1));
7763 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7768 if (pic14_sameRegs(AOP(left),AOP(result))) {
7770 tlbl = newiTempLabel(NULL);
7771 emitpcode(POC_COMFW, popGet(AOP(right),0));
7772 genMultiAsm(POC_RRF, result, size,1);
7773 emitpLabel(tlbl->key);
7774 genMultiAsm(POC_RLF, result, size,0);
7775 emitpcode(POC_ADDLW, popGetLit(1));
7777 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7781 //tlbl = newiTempLabel(NULL);
7783 //tlbl1 = newiTempLabel(NULL);
7785 //reAdjustPreg(AOP(result));
7787 //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7788 //pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7789 //l = aopGet(AOP(result),offset,FALSE,FALSE);
7791 //pic14_emitcode("add","a,acc");
7792 //aopPut(AOP(result),"a",offset++);
7794 // l = aopGet(AOP(result),offset,FALSE,FALSE);
7796 // pic14_emitcode("rlc","a");
7797 // aopPut(AOP(result),"a",offset++);
7799 //reAdjustPreg(AOP(result));
7801 //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7802 //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7805 tlbl = newiTempLabel(NULL);
7806 tlbl1= newiTempLabel(NULL);
7808 size = AOP_SIZE(result);
7811 pctemp = popGetTempReg(); /* grab a temporary working register. */
7813 emitpcode(POC_MOVFW, popGet(AOP(right),0));
7815 /* offset should be 0, 1 or 3 */
7816 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7818 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
7820 emitpcode(POC_MOVWF, pctemp);
7823 emitpLabel(tlbl->key);
7826 emitpcode(POC_RLF, popGet(AOP(result),0));
7828 emitpcode(POC_RLF, popGet(AOP(result),offset++));
7830 emitpcode(POC_DECFSZ, pctemp);
7831 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7832 emitpLabel(tlbl1->key);
7834 popReleaseTempReg(pctemp);
7838 freeAsmop (right,NULL,ic,TRUE);
7839 freeAsmop(left,NULL,ic,TRUE);
7840 freeAsmop(result,NULL,ic,TRUE);
7845 /*-----------------------------------------------------------------*/
7846 /* genrshOne - right shift a one byte quantity by known count */
7847 /*-----------------------------------------------------------------*/
7848 static void genrshOne (operand *result, operand *left,
7849 int shCount, int sign)
7852 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7853 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7856 /*-----------------------------------------------------------------*/
7857 /* genrshTwo - right shift two bytes by known amount != 0 */
7858 /*-----------------------------------------------------------------*/
7859 static void genrshTwo (operand *result,operand *left,
7860 int shCount, int sign)
7863 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7864 /* if shCount >= 8 */
7868 shiftR1Left2Result(left, MSB16, result, LSB,
7871 movLeft2Result(left, MSB16, result, LSB);
7873 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7876 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7877 emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7881 /* 1 <= shCount <= 7 */
7883 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
7886 /*-----------------------------------------------------------------*/
7887 /* shiftRLong - shift right one long from left to result */
7888 /* offl = LSB or MSB16 */
7889 /*-----------------------------------------------------------------*/
7890 static void shiftRLong (operand *left, int offl,
7891 operand *result, int sign)
7896 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7898 size = AOP_SIZE(left);
7899 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7902 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7906 assert (offl >= 0 && offl < size);
7908 same = pic14_sameRegs (AOP(left), AOP(result));
7910 /* perform the shift */
7913 if (same && !offl) {
7914 emitpcode (POC_RRF, popGet (AOP(result), size));
7916 emitpcode (POC_RRFW, popGet (AOP(left), size));
7917 emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7921 addSign (result, AOP_SIZE(left) - offl, sign);
7924 /*-----------------------------------------------------------------*/
7925 /* genrshFour - shift four byte by a known amount != 0 */
7926 /*-----------------------------------------------------------------*/
7927 static void genrshFour (operand *result, operand *left,
7928 int shCount, int sign)
7931 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7932 /* if shifting more that 3 bytes */
7933 if(shCount >= 24 ) {
7936 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7938 movLeft2Result(left, MSB32, result, LSB);
7940 addSign(result, MSB16, sign);
7942 else if(shCount >= 16){
7945 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7947 movLeft2Result(left, MSB24, result, LSB);
7948 movLeft2Result(left, MSB32, result, MSB16);
7950 addSign(result, MSB24, sign);
7952 else if(shCount >= 8){
7955 shiftRLong(left, MSB16, result, sign);
7956 else if(shCount == 0){
7957 movLeft2Result(left, MSB16, result, LSB);
7958 movLeft2Result(left, MSB24, result, MSB16);
7959 movLeft2Result(left, MSB32, result, MSB24);
7960 addSign(result, MSB32, sign);
7963 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7964 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7965 /* the last shift is signed */
7966 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7967 addSign(result, MSB32, sign);
7970 else{ /* 1 <= shCount <= 7 */
7972 shiftRLong(left, LSB, result, sign);
7974 shiftRLong(result, LSB, result, sign);
7977 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7978 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7979 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7984 /*-----------------------------------------------------------------*/
7985 /* genRightShiftLiteral - right shifting by known count */
7986 /*-----------------------------------------------------------------*/
7987 static void genRightShiftLiteral (operand *left,
7993 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7997 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7998 freeAsmop(right,NULL,ic,TRUE);
8000 aopOp(left,ic,FALSE);
8001 aopOp(result,ic,FALSE);
8004 pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8008 lsize = pic14_getDataSize(left);
8009 res_size = pic14_getDataSize(result);
8010 /* test the LEFT size !!! */
8012 /* I suppose that the left size >= result size */
8015 movLeft2Result(left, res_size, result, res_size);
8018 else if(shCount >= (lsize * 8)){
8021 emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8023 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8024 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8029 emitpcode(POC_MOVLW, popGetLit(0));
8030 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8031 emitpcode(POC_MOVLW, popGetLit(0xff));
8033 emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8038 emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8045 genrshOne (result,left,shCount,sign);
8049 genrshTwo (result,left,shCount,sign);
8053 genrshFour (result,left,shCount,sign);
8061 freeAsmop(left,NULL,ic,TRUE);
8062 freeAsmop(result,NULL,ic,TRUE);
8067 /*-----------------------------------------------------------------*/
8068 /* genSignedRightShift - right shift of signed number */
8069 /*-----------------------------------------------------------------*/
8070 static void genSignedRightShift (iCode *ic)
8072 operand *right, *left, *result;
8075 symbol *tlbl, *tlbl1 ;
8078 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8080 /* we do it the hard way put the shift count in b
8081 and loop thru preserving the sign */
8083 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8085 right = IC_RIGHT(ic);
8087 result = IC_RESULT(ic);
8089 aopOp(right,ic,FALSE);
8090 aopOp(left,ic,FALSE);
8091 aopOp(result,ic,FALSE);
8094 if ( AOP_TYPE(right) == AOP_LIT) {
8095 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8096 //genRightShiftLiteral (left,right,result,ic,1);
8099 /* shift count is unknown then we have to form
8100 a loop get the loop count in B : Note: we take
8101 only the lower order byte since shifting
8102 more that 32 bits make no sense anyway, ( the
8103 largest size of an object can be only 32 bits ) */
8105 //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8106 //pic14_emitcode("inc","b");
8107 //freeAsmop (right,NULL,ic,TRUE);
8108 //aopOp(left,ic,FALSE);
8109 //aopOp(result,ic,FALSE);
8111 /* now move the left to the result if they are not the
8113 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
8114 AOP_SIZE(result) > 1) {
8116 size = AOP_SIZE(result);
8120 l = aopGet(AOP(left),offset,FALSE,TRUE);
8121 if (*l == '@' && IS_AOP_PREG(result)) {
8122 pic14_emitcode("mov","a,%s",l);
8123 aopPut(AOP(result),"a",offset);
8125 aopPut(AOP(result),l,offset);
8127 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8128 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8134 /* mov the highest order bit to OVR */
8135 tlbl = newiTempLabel(NULL);
8136 tlbl1= newiTempLabel(NULL);
8138 size = AOP_SIZE(result);
8141 pctemp = popGetTempReg(); /* grab a temporary working register. */
8143 emitpcode(POC_MOVFW, popGet(AOP(right),0));
8145 /* offset should be 0, 1 or 3 */
8146 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8148 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8150 emitpcode(POC_MOVWF, pctemp);
8153 emitpLabel(tlbl->key);
8155 emitpcode(POC_RLFW, popGet(AOP(result),offset));
8156 emitpcode(POC_RRF, popGet(AOP(result),offset));
8159 emitpcode(POC_RRF, popGet(AOP(result),--offset));
8162 emitpcode(POC_DECFSZ, pctemp);
8163 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8164 emitpLabel(tlbl1->key);
8166 popReleaseTempReg(pctemp);
8168 size = AOP_SIZE(result);
8170 pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8171 pic14_emitcode("rlc","a");
8172 pic14_emitcode("mov","ov,c");
8173 /* if it is only one byte then */
8175 l = aopGet(AOP(left),0,FALSE,FALSE);
8177 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8178 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8179 pic14_emitcode("mov","c,ov");
8180 pic14_emitcode("rrc","a");
8181 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8182 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8183 aopPut(AOP(result),"a",0);
8187 reAdjustPreg(AOP(result));
8188 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8189 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8190 pic14_emitcode("mov","c,ov");
8192 l = aopGet(AOP(result),offset,FALSE,FALSE);
8194 pic14_emitcode("rrc","a");
8195 aopPut(AOP(result),"a",offset--);
8197 reAdjustPreg(AOP(result));
8198 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8199 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8204 freeAsmop(left,NULL,ic,TRUE);
8205 freeAsmop(result,NULL,ic,TRUE);
8206 freeAsmop(right,NULL,ic,TRUE);
8210 /*-----------------------------------------------------------------*/
8211 /* loadSignToC - load the operand's sign bit into CARRY */
8212 /*-----------------------------------------------------------------*/
8214 static void loadSignToC (operand *op)
8217 assert (op && AOP(op) && AOP_SIZE(op));
8220 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8224 /*-----------------------------------------------------------------*/
8225 /* genRightShift - generate code for right shifting */
8226 /*-----------------------------------------------------------------*/
8227 static void genGenericShift (iCode *ic, int shiftRight)
8229 operand *right, *left, *result;
8232 symbol *tlbl, *tlbl1, *inverselbl;
8235 /* if signed then we do it the hard way preserve the
8236 sign bit moving it inwards */
8237 retype = getSpec(operandType(IC_RESULT(ic)));
8238 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8240 /* signed & unsigned types are treated the same : i.e. the
8241 signed is NOT propagated inwards : quoting from the
8242 ANSI - standard : "for E1 >> E2, is equivalent to division
8243 by 2**E2 if unsigned or if it has a non-negative value,
8244 otherwise the result is implementation defined ", MY definition
8245 is that the sign does not get propagated */
8247 right = IC_RIGHT(ic);
8249 result = IC_RESULT(ic);
8251 aopOp(right,ic,FALSE);
8252 aopOp(left,ic,FALSE);
8253 aopOp(result,ic,FALSE);
8255 /* if the shift count is known then do it
8256 as efficiently as possible */
8257 if (AOP_TYPE(right) == AOP_LIT) {
8258 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8262 shiftRight = !shiftRight;
8266 shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8268 shiftLeft_Left2ResultLit (left, result, lit);
8269 //genRightShiftLiteral (left,right,result,ic, 0);
8273 /* shift count is unknown then we have to form
8274 a loop get the loop count in B : Note: we take
8275 only the lower order byte since shifting
8276 more that 32 bits make no sense anyway, ( the
8277 largest size of an object can be only 32 bits ) */
8279 /* we must not overwrite the shift counter */
8280 assert (!pic14_sameRegs(AOP(right),AOP(result)));
8282 /* now move the left to the result if they are not the
8284 if (!pic14_sameRegs(AOP(left),AOP(result)))
8286 size = min(AOP_SIZE(result), AOP_SIZE(left));
8288 mov2w(AOP(left), size);
8289 movwf(AOP(result), size);
8291 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8294 tlbl = newiTempLabel(NULL);
8295 tlbl1= newiTempLabel(NULL);
8297 size = AOP_SIZE(result);
8299 mov2w(AOP(right),0);
8300 if (!SPEC_USIGN(operandType(right)))
8302 inverselbl = newiTempLabel(NULL);
8303 /* signed shift count -- invert shift direction for c<0 */
8304 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8305 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8307 emitpcode(POC_SUBLW, popGetLit(0)); /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8308 /* check for `a = b >> c' with `-c == 0' */
8310 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8311 emitpLabel(tlbl->key);
8312 /* propagate the sign bit inwards for SIGNED result */
8313 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8314 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8315 emitpcode(POC_ADDLW, popGetLit(1)); /* clears CARRY (unless W==0 afterwards) */
8317 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8319 if (!SPEC_USIGN(operandType(right)))
8321 symbol *inv_loop = newiTempLabel(NULL);
8323 shiftRight = !shiftRight; /* invert shift direction */
8325 /* we came here from the code above -- we are done */
8326 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8328 /* emit code for shifting N<0 steps, count is already in W */
8329 emitpLabel(inverselbl->key);
8330 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8331 emitpLabel(inv_loop->key);
8332 /* propagate the sign bit inwards for SIGNED result */
8333 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8334 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8335 emitpcode(POC_ADDLW, popGetLit(1));
8337 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8340 emitpLabel(tlbl1->key);
8342 freeAsmop(left,NULL,ic,TRUE);
8343 freeAsmop (right,NULL,ic,TRUE);
8344 freeAsmop(result,NULL,ic,TRUE);
8347 static void genRightShift (iCode *ic)
8349 genGenericShift(ic, 1);
8352 static void genLeftShift (iCode *ic)
8354 genGenericShift(ic, 0);
8357 /*-----------------------------------------------------------------*/
8358 /* SetIrp - Set IRP bit */
8359 /*-----------------------------------------------------------------*/
8360 void SetIrp(operand *result) {
8362 if (AOP_TYPE(result) == AOP_LIT) {
8363 unsigned lit = (unsigned)operandLitValue(result);
8369 if (PCOP(AOP(result))->type == PO_LITERAL) {
8370 int addrs = PCOL(AOP(result))->lit;
8376 emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8377 if(AOP_SIZE(result) > 1) {
8378 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8386 setup_fsr (operand *ptr)
8389 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8391 /* also setup-up IRP */
8395 /*-----------------------------------------------------------------*/
8396 /* emitPtrByteGet - emits code to get a byte into WREG from an */
8397 /* arbitrary pointer (__code, __data, generic) */
8398 /*-----------------------------------------------------------------*/
8400 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8407 if (!alreadyAddressed) setup_fsr (src);
8408 emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8412 assert( AOP_SIZE(src) == 2 );
8414 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8416 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8417 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
8418 call_libraryfunc ("__gptrget1");
8422 assert( AOP_SIZE(src) == 3 );
8424 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8426 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8428 call_libraryfunc ("__gptrget1");
8432 assert( !"unhandled pointer type" );
8437 /*-----------------------------------------------------------------*/
8438 /* emitPtrByteSet - emits code to set a byte from src through a */
8439 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR). */
8440 /*-----------------------------------------------------------------*/
8442 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8449 if (!alreadyAddressed) setup_fsr (dst);
8450 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8454 assert( !"trying to assign to __code pointer" );
8458 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8460 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8462 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8464 call_libraryfunc ("__gptrput1");
8468 assert( !"unhandled pointer type" );
8473 /*-----------------------------------------------------------------*/
8474 /* genUnpackBits - generates code for unpacking bits */
8475 /*-----------------------------------------------------------------*/
8476 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8478 int rsize; /* result size */
8479 sym_link *etype; /* bitfield type information */
8480 int blen; /* bitfield length */
8481 int bstr; /* bitfield starting bit within byte */
8484 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8485 etype = getSpec(operandType(result));
8486 rsize = getSize (operandType (result));
8487 blen = SPEC_BLEN (etype);
8488 bstr = SPEC_BSTR (etype);
8490 /* single bit field case */
8492 if (ifx) { /* that is for an if statement */
8495 resolveIfx(&rIfx,ifx);
8496 if (ptype == -1) /* direct */
8497 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8499 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8500 emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8501 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8505 assert (!pic14_sameRegs (AOP(result), AOP(left)));
8506 for (i=0; i < AOP_SIZE(result); i++)
8507 emitpcode (POC_CLRF, popGet (AOP(result), i));
8512 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8513 /* adjust result below */
8520 emitPtrByteGet (left, ptype, FALSE);
8521 emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8523 /* adjust result below */
8527 assert( !"unhandled pointer type" );
8530 /* move sign-/zero extended bit to result */
8531 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8532 emitpcode (POC_INCF, popGet (AOP(result), 0));
8534 emitpcode (POC_DECF, popGet (AOP(result), 0));
8536 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8540 else if (blen <= 8 && ((blen + bstr) <= 8))
8545 for (i=0; i < AOP_SIZE(result); i++)
8546 emitpcode (POC_CLRF, popGet (AOP(result), i));
8551 mov2w(AOP(left), 0);
8558 emitPtrByteGet (left, ptype, FALSE);
8562 assert( !"unhandled pointer type" );
8566 emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8567 movwf(AOP(result), 0);
8568 AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8570 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8572 /* signed bitfield */
8573 assert (bstr + blen > 0);
8574 emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8575 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8576 emitpcode(POC_IORWF, popGet(AOP(result),0));
8578 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8582 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8586 /*-----------------------------------------------------------------*/
8587 /* genDataPointerGet - generates code when ptr offset is known */
8588 /*-----------------------------------------------------------------*/
8589 static void genDataPointerGet (operand *left,
8593 int size , offset = 0;
8596 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8599 /* optimization - most of the time, left and result are the same
8600 * address, but different types. for the pic code, we could omit
8603 aopOp(result,ic,TRUE);
8605 if (pic14_sameRegs (AOP(left), AOP(result)))
8608 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8610 //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8612 size = AOP_SIZE(result);
8613 if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8617 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8618 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8622 freeAsmop(left,NULL,ic,TRUE);
8623 freeAsmop(result,NULL,ic,TRUE);
8627 /*-----------------------------------------------------------------*/
8628 /* genNearPointerGet - pic14_emitcode for near pointer fetch */
8629 /*-----------------------------------------------------------------*/
8630 static void genNearPointerGet (operand *left,
8635 sym_link *ltype = operandType(left);
8636 sym_link *rtype = operandType(result);
8637 sym_link *retype= getSpec(rtype); /* bitfield type information */
8641 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8644 aopOp(left,ic,FALSE);
8646 /* if left is rematerialisable and
8647 result is not bit variable type and
8648 the left is pointer to data space i.e
8649 lower 128 bytes of space */
8650 if (AOP_TYPE(left) == AOP_PCODE && //AOP_TYPE(left) == AOP_IMMD &&
8651 !IS_BITVAR(retype) &&
8652 PIC_IS_DATA_PTR(ltype)) {
8653 genDataPointerGet (left,result,ic);
8657 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8658 aopOp (result,ic,FALSE);
8660 /* Check if can access directly instead of via a pointer */
8661 if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8662 && AOP_SIZE(result) == 1)
8667 if (IS_BITFIELD(getSpec(operandType(result))))
8669 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8673 /* If the pointer value is not in a the FSR then need to put it in */
8674 /* Must set/reset IRP bit for use with FSR. */
8679 /* if bitfield then unpack the bits */
8681 /* we have can just get the values */
8682 int size = AOP_SIZE(result);
8685 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8689 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8691 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8692 if (AOP_TYPE(result) == AOP_LIT) {
8693 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8695 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8697 if (size && !direct)
8698 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8703 /* now some housekeeping stuff */
8705 /* we had to allocate for this iCode */
8706 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8707 freeAsmop(NULL,aop,ic,TRUE);
8709 /* we did not allocate which means left
8710 already in a pointer register, then
8711 if size > 0 && this could be used again
8712 we have to point it back to where it
8714 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8715 if (AOP_SIZE(result) > 1 &&
8716 !OP_SYMBOL(left)->remat &&
8717 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8719 int size = AOP_SIZE(result) - 1;
8721 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8727 freeAsmop(left,NULL,ic,TRUE);
8728 freeAsmop(result,NULL,ic,TRUE);
8733 /*-----------------------------------------------------------------*/
8734 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch */
8735 /*-----------------------------------------------------------------*/
8736 static void genPagedPointerGet (operand *left,
8743 sym_link *rtype, *retype;
8746 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8748 rtype = operandType(result);
8749 retype= getSpec(rtype);
8751 aopOp(left,ic,FALSE);
8753 /* if the value is already in a pointer register
8754 then don't need anything more */
8755 if (!AOP_INPREG(AOP(left))) {
8756 /* otherwise get a free pointer register */
8758 preg = getFreePtr(ic,&aop,FALSE);
8759 pic14_emitcode("mov","%s,%s",
8761 aopGet(AOP(left),0,FALSE,TRUE));
8762 rname = preg->name ;
8764 rname = aopGet(AOP(left),0,FALSE,FALSE);
8766 freeAsmop(left,NULL,ic,TRUE);
8767 aopOp (result,ic,FALSE);
8769 /* if bitfield then unpack the bits */
8770 if (IS_BITFIELD(retype))
8771 genUnpackBits (result,left,rname,PPOINTER,0);
8773 /* we have can just get the values */
8774 int size = AOP_SIZE(result);
8779 pic14_emitcode("movx","a,@%s",rname);
8780 aopPut(AOP(result),"a",offset);
8785 pic14_emitcode("inc","%s",rname);
8789 /* now some housekeeping stuff */
8791 /* we had to allocate for this iCode */
8792 freeAsmop(NULL,aop,ic,TRUE);
8794 /* we did not allocate which means left
8795 already in a pointer register, then
8796 if size > 0 && this could be used again
8797 we have to point it back to where it
8799 if (AOP_SIZE(result) > 1 &&
8800 !OP_SYMBOL(left)->remat &&
8801 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8803 int size = AOP_SIZE(result) - 1;
8805 pic14_emitcode("dec","%s",rname);
8810 freeAsmop(result,NULL,ic,TRUE);
8815 /*-----------------------------------------------------------------*/
8816 /* genFarPointerGet - gget value from far space */
8817 /*-----------------------------------------------------------------*/
8818 static void genFarPointerGet (operand *left,
8819 operand *result, iCode *ic)
8822 sym_link *retype = getSpec(operandType(result));
8825 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8827 aopOp(left,ic,FALSE);
8829 /* if the operand is already in dptr
8830 then we do nothing else we move the value to dptr */
8831 if (AOP_TYPE(left) != AOP_STR) {
8832 /* if this is remateriazable */
8833 if (AOP_TYPE(left) == AOP_IMMD)
8834 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8835 else { /* we need to get it byte by byte */
8836 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8837 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8838 if (options.model == MODEL_FLAT24)
8840 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8844 /* so dptr know contains the address */
8845 freeAsmop(left,NULL,ic,TRUE);
8846 aopOp(result,ic,FALSE);
8848 /* if bit then unpack */
8849 if (IS_BITFIELD(retype))
8850 genUnpackBits(result,left,"dptr",FPOINTER,0);
8852 size = AOP_SIZE(result);
8856 pic14_emitcode("movx","a,@dptr");
8857 aopPut(AOP(result),"a",offset++);
8859 pic14_emitcode("inc","dptr");
8863 freeAsmop(result,NULL,ic,TRUE);
8868 /*-----------------------------------------------------------------*/
8869 /* genCodePointerGet - get value from code space */
8870 /*-----------------------------------------------------------------*/
8871 static void genCodePointerGet (operand *left,
8872 operand *result, iCode *ic)
8875 sym_link *retype = getSpec(operandType(result));
8877 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8879 aopOp(left,ic,FALSE);
8881 /* if the operand is already in dptr
8882 then we do nothing else we move the value to dptr */
8883 if (AOP_TYPE(left) != AOP_STR) {
8884 /* if this is remateriazable */
8885 if (AOP_TYPE(left) == AOP_IMMD)
8886 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8887 else { /* we need to get it byte by byte */
8888 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8889 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8890 if (options.model == MODEL_FLAT24)
8892 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8896 /* so dptr know contains the address */
8897 freeAsmop(left,NULL,ic,TRUE);
8898 aopOp(result,ic,FALSE);
8900 /* if bit then unpack */
8901 if (IS_BITFIELD(retype))
8902 genUnpackBits(result,left,"dptr",CPOINTER,0);
8904 size = AOP_SIZE(result);
8908 pic14_emitcode("clr","a");
8909 pic14_emitcode("movc","a,@a+dptr");
8910 aopPut(AOP(result),"a",offset++);
8912 pic14_emitcode("inc","dptr");
8916 freeAsmop(result,NULL,ic,TRUE);
8919 /*-----------------------------------------------------------------*/
8920 /* genGenPointerGet - gget value from generic pointer space */
8921 /*-----------------------------------------------------------------*/
8922 static void genGenPointerGet (operand *left,
8923 operand *result, iCode *ic)
8926 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8927 aopOp(left,ic,FALSE);
8928 aopOp(result,ic,FALSE);
8931 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8933 if (IS_BITFIELD(getSpec(operandType(result))))
8935 genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
8940 /* emit call to __gptrget */
8941 char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
8942 int size = AOP_SIZE(result);
8945 assert (size > 0 && size <= 4);
8947 /* pass arguments */
8948 assert (AOP_SIZE(left) == 3);
8949 mov2w(AOP(left), 0);
8950 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8951 mov2w(AOP(left), 1);
8952 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8953 mov2w(AOP(left), 2);
8954 call_libraryfunc (func[size]);
8957 movwf (AOP(result), --size);
8959 emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
8960 movwf (AOP(result), size);
8964 freeAsmop(left,NULL,ic,TRUE);
8965 freeAsmop(result,NULL,ic,TRUE);
8969 /*-----------------------------------------------------------------*/
8970 /* genConstPointerGet - get value from const generic pointer space */
8971 /*-----------------------------------------------------------------*/
8972 static void genConstPointerGet (operand *left,
8973 operand *result, iCode *ic)
8975 //sym_link *retype = getSpec(operandType(result));
8977 symbol *albl, *blbl;//, *clbl;
8984 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8985 aopOp(left,ic,FALSE);
8986 aopOp(result,ic,FALSE);
8988 size = AOP_SIZE(result);
8990 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8992 DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
8994 lit = op_isLitLike (left);
8995 poc = lit ? POC_MOVLW : POC_MOVFW;
8997 if (IS_BITFIELD(getSpec(operandType(result))))
8999 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
9004 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
9005 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
9006 assert (size > 0 && size <= 4);
9009 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9011 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9012 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
9013 call_libraryfunc (func[size]);
9015 movwf(AOP(result),size-1);
9016 for (i = 1; i < size; i++)
9018 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
9019 movwf(AOP(result),size - 1 - i);
9024 freeAsmop(left,NULL,ic,TRUE);
9025 freeAsmop(result,NULL,ic,TRUE);
9028 /*-----------------------------------------------------------------*/
9029 /* genPointerGet - generate code for pointer get */
9030 /*-----------------------------------------------------------------*/
9031 static void genPointerGet (iCode *ic)
9033 operand *left, *result ;
9034 sym_link *type, *etype;
9038 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9041 result = IC_RESULT(ic) ;
9043 /* depending on the type of pointer we need to
9044 move it to the correct pointer register */
9045 type = operandType(left);
9046 etype = getSpec(type);
9048 if (IS_PTR_CONST(type))
9049 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9051 /* if left is of type of pointer then it is simple */
9052 if (IS_PTR(type) && !IS_FUNC(type->next))
9053 p_type = DCL_TYPE(type);
9055 /* we have to go by the storage class */
9056 p_type = PTR_TYPE(SPEC_OCLS(etype));
9058 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9060 if (SPEC_OCLS(etype)->codesp ) {
9061 DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9062 //p_type = CPOINTER ;
9065 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9066 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9067 /*p_type = FPOINTER ;*/
9069 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9070 DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9071 /* p_type = PPOINTER; */
9073 if (SPEC_OCLS(etype) == idata )
9074 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9075 /* p_type = IPOINTER; */
9077 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9078 /* p_type = POINTER ; */
9081 /* now that we have the pointer type we assign
9082 the pointer values */
9088 genNearPointerGet (left,result,ic);
9092 genPagedPointerGet(left,result,ic);
9096 genFarPointerGet (left,result,ic);
9100 genConstPointerGet (left,result,ic);
9104 genGenPointerGet (left,result,ic);
9107 assert ( !"unhandled pointer type" );
9113 /*-----------------------------------------------------------------*/
9114 /* genPackBits - generates code for packed bit storage */
9115 /*-----------------------------------------------------------------*/
9116 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9118 int blen; /* bitfield length */
9119 int bstr; /* bitfield starting bit within byte */
9120 int litval; /* source literal value (if AOP_LIT) */
9121 unsigned char mask; /* bitmask within current byte */
9124 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9126 blen = SPEC_BLEN (etype);
9127 bstr = SPEC_BSTR (etype);
9129 /* If the bitfield length is less than a byte and does not cross byte boundaries */
9130 if ((blen <= 8) && ((bstr + blen) <= 8))
9132 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9133 (unsigned char) (0xFF >> (8 - bstr)));
9135 if (AOP_TYPE (right) == AOP_LIT)
9137 /* Case with a bitfield length <8 and literal source */
9138 int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9145 if (AOP(result)->type == AOP_PCODE)
9146 pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9148 pcop = popGet(AOP(result),0);
9149 emitpcode(lit?POC_BSF:POC_BCF,pcop);
9155 emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9159 assert( !"trying to assign to bitfield via pointer to __code space" );
9163 emitPtrByteGet(result, p_type, FALSE);
9165 emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9167 emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9169 emitPtrByteSet(result, p_type, TRUE);
9173 assert( !"unhandled pointer type" );
9175 } // switch (p_type)
9178 litval = lit << bstr;
9179 litval &= (~mask) & 0x00ff;
9184 mov2w (AOP(result), 0);
9185 if ((litval|mask) != 0x00ff)
9186 emitpcode(POC_ANDLW, popGetLit (mask));
9188 emitpcode(POC_IORLW, popGetLit (litval));
9189 movwf (AOP(result), 0);
9195 emitPtrByteGet(result, p_type, FALSE);
9196 if ((litval|mask) != 0x00ff)
9197 emitpcode(POC_ANDLW, popGetLit (mask));
9199 emitpcode(POC_IORLW, popGetLit (litval));
9200 emitPtrByteSet(result, p_type, TRUE);
9204 assert( !"trying to assign to bitfield via pointer to __code space" );
9208 assert( !"unhandled pointer type" );
9215 /* right is no literal */
9220 /* Note more efficient code, of pre clearing bit then only setting it if required,
9221 * can only be done if it is known that the result is not a SFR */
9222 emitpcode(POC_RRFW,popGet(AOP(right),0));
9224 emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9226 emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9232 emitPtrByteGet (result, p_type, FALSE);
9233 emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9234 emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9235 emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9236 emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9237 emitPtrByteSet (result, p_type, TRUE);
9241 assert( !"trying to assign to bitfield via pointer to __code space" );
9245 assert( !"unhandled pointer type" );
9250 /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9251 pCodeOp *temp = popGetTempReg ();
9253 mov2w (AOP(right), 0);
9255 emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9257 emitpcode(POC_MOVWF, temp);
9259 AccLsh (temp, bstr);
9265 mov2w (AOP(result), 0);
9266 emitpcode(POC_ANDLW, popGetLit (mask));
9267 emitpcode(POC_IORFW, temp);
9268 movwf (AOP(result), 0);
9274 emitPtrByteGet (result, p_type, FALSE);
9275 emitpcode(POC_ANDLW, popGetLit (mask));
9276 emitpcode(POC_IORFW, temp);
9277 emitPtrByteSet (result, p_type, TRUE);
9281 assert( !"trying to assign to bitfield via pointer to __code space" );
9285 assert( !"unhandled pointer type" );
9289 popReleaseTempReg (temp);
9291 } // if (AOP(right)->type != AOP_LIT)
9293 } // if (blen <= 8 && ((blen + bstr) <= 8))
9295 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9298 /*-----------------------------------------------------------------*/
9299 /* genDataPointerSet - remat pointer to data space */
9300 /*-----------------------------------------------------------------*/
9301 static void genDataPointerSet(operand *right,
9305 int size, offset = 0 ;
9309 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9310 aopOp(right,ic,FALSE);
9311 aopOp(result,ic,FALSE);
9313 assert (IS_SYMOP(result));
9314 assert (IS_PTR(OP_SYM_TYPE(result)));
9316 if (AOP_TYPE(right) == AOP_LIT)
9319 size = AOP_SIZE(right);
9320 ressize = getSize(OP_SYM_ETYPE(result));
9321 if (size > ressize) size = ressize;
9322 //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9324 //assert( !"what's going on here?" );
9327 if ( AOP_TYPE(result) == AOP_PCODE) {
9328 fprintf(stderr,"genDataPointerSet %s, %d\n",
9329 AOP(result)->aopu.pcop->name,
9330 PCOI(AOP(result)->aopu.pcop)->offset);
9334 // tsd, was l+1 - the underline `_' prefix was being stripped
9336 emitpComment ("%s:%u: size=%d/%d, offset=%d, AOP_TYPE(res)=%d", __FILE__,__LINE__, size, ressize, offset, AOP_TYPE(result));
9338 if (AOP_TYPE(right) == AOP_LIT) {
9339 unsigned int lit = pic14aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
9340 //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9342 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9343 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9345 emitpcode(POC_CLRF, popGet(AOP(result), offset));
9348 //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9349 emitpcode(POC_MOVFW, popGet(AOP(right), offset));
9350 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9356 freeAsmop(right,NULL,ic,TRUE);
9357 freeAsmop(result,NULL,ic,TRUE);
9360 /*-----------------------------------------------------------------*/
9361 /* genNearPointerSet - pic14_emitcode for near pointer put */
9362 /*-----------------------------------------------------------------*/
9363 static void genNearPointerSet (operand *right,
9368 sym_link *ptype = operandType(result);
9369 sym_link *retype = getSpec(operandType(right));
9370 sym_link *letype = getSpec(ptype);
9375 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9376 aopOp(result,ic,FALSE);
9379 /* if the result is rematerializable &
9380 in data space & not a bit variable */
9381 //if (AOP_TYPE(result) == AOP_IMMD &&
9382 if (AOP_TYPE(result) == AOP_PCODE &&
9383 PIC_IS_DATA_PTR(ptype) &&
9384 !IS_BITVAR (retype) &&
9385 !IS_BITVAR (letype)) {
9386 genDataPointerSet (right,result,ic);
9387 freeAsmop(result,NULL,ic,TRUE);
9392 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9393 aopOp(right,ic,FALSE);
9394 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9396 /* Check if can access directly instead of via a pointer */
9397 if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9401 if (IS_BITFIELD (letype))
9403 genPackBits (letype, result, right, direct?-1:POINTER);
9407 /* If the pointer value is not in a the FSR then need to put it in */
9408 /* Must set/reset IRP bit for use with FSR. */
9409 /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9414 /* we have can just get the values */
9415 int size = AOP_SIZE(right);
9418 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9420 char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9422 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9424 if (AOP_TYPE(right) == AOP_LIT) {
9425 emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9427 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9430 emitpcode(POC_MOVWF,popGet(AOP(result),0));
9432 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9434 if (size && !direct)
9435 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9440 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9441 /* now some housekeeping stuff */
9443 /* we had to allocate for this iCode */
9444 freeAsmop(NULL,aop,ic,TRUE);
9446 /* we did not allocate which means left
9447 already in a pointer register, then
9448 if size > 0 && this could be used again
9449 we have to point it back to where it
9451 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9452 if (AOP_SIZE(right) > 1 &&
9453 !OP_SYMBOL(result)->remat &&
9454 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9456 int size = AOP_SIZE(right) - 1;
9458 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9462 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9465 freeAsmop(right,NULL,ic,TRUE);
9466 freeAsmop(result,NULL,ic,TRUE);
9470 /*-----------------------------------------------------------------*/
9471 /* genPagedPointerSet - pic14_emitcode for Paged pointer put */
9472 /*-----------------------------------------------------------------*/
9473 static void genPagedPointerSet (operand *right,
9483 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9485 retype= getSpec(operandType(right));
9487 aopOp(result,ic,FALSE);
9489 /* if the value is already in a pointer register
9490 then don't need anything more */
9491 if (!AOP_INPREG(AOP(result))) {
9492 /* otherwise get a free pointer register */
9494 preg = getFreePtr(ic,&aop,FALSE);
9495 pic14_emitcode("mov","%s,%s",
9497 aopGet(AOP(result),0,FALSE,TRUE));
9498 rname = preg->name ;
9500 rname = aopGet(AOP(result),0,FALSE,FALSE);
9502 freeAsmop(result,NULL,ic,TRUE);
9503 aopOp (right,ic,FALSE);
9505 /* if bitfield then unpack the bits */
9506 if (IS_BITFIELD(retype))
9507 genPackBits (retype,result,right,rname,PPOINTER);
9509 /* we have can just get the values */
9510 int size = AOP_SIZE(right);
9514 l = aopGet(AOP(right),offset,FALSE,TRUE);
9517 pic14_emitcode("movx","@%s,a",rname);
9520 pic14_emitcode("inc","%s",rname);
9526 /* now some housekeeping stuff */
9528 /* we had to allocate for this iCode */
9529 freeAsmop(NULL,aop,ic,TRUE);
9531 /* we did not allocate which means left
9532 already in a pointer register, then
9533 if size > 0 && this could be used again
9534 we have to point it back to where it
9536 if (AOP_SIZE(right) > 1 &&
9537 !OP_SYMBOL(result)->remat &&
9538 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9540 int size = AOP_SIZE(right) - 1;
9542 pic14_emitcode("dec","%s",rname);
9547 freeAsmop(right,NULL,ic,TRUE);
9552 /*-----------------------------------------------------------------*/
9553 /* genFarPointerSet - set value from far space */
9554 /*-----------------------------------------------------------------*/
9555 static void genFarPointerSet (operand *right,
9556 operand *result, iCode *ic)
9559 sym_link *retype = getSpec(operandType(right));
9562 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9563 aopOp(result,ic,FALSE);
9565 /* if the operand is already in dptr
9566 then we do nothing else we move the value to dptr */
9567 if (AOP_TYPE(result) != AOP_STR) {
9568 /* if this is remateriazable */
9569 if (AOP_TYPE(result) == AOP_IMMD)
9570 pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9571 else { /* we need to get it byte by byte */
9572 pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9573 pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9574 if (options.model == MODEL_FLAT24)
9576 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9580 /* so dptr know contains the address */
9581 freeAsmop(result,NULL,ic,TRUE);
9582 aopOp(right,ic,FALSE);
9584 /* if bit then unpack */
9585 if (IS_BITFIELD(retype))
9586 genPackBits(retype,result,right,"dptr",FPOINTER);
9588 size = AOP_SIZE(right);
9592 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9594 pic14_emitcode("movx","@dptr,a");
9596 pic14_emitcode("inc","dptr");
9600 freeAsmop(right,NULL,ic,TRUE);
9604 /*-----------------------------------------------------------------*/
9605 /* genGenPointerSet - set value from generic pointer space */
9606 /*-----------------------------------------------------------------*/
9607 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9609 sym_link *retype = getSpec(operandType(result));
9612 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9613 aopOp(right,ic,FALSE);
9614 aopOp(result,ic,FALSE);
9617 DEBUGpic14_AopType(__LINE__,right,NULL,result);
9619 if (IS_BITFIELD(retype))
9621 genPackBits (retype, result, right, GPOINTER);
9626 /* emit call to __gptrput */
9627 char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9628 int size = AOP_SIZE(right);
9631 assert (size == getSize(OP_SYM_ETYPE(result)));
9632 assert (size > 0 && size <= 4);
9634 /* pass arguments */
9635 /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9641 mov2w_op (right, off);
9642 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9647 assert (AOP_SIZE(result) == 3);
9648 mov2w(AOP(result), 0);
9649 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9650 mov2w(AOP(result), 1);
9651 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9652 mov2w(AOP(result), 2);
9653 call_libraryfunc (func[size]);
9656 freeAsmop(right,NULL,ic,TRUE);
9657 freeAsmop(result,NULL,ic,TRUE);
9660 /*-----------------------------------------------------------------*/
9661 /* genPointerSet - stores the value into a pointer location */
9662 /*-----------------------------------------------------------------*/
9663 static void genPointerSet (iCode *ic)
9665 operand *right, *result ;
9666 sym_link *type, *etype;
9670 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9672 right = IC_RIGHT(ic);
9673 result = IC_RESULT(ic) ;
9675 /* depending on the type of pointer we need to
9676 move it to the correct pointer register */
9677 type = operandType(result);
9678 etype = getSpec(type);
9679 /* if left is of type of pointer then it is simple */
9680 if (IS_PTR(type) && !IS_FUNC(type->next)) {
9681 p_type = DCL_TYPE(type);
9684 /* we have to go by the storage class */
9685 p_type = PTR_TYPE(SPEC_OCLS(etype));
9687 /* if (SPEC_OCLS(etype)->codesp ) { */
9688 /* p_type = CPOINTER ; */
9691 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9692 /* p_type = FPOINTER ; */
9694 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9695 /* p_type = PPOINTER ; */
9697 /* if (SPEC_OCLS(etype) == idata ) */
9698 /* p_type = IPOINTER ; */
9700 /* p_type = POINTER ; */
9703 /* now that we have the pointer type we assign
9704 the pointer values */
9710 genNearPointerSet (right,result,ic);
9714 genPagedPointerSet (right,result,ic);
9718 genFarPointerSet (right,result,ic);
9722 genGenPointerSet (right,result,ic);
9726 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9727 "genPointerSet: illegal pointer type");
9731 /*-----------------------------------------------------------------*/
9732 /* genIfx - generate code for Ifx statement */
9733 /*-----------------------------------------------------------------*/
9734 static void genIfx (iCode *ic, iCode *popIc)
9736 operand *cond = IC_COND(ic);
9740 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9742 aopOp(cond,ic,FALSE);
9744 /* get the value into acc */
9745 if (AOP_TYPE(cond) != AOP_CRY)
9746 pic14_toBoolean(cond);
9750 /* if there was something to be popped then do it */
9756 /* This assumes that CARRY is set iff cond is true */
9759 assert (!IC_FALSE(ic));
9760 emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
9762 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9764 assert (IC_FALSE(ic));
9765 emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
9767 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9771 static int hasWarned = 0;
9774 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
9781 /* now Z is set iff !cond */
9784 assert (!IC_FALSE(ic));
9786 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9789 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9795 /* the result is now in the accumulator */
9796 freeAsmop(cond,NULL,ic,TRUE);
9799 /*-----------------------------------------------------------------*/
9800 /* genAddrOf - generates code for address of */
9801 /*-----------------------------------------------------------------*/
9802 static void genAddrOf (iCode *ic)
9804 operand *right, *result, *left;
9808 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9811 //aopOp(IC_RESULT(ic),ic,FALSE);
9813 aopOp((left=IC_LEFT(ic)),ic,FALSE);
9814 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9815 aopOp((result=IC_RESULT(ic)),ic,TRUE);
9817 DEBUGpic14_AopType(__LINE__,left,right,result);
9818 assert (IS_SYMOP (left));
9820 /* sanity check: generic pointers to code space are not yet supported,
9821 * pionters to codespace must not be assigned addresses of __data values. */
9823 fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9824 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)));
9825 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)));
9826 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)));
9827 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)));
9830 if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9831 fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9832 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9833 OP_SYMBOL(left)->name);
9834 } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9835 fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9836 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9837 OP_SYMBOL(left)->name);
9840 size = AOP_SIZE(IC_RESULT(ic));
9841 if (IS_GENPTR(OP_SYM_TYPE(result))) {
9843 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9848 /* fixing bug #863624, reported from (errolv) */
9849 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9850 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9853 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9854 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9859 if (IS_GENPTR(OP_SYM_TYPE(result)))
9861 /* provide correct tag */
9862 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9863 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9864 movwf (AOP(result), 2);
9867 freeAsmop(left,NULL,ic,FALSE);
9868 freeAsmop(result,NULL,ic,TRUE);
9873 /*-----------------------------------------------------------------*/
9874 /* genFarFarAssign - assignment when both are in far space */
9875 /*-----------------------------------------------------------------*/
9876 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9878 int size = AOP_SIZE(right);
9881 /* first push the right side on to the stack */
9883 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9885 pic14_emitcode ("push","acc");
9888 freeAsmop(right,NULL,ic,FALSE);
9889 /* now assign DPTR to result */
9890 aopOp(result,ic,FALSE);
9891 size = AOP_SIZE(result);
9893 pic14_emitcode ("pop","acc");
9894 aopPut(AOP(result),"a",--offset);
9896 freeAsmop(result,NULL,ic,FALSE);
9901 /*-----------------------------------------------------------------*/
9902 /* genAssign - generate code for assignment */
9903 /*-----------------------------------------------------------------*/
9904 static void genAssign (iCode *ic)
9906 operand *result, *right;
9907 int size, offset,know_W;
9908 unsigned long lit = 0L;
9910 result = IC_RESULT(ic);
9911 right = IC_RIGHT(ic) ;
9914 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9916 /* if they are the same */
9917 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9920 aopOp(right,ic,FALSE);
9921 aopOp(result,ic,TRUE);
9923 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9925 /* if they are the same registers */
9926 if (pic14_sameRegs(AOP(right),AOP(result)))
9929 /* special case: assign from __code */
9930 if (!IS_ITEMP(right) /* --> iTemps never reside in __code */
9931 && IS_SYMOP (right) /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
9932 && !IS_FUNC(OP_SYM_TYPE(right)) /* --> we would want its address instead of the first instruction */
9933 && !IS_CODEPTR(OP_SYM_TYPE(right)) /* --> get symbols address instread */
9934 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
9936 emitpComment ("genAssign from CODESPACE");
9937 genConstPointerGet (right, result, ic);
9941 /* just for symmetry reasons... */
9942 if (!IS_ITEMP(result)
9943 && IS_SYMOP (result)
9944 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
9946 assert ( !"cannot write to CODESPACE" );
9949 /* if the result is a bit */
9950 if (AOP_TYPE(result) == AOP_CRY) {
9952 /* if the right size is a literal then
9953 we know what the value is */
9954 if (AOP_TYPE(right) == AOP_LIT) {
9956 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9957 popGet(AOP(result),0));
9959 if (((int) operandLitValue(right)))
9960 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9961 AOP(result)->aopu.aop_dir,
9962 AOP(result)->aopu.aop_dir);
9964 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9965 AOP(result)->aopu.aop_dir,
9966 AOP(result)->aopu.aop_dir);
9970 /* the right is also a bit variable */
9971 if (AOP_TYPE(right) == AOP_CRY) {
9972 emitpcode(POC_BCF, popGet(AOP(result),0));
9973 emitpcode(POC_BTFSC, popGet(AOP(right),0));
9974 emitpcode(POC_BSF, popGet(AOP(result),0));
9976 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9977 AOP(result)->aopu.aop_dir,
9978 AOP(result)->aopu.aop_dir);
9979 pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
9980 AOP(right)->aopu.aop_dir,
9981 AOP(right)->aopu.aop_dir);
9982 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9983 AOP(result)->aopu.aop_dir,
9984 AOP(result)->aopu.aop_dir);
9989 emitpcode(POC_BCF, popGet(AOP(result),0));
9990 pic14_toBoolean(right);
9992 emitpcode(POC_BSF, popGet(AOP(result),0));
9993 //aopPut(AOP(result),"a",0);
9997 /* bit variables done */
9999 size = AOP_SIZE(result);
10001 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
10002 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10003 if(aopIdx(AOP(result),0) == 4) {
10004 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10005 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10006 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10009 DEBUGpic14_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
10015 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10016 if(AOP_TYPE(right) == AOP_LIT) {
10017 lit = (unsigned long)pic14aopLiteral(AOP(right)->aopu.aop_lit, offset) & 0x0ff;
10019 if(know_W != (int)(lit&0xff))
10020 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10022 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10024 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10026 } else if (AOP_TYPE(right) == AOP_CRY) {
10027 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10029 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10030 emitpcode(POC_INCF, popGet(AOP(result),0));
10033 mov2w_op (right, offset);
10034 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10042 freeAsmop (right,NULL,ic,FALSE);
10043 freeAsmop (result,NULL,ic,TRUE);
10046 /*-----------------------------------------------------------------*/
10047 /* genJumpTab - genrates code for jump table */
10048 /*-----------------------------------------------------------------*/
10049 static void genJumpTab (iCode *ic)
10055 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10057 aopOp(IC_JTCOND(ic),ic,FALSE);
10058 /* get the condition into accumulator */
10059 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10061 /* multiply by three */
10062 pic14_emitcode("add","a,acc");
10063 pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10065 jtab = newiTempLabel(NULL);
10066 pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10067 pic14_emitcode("jmp","@a+dptr");
10068 pic14_emitcode("","%05d_DS_:",jtab->key+100);
10070 emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10071 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10072 emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10073 emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10075 emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10076 emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10077 emitpLabel(jtab->key);
10079 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10081 /* now generate the jump labels */
10082 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10083 jtab = setNextItem(IC_JTLABELS(ic))) {
10084 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10085 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10091 /*-----------------------------------------------------------------*/
10092 /* genMixedOperation - gen code for operators between mixed types */
10093 /*-----------------------------------------------------------------*/
10095 TSD - Written for the PIC port - but this unfortunately is buggy.
10096 This routine is good in that it is able to efficiently promote
10097 types to different (larger) sizes. Unfortunately, the temporary
10098 variables that are optimized out by this routine are sometimes
10099 used in other places. So until I know how to really parse the
10100 iCode tree, I'm going to not be using this routine :(.
10102 static int genMixedOperation (iCode *ic)
10106 operand *result = IC_RESULT(ic);
10107 sym_link *ctype = operandType(IC_LEFT(ic));
10108 operand *right = IC_RIGHT(ic);
10114 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10116 pic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10122 nextright = IC_RIGHT(nextic);
10123 nextleft = IC_LEFT(nextic);
10124 nextresult = IC_RESULT(nextic);
10126 aopOp(right,ic,FALSE);
10127 aopOp(result,ic,FALSE);
10128 aopOp(nextright, nextic, FALSE);
10129 aopOp(nextleft, nextic, FALSE);
10130 aopOp(nextresult, nextic, FALSE);
10132 if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10134 operand *t = right;
10138 pic14_emitcode(";remove right +","");
10140 } else if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10142 operand *t = right;
10146 pic14_emitcode(";remove left +","");
10150 big = AOP_SIZE(nextleft);
10151 small = AOP_SIZE(nextright);
10153 switch(nextic->op) {
10156 pic14_emitcode(";optimize a +","");
10157 /* if unsigned or not an integral type */
10158 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10159 pic14_emitcode(";add a bit to something","");
10162 pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10164 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10165 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10166 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10168 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10176 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10177 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10178 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10181 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10183 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10184 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10185 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10186 pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10187 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10190 pic14_emitcode("rlf","known_zero,w");
10197 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10198 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10199 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10201 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10211 freeAsmop(right,NULL,ic,TRUE);
10212 freeAsmop(result,NULL,ic,TRUE);
10213 freeAsmop(nextright,NULL,ic,TRUE);
10214 freeAsmop(nextleft,NULL,ic,TRUE);
10216 nextic->generated = 1;
10223 /*-----------------------------------------------------------------*/
10224 /* genCast - gen code for casting */
10225 /*-----------------------------------------------------------------*/
10226 static void genCast (iCode *ic)
10228 operand *result = IC_RESULT(ic);
10229 sym_link *restype = operandType(result);
10230 sym_link *rtype = operandType(IC_RIGHT(ic));
10231 operand *right = IC_RIGHT(ic);
10235 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10236 /* if they are equivalent then do nothing */
10237 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10240 aopOp(right,ic,FALSE) ;
10241 aopOp(result,ic,FALSE);
10243 DEBUGpic14_AopType(__LINE__,NULL,right,result);
10245 /* if the result is a bit */
10246 if (AOP_TYPE(result) == AOP_CRY) {
10247 assert(!"assigning to bit variables is not supported");
10250 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10252 size = AOP_SIZE(result);
10254 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10256 emitpcode(POC_CLRF, popGet(AOP(result),0));
10257 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10258 emitpcode(POC_INCF, popGet(AOP(result),0));
10261 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
10266 if (IS_PTR(restype))
10268 operand *result = IC_RESULT(ic);
10269 //operand *left = IC_LEFT(ic);
10270 operand *right = IC_RIGHT(ic);
10273 /* copy common part */
10274 int max, size = AOP_SIZE(result);
10275 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10276 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10278 /* warn if we discard generic opinter tag */
10279 if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10281 //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10287 mov2w_op (right, size);
10288 movwf (AOP(result), size);
10291 /* upcast into generic pointer type? */
10292 if (IS_GENPTR(restype)
10293 && (size < AOP_SIZE(result))
10294 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10296 //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10299 switch (DCL_TYPE(rtype))
10301 case POINTER: /* __data */
10302 case FPOINTER: /* __data */
10303 assert (AOP_SIZE(right) == 2);
10304 tag = GPTRTAG_DATA;
10307 case CPOINTER: /* __code */
10308 assert (AOP_SIZE(right) == 2);
10309 tag = GPTRTAG_CODE;
10312 case GPOINTER: /* unknown destination, __data or __code */
10313 /* assume __data space (address of immediate) */
10314 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10315 if (AOP(right)->code)
10316 tag = GPTRTAG_CODE;
10318 tag = GPTRTAG_DATA;
10322 assert (!"unhandled pointer type");
10325 /* convert other values into pointers to __data space */
10326 tag = GPTRTAG_DATA;
10329 assert (AOP_SIZE(result) == 3);
10331 emitpcode(POC_CLRF, popGet(AOP(result), 2));
10333 emitpcode(POC_MOVLW, popGetLit(tag));
10334 movwf(AOP(result), 2);
10337 addSign(result, max, 0);
10342 /* if they are the same size : or less */
10343 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10345 /* if they are in the same place */
10346 if (pic14_sameRegs(AOP(right),AOP(result)))
10349 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10350 if (IS_PTR_CONST(rtype))
10351 DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10352 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10353 DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10355 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10356 emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10357 emitpcode(POC_MOVWF, popGet(AOP(result),0));
10358 emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10359 emitpcode(POC_MOVWF, popGet(AOP(result),1));
10360 if(AOP_SIZE(result) <2)
10361 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10365 /* if they in different places then copy */
10366 size = AOP_SIZE(result);
10369 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10370 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10372 //aopPut(AOP(result),
10373 // aopGet(AOP(right),offset,FALSE,FALSE),
10382 /* so we now know that the size of destination is greater
10383 than the size of the source.
10384 Now, if the next iCode is an operator then we might be
10385 able to optimize the operation without performing a cast.
10387 if(0 && genMixedOperation(ic)) {
10388 /* XXX: cannot optimize: must copy regs! */
10392 /* we move to result for the size of source */
10393 size = AOP_SIZE(right);
10396 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10397 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10401 addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10404 freeAsmop(right,NULL,ic,TRUE);
10405 freeAsmop(result,NULL,ic,TRUE);
10409 /*-----------------------------------------------------------------*/
10410 /* genDjnz - generate decrement & jump if not zero instrucion */
10411 /*-----------------------------------------------------------------*/
10412 static int genDjnz (iCode *ic, iCode *ifx)
10414 symbol *lbl, *lbl1;
10416 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10421 /* if the if condition has a false label
10422 then we cannot save */
10426 /* if the minus is not of the form
10428 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10429 !IS_OP_LITERAL(IC_RIGHT(ic)))
10432 if (operandLitValue(IC_RIGHT(ic)) != 1)
10435 /* if the size of this greater than one then no
10437 if (getSize(operandType(IC_RESULT(ic))) > 1)
10440 /* otherwise we can save BIG */
10441 lbl = newiTempLabel(NULL);
10442 lbl1= newiTempLabel(NULL);
10444 aopOp(IC_RESULT(ic),ic,FALSE);
10446 if (IS_AOP_PREG(IC_RESULT(ic))) {
10447 pic14_emitcode("dec","%s",
10448 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10449 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10450 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10454 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10455 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10457 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10458 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10461 /* pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10462 /* pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10463 /* pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10464 /* pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10467 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10468 ifx->generated = 1;
10472 /*-----------------------------------------------------------------*/
10473 /* genReceive - generate code for a receive iCode */
10474 /*-----------------------------------------------------------------*/
10475 static void genReceive (iCode *ic)
10478 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10480 if (isOperandInFarSpace(IC_RESULT(ic)) &&
10481 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10482 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10484 int size = getSize(operandType(IC_RESULT(ic)));
10485 int offset = fReturnSizePic - size;
10487 pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10488 fReturn[fReturnSizePic - offset - 1] : "acc"));
10491 aopOp(IC_RESULT(ic),ic,FALSE);
10492 size = AOP_SIZE(IC_RESULT(ic));
10495 pic14_emitcode ("pop","acc");
10496 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10501 aopOp(IC_RESULT(ic),ic,FALSE);
10503 GpsuedoStkPtr = ic->parmBytes; // address used arg on stack
10504 assignResultValue(IC_RESULT(ic));
10507 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10510 /*-----------------------------------------------------------------*/
10511 /* genDummyRead - generate code for dummy read of volatiles */
10512 /*-----------------------------------------------------------------*/
10514 genDummyRead (iCode * ic)
10517 pic14_emitcode ("; genDummyRead","");
10518 pic14_emitcode ("; not implemented","");
10523 /*-----------------------------------------------------------------*/
10524 /* genpic14Code - generate code for pic14 based controllers */
10525 /*-----------------------------------------------------------------*/
10527 * At this point, ralloc.c has gone through the iCode and attempted
10528 * to optimize in a way suitable for a PIC. Now we've got to generate
10529 * PIC instructions that correspond to the iCode.
10531 * Once the instructions are generated, we'll pass through both the
10532 * peep hole optimizer and the pCode optimizer.
10533 *-----------------------------------------------------------------*/
10535 void genpic14Code (iCode *lic)
10542 lineHead = lineCurr = NULL;
10544 pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10547 /* if debug information required */
10548 if (options.debug && currFunc) {
10550 debugFile->writeFunction (currFunc, lic);
10555 for (ic = lic ; ic ; ic = ic->next ) {
10557 //DEBUGpic14_emitcode(";ic","");
10558 //fprintf (stderr, "in ic loop\n");
10559 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10560 //ic->lineno, printCLine(ic->filename, ic->lineno));
10562 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10564 //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10565 cline = printCLine (ic->filename, ic->lineno);
10566 if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10567 addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10568 //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10571 if (options.iCodeInAsm) {
10572 char *iLine = printILine(ic);
10573 emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10576 /* if the result is marked as
10577 spilt and rematerializable or code for
10578 this has already been generated then
10580 if (resultRemat(ic) || ic->generated )
10583 /* depending on the operation */
10602 /* IPOP happens only when trying to restore a
10603 spilt live range, if there is an ifx statement
10604 following this pop then the if statement might
10605 be using some of the registers being popped which
10606 would destory the contents of the register so
10607 we need to check for this condition and handle it */
10609 ic->next->op == IFX &&
10610 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10611 genIfx (ic->next,ic);
10629 genEndFunction (ic);
10649 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10666 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
10670 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10677 /* note these two are xlated by algebraic equivalence
10678 during parsing SDCC.y */
10679 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10680 "got '>=' or '<=' shouldn't have come here");
10684 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10696 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10700 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10704 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10728 genRightShift (ic);
10731 case GET_VALUE_AT_ADDRESS:
10736 if (POINTER_SET(ic))
10763 addSet(&_G.sendSet,ic);
10766 case DUMMY_READ_VOLATILE:
10771 fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10778 /* now we are ready to call the
10779 peep hole optimizer */
10780 if (!options.nopeep) {
10781 peepHole (&lineHead);
10783 /* now do the actual printing */
10784 printLine (lineHead,codeOutBuf);
10787 DFPRINTF((stderr,"printing pBlock\n\n"));
10788 printpBlock(stdout,pb);
10794 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10795 * (meaning: representing its own address) or not (referencing its contents).
10796 * This can only be decided based on the operand's type. */
10798 aop_isLitLike (asmop *aop)
10801 if (aop->type == AOP_LIT) return 1;
10802 if (aop->type == AOP_IMMD) return 1;
10803 if ((aop->type == AOP_PCODE) &&
10804 ((aop->aopu.pcop->type == PO_LITERAL)))
10806 /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10807 * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10814 op_isLitLike (operand *op)
10817 if (aop_isLitLike (AOP(op))) return 1;
10818 if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10819 if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;