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))
2781 /*-----------------------------------------------------------------*/
2782 /* inExcludeList - return 1 if the string is in exclude Reg list */
2783 /*-----------------------------------------------------------------*/
2784 static bool inExcludeList(char *s)
2786 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2789 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2790 if (options.excludeRegs[i] &&
2791 STRCASECMP(options.excludeRegs[i],"none") == 0)
2794 for ( i = 0 ; options.excludeRegs[i]; i++) {
2795 if (options.excludeRegs[i] &&
2796 STRCASECMP(s,options.excludeRegs[i]) == 0)
2803 /*-----------------------------------------------------------------*/
2804 /* genFunction - generated code for function entry */
2805 /*-----------------------------------------------------------------*/
2806 static void genFunction (iCode *ic)
2813 DEBUGpic14_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2815 labelOffset += (max_key+4);
2819 /* create the function header */
2820 pic14_emitcode(";","-----------------------------------------");
2821 pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2822 pic14_emitcode(";","-----------------------------------------");
2824 /* prevent this symbol from being emitted as 'extern' */
2825 pic14_stringInSet(sym->rname, &pic14_localFunctions, 1);
2827 pic14_emitcode("","%s:",sym->rname);
2828 addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2830 ftype = operandType(IC_LEFT(ic));
2832 /* if critical function then turn interrupts off */
2833 if (IFFUNC_ISCRITICAL(ftype))
2834 pic14_emitcode("clr","ea");
2836 /* here we need to generate the equates for the
2837 register bank if required */
2839 if (FUNC_REGBANK(ftype) != rbank) {
2842 rbank = FUNC_REGBANK(ftype);
2843 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2844 if (strcmp(regspic14[i].base,"0") == 0)
2845 pic14_emitcode("","%s = 0x%02x",
2847 8*rbank+regspic14[i].offset);
2849 pic14_emitcode ("","%s = %s + 0x%02x",
2852 8*rbank+regspic14[i].offset);
2857 /* if this is an interrupt service routine */
2859 if (IFFUNC_ISISR(sym->type)) {
2861 /* already done in pic14createInterruptVect() - delete me
2862 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2863 emitpcodeNULLop(POC_NOP);
2864 emitpcodeNULLop(POC_NOP);
2865 emitpcodeNULLop(POC_NOP);
2867 emitpcode(POC_MOVWF, popCopyReg(&pc_wsave));
2868 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2869 emitpcode(POC_CLRF, popCopyReg(&pc_status));
2870 emitpcode(POC_MOVWF, popCopyReg(&pc_ssave));
2871 emitpcode(POC_MOVFW, popCopyReg(&pc_pclath));
2872 emitpcode(POC_MOVWF, popCopyReg(&pc_psave));
2873 emitpcode(POC_CLRF, popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2875 pBlockConvert2ISR(pb);
2876 pic14_hasInterrupt = 1;
2878 if (!inExcludeList("acc"))
2879 pic14_emitcode ("push","acc");
2880 if (!inExcludeList("b"))
2881 pic14_emitcode ("push","b");
2882 if (!inExcludeList("dpl"))
2883 pic14_emitcode ("push","dpl");
2884 if (!inExcludeList("dph"))
2885 pic14_emitcode ("push","dph");
2886 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2888 pic14_emitcode ("push", "dpx");
2889 /* Make sure we're using standard DPTR */
2890 pic14_emitcode ("push", "dps");
2891 pic14_emitcode ("mov", "dps, #0x00");
2892 if (options.stack10bit)
2894 /* This ISR could conceivably use DPTR2. Better save it. */
2895 pic14_emitcode ("push", "dpl1");
2896 pic14_emitcode ("push", "dph1");
2897 pic14_emitcode ("push", "dpx1");
2900 /* if this isr has no bank i.e. is going to
2901 run with bank 0 , then we need to save more
2903 if (!FUNC_REGBANK(sym->type)) {
2905 /* if this function does not call any other
2906 function then we can be economical and
2907 save only those registers that are used */
2908 if (! IFFUNC_HASFCALL(sym->type)) {
2911 /* if any registers used */
2912 if (sym->regsUsed) {
2913 /* save the registers used */
2914 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2915 if (bitVectBitValue(sym->regsUsed,i) ||
2916 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2917 pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);
2922 /* this function has a function call cannot
2923 determines register usage so we will have the
2925 saverbank(0,ic,FALSE);
2930 /* if callee-save to be used for this function
2931 then save the registers being used in this function */
2932 if (IFFUNC_CALLEESAVES(sym->type)) {
2935 /* if any registers used */
2936 if (sym->regsUsed) {
2937 /* save the registers used */
2938 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2939 if (bitVectBitValue(sym->regsUsed,i) ||
2940 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2941 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2949 /* set the register bank to the desired value */
2950 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2951 pic14_emitcode("push","psw");
2952 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);
2955 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2957 if (options.useXstack) {
2958 pic14_emitcode("mov","r0,%s",spname);
2959 pic14_emitcode("mov","a,_bp");
2960 pic14_emitcode("movx","@r0,a");
2961 pic14_emitcode("inc","%s",spname);
2965 /* set up the stack */
2966 pic14_emitcode ("push","_bp"); /* save the callers stack */
2968 pic14_emitcode ("mov","_bp,%s",spname);
2971 /* adjust the stack for the function */
2976 werror(W_STACK_OVERFLOW,sym->name);
2978 if (i > 3 && sym->recvSize < 4) {
2980 pic14_emitcode ("mov","a,sp");
2981 pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2982 pic14_emitcode ("mov","sp,a");
2987 pic14_emitcode("inc","sp");
2992 pic14_emitcode ("mov","a,_spx");
2993 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2994 pic14_emitcode ("mov","_spx,a");
2999 /*-----------------------------------------------------------------*/
3000 /* genEndFunction - generates epilogue for functions */
3001 /*-----------------------------------------------------------------*/
3002 static void genEndFunction (iCode *ic)
3004 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3008 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3010 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3012 pic14_emitcode ("mov","%s,_bp",spname);
3015 /* if use external stack but some variables were
3016 added to the local stack then decrement the
3018 if (options.useXstack && sym->stack) {
3019 pic14_emitcode("mov","a,sp");
3020 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3021 pic14_emitcode("mov","sp,a");
3025 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3026 if (options.useXstack) {
3027 pic14_emitcode("mov","r0,%s",spname);
3028 pic14_emitcode("movx","a,@r0");
3029 pic14_emitcode("mov","_bp,a");
3030 pic14_emitcode("dec","%s",spname);
3034 pic14_emitcode ("pop","_bp");
3038 /* restore the register bank */
3039 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3040 pic14_emitcode ("pop","psw");
3042 if (IFFUNC_ISISR(sym->type)) {
3044 /* now we need to restore the registers */
3045 /* if this isr has no bank i.e. is going to
3046 run with bank 0 , then we need to save more
3048 if (!FUNC_REGBANK(sym->type)) {
3050 /* if this function does not call any other
3051 function then we can be economical and
3052 save only those registers that are used */
3053 if (! IFFUNC_HASFCALL(sym->type)) {
3056 /* if any registers used */
3057 if (sym->regsUsed) {
3058 /* save the registers used */
3059 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3060 if (bitVectBitValue(sym->regsUsed,i) ||
3061 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3062 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3067 /* this function has a function call cannot
3068 determines register usage so we will have the
3070 unsaverbank(0,ic,FALSE);
3074 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3076 if (options.stack10bit)
3078 pic14_emitcode ("pop", "dpx1");
3079 pic14_emitcode ("pop", "dph1");
3080 pic14_emitcode ("pop", "dpl1");
3082 pic14_emitcode ("pop", "dps");
3083 pic14_emitcode ("pop", "dpx");
3085 if (!inExcludeList("dph"))
3086 pic14_emitcode ("pop","dph");
3087 if (!inExcludeList("dpl"))
3088 pic14_emitcode ("pop","dpl");
3089 if (!inExcludeList("b"))
3090 pic14_emitcode ("pop","b");
3091 if (!inExcludeList("acc"))
3092 pic14_emitcode ("pop","acc");
3094 if (IFFUNC_ISCRITICAL(sym->type))
3095 pic14_emitcode("setb","ea");
3098 /* if debug then send end of function */
3099 /* if (options.debug && currFunc) { */
3101 debugFile->writeEndFunction (currFunc, ic, 1);
3104 pic14_emitcode ("reti","");
3105 emitpcode(POC_MOVFW, popCopyReg(&pc_psave));
3106 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
3107 emitpcode(POC_CLRF, popCopyReg(&pc_status));
3108 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3109 emitpcode(POC_MOVWF, popCopyReg(&pc_status));
3110 emitpcode(POC_SWAPF, popCopyReg(&pc_wsave));
3111 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3112 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3113 emitpcodeNULLop(POC_RETFIE);
3116 if (IFFUNC_ISCRITICAL(sym->type))
3117 pic14_emitcode("setb","ea");
3119 if (IFFUNC_CALLEESAVES(sym->type)) {
3122 /* if any registers used */
3123 if (sym->regsUsed) {
3124 /* save the registers used */
3125 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3126 if (bitVectBitValue(sym->regsUsed,i) ||
3127 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3128 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3134 /* if debug then send end of function */
3136 debugFile->writeEndFunction (currFunc, ic, 1);
3139 pic14_emitcode ("return","");
3140 emitpcodeNULLop(POC_RETURN);
3142 /* Mark the end of a function */
3143 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3148 /*-----------------------------------------------------------------*/
3149 /* genRet - generate code for return statement */
3150 /*-----------------------------------------------------------------*/
3151 static void genRet (iCode *ic)
3153 int size,offset = 0;
3157 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3158 /* if we have no return value then
3159 just generate the "ret" */
3163 /* we have something to return then
3164 move the return value into place */
3165 aopOp(IC_LEFT(ic),ic,FALSE);
3166 size = AOP_SIZE(IC_LEFT(ic));
3168 for (offset = 0; offset < size; offset++)
3170 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
3173 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3176 /* generate a jump to the return label
3177 if the next is not the return statement */
3178 if (!(ic->next && ic->next->op == LABEL &&
3179 IC_LABEL(ic->next) == returnLabel)) {
3181 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3186 /*-----------------------------------------------------------------*/
3187 /* genLabel - generates a label */
3188 /*-----------------------------------------------------------------*/
3189 static void genLabel (iCode *ic)
3193 /* special case never generate */
3194 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3195 if (IC_LABEL(ic) == entryLabel)
3198 emitpLabel(IC_LABEL(ic)->key);
3199 pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3202 /*-----------------------------------------------------------------*/
3203 /* genGoto - generates a goto */
3204 /*-----------------------------------------------------------------*/
3206 static void genGoto (iCode *ic)
3210 emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3211 pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3215 /*-----------------------------------------------------------------*/
3216 /* genMultbits :- multiplication of bits */
3217 /*-----------------------------------------------------------------*/
3218 static void genMultbits (operand *left,
3223 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3225 if(!pic14_sameRegs(AOP(result),AOP(right)))
3226 emitpcode(POC_BSF, popGet(AOP(result),0));
3228 emitpcode(POC_BTFSC,popGet(AOP(right),0));
3229 emitpcode(POC_BTFSS,popGet(AOP(left),0));
3230 emitpcode(POC_BCF, popGet(AOP(result),0));
3235 /*-----------------------------------------------------------------*/
3236 /* genMultOneByte : 8 bit multiplication & division */
3237 /*-----------------------------------------------------------------*/
3238 static void genMultOneByte (operand *left,
3242 char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
3250 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3251 DEBUGpic14_AopType(__LINE__,left,right,result);
3252 DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3254 /* (if two literals, the value is computed before) */
3255 /* if one literal, literal on the right */
3256 if (AOP_TYPE(left) == AOP_LIT){
3262 assert (AOP_SIZE(left) == AOP_SIZE(right));
3264 size = min(AOP_SIZE(result),AOP_SIZE(left));
3265 offset = Gstack_base_addr - (2*size - 1);
3267 /* pass right operand as argument */
3268 for (i=0; i < size; i++)
3270 mov2w (AOP(right), i);
3271 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3274 /* pass left operand as argument */
3275 for (i=0; i < size; i++)
3277 mov2w (AOP(left), i);
3278 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3280 assert (offset == Gstack_base_addr);
3282 /* call library routine */
3283 assert (size > 0 && size <= 4);
3284 call_libraryfunc (func[size]);
3287 movwf (AOP(result), size-1);
3288 for (i=0; i < size - 1; i++)
3290 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
3291 movwf (AOP(result), size - 2 - i);
3294 /* now (zero-/sign) extend the result to its size */
3295 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
3298 /*-----------------------------------------------------------------*/
3299 /* genMult - generates code for multiplication */
3300 /*-----------------------------------------------------------------*/
3301 static void genMult (iCode *ic)
3303 operand *left = IC_LEFT(ic);
3304 operand *right = IC_RIGHT(ic);
3305 operand *result= IC_RESULT(ic);
3309 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3310 /* assign the amsops */
3311 aopOp (left,ic,FALSE);
3312 aopOp (right,ic,FALSE);
3313 aopOp (result,ic,TRUE);
3315 DEBUGpic14_AopType(__LINE__,left,right,result);
3317 /* special cases first */
3319 if (AOP_TYPE(left) == AOP_CRY &&
3320 AOP_TYPE(right)== AOP_CRY) {
3321 genMultbits(left,right,result);
3325 /* if both are of size == 1 */
3326 if (AOP_SIZE(left) == 1 &&
3327 AOP_SIZE(right) == 1 ) {
3328 genMultOneByte(left,right,result);
3332 /* should have been converted to function call */
3336 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3337 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3338 freeAsmop(result,NULL,ic,TRUE);
3341 /*-----------------------------------------------------------------*/
3342 /* genDivbits :- division of bits */
3343 /*-----------------------------------------------------------------*/
3344 static void genDivbits (operand *left,
3353 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3354 /* the result must be bit */
3355 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3356 l = aopGet(AOP(left),0,FALSE,FALSE);
3360 pic14_emitcode("div","ab");
3361 pic14_emitcode("rrc","a");
3362 aopPut(AOP(result),"c",0);
3365 /*-----------------------------------------------------------------*/
3366 /* genDivOneByte : 8 bit division */
3367 /*-----------------------------------------------------------------*/
3368 static void genDivOneByte (operand *left,
3376 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3378 assert (AOP_SIZE(right) == 1);
3379 assert (AOP_SIZE(left) == 1);
3381 size = min(AOP_SIZE(result),AOP_SIZE(left));
3382 sign = !(SPEC_USIGN(operandType(left))
3383 && SPEC_USIGN(operandType(right)));
3385 if (AOP_TYPE(right) == AOP_LIT)
3387 /* XXX: might add specialized code */
3392 /* unsigned division */
3394 mov2w(AOP(right),0);
3395 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3397 call_libraryfunc("__divuchar");
3398 movwf(AOP(result),0);
3403 temp = popGetTempReg();
3404 lbl = newiTempLabel(NULL);
3406 /* XXX: improve this naive approach:
3407 [result] = [a] / [b]
3408 ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
3412 movwf temp // temp <-- left
3413 movf right,W // W <-- right
3417 subwf temp,F // temp <-- temp - W
3418 skipNC // subwf clears CARRY (i.e. sets BORROW) if temp < W
3420 decf result // we just subtract once too often
3423 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3424 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
3427 emitpcode(POC_MOVWF, temp);
3428 mov2w(AOP(right),0);
3429 emitpcode(POC_CLRF, popGet(AOP(result),0));
3431 emitpLabel(lbl->key);
3432 emitpcode(POC_INCF, popGet(AOP(result),0));
3433 emitpcode(POC_SUBWF, temp);
3435 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3436 emitpcode(POC_DECF, popGet(AOP(result),0));
3441 /* signed division */
3442 mov2w(AOP(right),0);
3443 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3445 call_libraryfunc("__divschar");
3446 movwf(AOP(result),0);
3449 /* now performed the signed/unsigned division -- extend result */
3450 addSign(result, 1, sign);
3453 /*-----------------------------------------------------------------*/
3454 /* genDiv - generates code for division */
3455 /*-----------------------------------------------------------------*/
3456 static void genDiv (iCode *ic)
3458 operand *left = IC_LEFT(ic);
3459 operand *right = IC_RIGHT(ic);
3460 operand *result= IC_RESULT(ic);
3463 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3464 /* assign the amsops */
3465 aopOp (left,ic,FALSE);
3466 aopOp (right,ic,FALSE);
3467 aopOp (result,ic,TRUE);
3469 /* special cases first */
3471 if (AOP_TYPE(left) == AOP_CRY &&
3472 AOP_TYPE(right)== AOP_CRY) {
3473 genDivbits(left,right,result);
3477 /* if both are of size == 1 */
3478 if (AOP_SIZE(left) == 1 &&
3479 AOP_SIZE(right) == 1 ) {
3480 genDivOneByte(left,right,result);
3484 /* should have been converted to function call */
3487 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3488 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3489 freeAsmop(result,NULL,ic,TRUE);
3492 /*-----------------------------------------------------------------*/
3493 /* genModOneByte : 8 bit modulus */
3494 /*-----------------------------------------------------------------*/
3495 static void genModOneByte (operand *left,
3503 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3505 assert (AOP_SIZE(right) == 1);
3506 assert (AOP_SIZE(left) == 1);
3508 size = min(AOP_SIZE(result),AOP_SIZE(left));
3509 sign = !(SPEC_USIGN(operandType(left))
3510 && SPEC_USIGN(operandType(right)));
3512 if (AOP_TYPE(right) == AOP_LIT)
3514 /* XXX: might add specialized code */
3519 /* unsigned division */
3521 mov2w(AOP(right),0);
3522 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3524 call_libraryfunc("__moduchar");
3525 movwf(AOP(result),0);
3530 lbl = newiTempLabel(NULL);
3532 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3534 /* XXX: improve this naive approach:
3535 [result] = [a] % [b]
3536 ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3540 movwf result // result <-- left
3541 movf right,W // W <-- right
3543 subwf result,F // result <-- result - W
3544 skipNC // subwf clears CARRY (i.e. sets BORROW) if result < W
3546 addwf result, F // we just subtract once too often
3549 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3550 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3552 if (!pic14_sameRegs(AOP(left), AOP(result)))
3555 emitpcode(POC_MOVWF, popGet(AOP(result),0));
3557 mov2w(AOP(right),0);
3559 emitpLabel(lbl->key);
3560 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3562 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3563 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3568 /* signed division */
3569 mov2w(AOP(right),0);
3570 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3572 call_libraryfunc("__modschar");
3573 movwf(AOP(result),0);
3576 /* now we performed the signed/unsigned modulus -- extend result */
3577 addSign(result, 1, sign);
3580 /*-----------------------------------------------------------------*/
3581 /* genMod - generates code for division */
3582 /*-----------------------------------------------------------------*/
3583 static void genMod (iCode *ic)
3585 operand *left = IC_LEFT(ic);
3586 operand *right = IC_RIGHT(ic);
3587 operand *result= IC_RESULT(ic);
3590 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3591 /* assign the amsops */
3592 aopOp (left,ic,FALSE);
3593 aopOp (right,ic,FALSE);
3594 aopOp (result,ic,TRUE);
3596 /* if both are of size == 1 */
3597 if (AOP_SIZE(left) == 1 &&
3598 AOP_SIZE(right) == 1 ) {
3599 genModOneByte(left,right,result);
3603 /* should have been converted to function call */
3607 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3608 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3609 freeAsmop(result,NULL,ic,TRUE);
3612 /*-----------------------------------------------------------------*/
3613 /* genIfxJump :- will create a jump depending on the ifx */
3614 /*-----------------------------------------------------------------*/
3616 note: May need to add parameter to indicate when a variable is in bit space.
3618 static void genIfxJump (iCode *ic, char *jval)
3622 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3623 /* if true label then we jump if condition
3625 if ( IC_TRUE(ic) ) {
3627 if(strcmp(jval,"a") == 0)
3629 else if (strcmp(jval,"c") == 0)
3632 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3633 emitpcode(POC_BTFSC, newpCodeOpBit(jval,-1,1));
3636 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3637 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3641 /* false label is present */
3642 if(strcmp(jval,"a") == 0)
3644 else if (strcmp(jval,"c") == 0)
3647 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3648 emitpcode(POC_BTFSS, newpCodeOpBit(jval,-1,1));
3651 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3652 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3657 /* mark the icode as generated */
3662 /*-----------------------------------------------------------------*/
3664 /*-----------------------------------------------------------------*/
3665 static void genSkip(iCode *ifx,int status_bit)
3671 if ( IC_TRUE(ifx) ) {
3672 switch(status_bit) {
3687 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3688 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3692 switch(status_bit) {
3706 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3707 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3714 /*-----------------------------------------------------------------*/
3716 /*-----------------------------------------------------------------*/
3717 static void genSkipc(resolvedIfx *rifx)
3728 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3729 emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3730 rifx->generated = 1;
3734 /*-----------------------------------------------------------------*/
3736 /*-----------------------------------------------------------------*/
3737 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3743 if( (rifx->condition ^ invert_condition) & 1)
3748 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3749 rifx->generated = 1;
3754 /*-----------------------------------------------------------------*/
3756 /*-----------------------------------------------------------------*/
3757 static void genSkipz(iCode *ifx, int condition)
3760 assert (ifx != NULL);
3768 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3770 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3773 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3775 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3781 /*-----------------------------------------------------------------*/
3783 /*-----------------------------------------------------------------*/
3784 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3791 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3793 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3796 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3797 rifx->generated = 1;
3802 /*-----------------------------------------------------------------*/
3803 /* genChkZeroes :- greater or less than comparison */
3804 /* For each byte in a literal that is zero, inclusive or the */
3805 /* the corresponding byte in the operand with W */
3806 /* returns true if any of the bytes are zero */
3807 /*-----------------------------------------------------------------*/
3808 static int genChkZeroes(operand *op, int lit, int size)
3815 i = (lit >> (size*8)) & 0xff;
3819 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3821 emitpcode(POC_IORFW, popGet(AOP(op),size));
3831 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3832 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
3833 #define DEBUGpc emitpComment
3835 /*-----------------------------------------------------------------*/
3836 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
3837 /* aop (if it's NOT a literal) or from lit (if */
3838 /* aop is a literal) */
3839 /*-----------------------------------------------------------------*/
3840 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3841 if (aop->type == AOP_LIT) {
3842 emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3844 emitpcode (POC_MOVFW, popGet (aop, offset));
3848 /* genCmp performs a left < right comparison, stores
3849 * the outcome in result (if != NULL) and generates
3850 * control flow code for the ifx (if != NULL).
3852 * This version leaves in sequences like
3853 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3854 * which should be optmized by the peephole
3855 * optimizer - RN 2005-01-01 */
3856 static void genCmp (operand *left,operand *right,
3857 operand *result, iCode *ifx, int sign)
3867 int invert_result = 0;
3871 assert (AOP_SIZE(left) == AOP_SIZE(right));
3872 assert (left && right);
3874 size = AOP_SIZE(right) - 1;
3875 mask = (0x100UL << (size*8)) - 1;
3876 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3881 resolveIfx (&rIfx, ifx);
3883 /**********************************************************************
3884 * handle bits - bit compares are promoted to int compares seemingly! *
3885 **********************************************************************/
3887 // THIS IS COMPLETELY UNTESTED!
3888 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3889 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3890 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3891 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3894 // 1 < {0,1} is false --> clear C by skipping the next instruction
3895 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3896 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3897 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3898 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3899 emitCLRC; // only skipped for left=0 && right=1
3901 goto correct_result_in_carry;
3905 /*************************************************
3906 * make sure that left is register (or the like) *
3907 *************************************************/
3908 if (!isAOP_REGlike(left)) {
3909 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
3910 assert (isAOP_LIT(left));
3911 assert (isAOP_REGlike(right));
3912 // swap left and right
3913 // left < right <==> right > left <==> (right >= left + 1)
3914 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3916 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
3917 // MAXVALUE < right? always false
3918 if (performedLt) emitCLRC; else emitSETC;
3919 goto correct_result_in_carry;
3922 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
3923 // that's why we handled it above.
3930 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
3931 } else if (isAOP_LIT(right)) {
3932 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3935 assert (isAOP_REGlike(left)); // left must be register or the like
3936 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
3938 /*************************************************
3939 * special cases go here *
3940 *************************************************/
3942 if (isAOP_LIT(right)) {
3944 // unsigned comparison to a literal
3945 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
3947 // unsigned left < 0? always false
3948 if (performedLt) emitCLRC; else emitSETC;
3949 goto correct_result_in_carry;
3952 // signed comparison to a literal
3953 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
3954 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
3955 // signed left < 0x80000000? always false
3956 if (performedLt) emitCLRC; else emitSETC;
3957 goto correct_result_in_carry;
3958 } else if (lit == 0) {
3959 // compare left < 0; set CARRY if SIGNBIT(left) is set
3960 if (performedLt) emitSETC; else emitCLRC;
3961 emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
3962 if (performedLt) emitCLRC; else emitSETC;
3963 goto correct_result_in_carry;
3966 } // right is literal
3968 /*************************************************
3969 * perform a general case comparison *
3970 * make sure we get CARRY==1 <==> left >= right *
3971 *************************************************/
3972 // compare most significant bytes
3973 //DEBUGpc ("comparing bytes at offset %d", size);
3975 // unsigned comparison
3976 pic14_mov2w_regOrLit (AOP(right), lit, size);
3977 emitpcode (POC_SUBFW, popGet (AOP(left), size));
3979 // signed comparison
3980 // (add 2^n to both operands then perform an unsigned comparison)
3981 if (isAOP_LIT(right)) {
3982 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
3983 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
3985 if (litbyte == 0x80) {
3986 // left >= 0x80 -- always true, but more bytes to come
3987 mov2w (AOP(left), size);
3988 emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
3991 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
3992 mov2w (AOP(left), size);
3993 emitpcode (POC_ADDLW, popGetLit (0x80));
3994 emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
3997 pCodeOp *pctemp = popGetTempReg();
3998 mov2w (AOP(left), size);
3999 emitpcode (POC_ADDLW, popGetLit (0x80));
4000 emitpcode (POC_MOVWF, pctemp);
4001 mov2w (AOP(right), size);
4002 emitpcode (POC_ADDLW, popGetLit (0x80));
4003 emitpcode (POC_SUBFW, pctemp);
4004 popReleaseTempReg(pctemp);
4008 // compare remaining bytes (treat as unsigned case from above)
4009 templbl = newiTempLabel ( NULL );
4012 //DEBUGpc ("comparing bytes at offset %d", offs);
4014 emitpcode (POC_GOTO, popGetLabel (templbl->key));
4015 pic14_mov2w_regOrLit (AOP(right), lit, offs);
4016 emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4018 emitpLabel (templbl->key);
4019 goto result_in_carry;
4023 /****************************************************
4024 * now CARRY contains the result of the comparison: *
4025 * SUBWF sets CARRY iff *
4026 * F-W >= 0 <==> F >= W <==> !(F < W) *
4027 * (F=left, W=right) *
4028 ****************************************************/
4032 // value will be used in the following genSkipc()
4033 rIfx.condition ^= 1;
4036 correct_result_in_carry:
4038 // assign result to variable (if neccessary)
4039 if (result && AOP_TYPE(result) != AOP_CRY) {
4040 //DEBUGpc ("assign result");
4041 size = AOP_SIZE(result);
4043 emitpcode (POC_CLRF, popGet (AOP(result), size));
4045 if (invert_result) {
4047 emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4049 emitpcode (POC_RLF, popGet (AOP(result), 0));
4053 // perform conditional jump
4055 //DEBUGpc ("generate control flow");
4063 /* OLD VERSION -- BUGGY, DO NOT USE */
4065 /*-----------------------------------------------------------------*/
4066 /* genCmp :- greater or less than comparison */
4067 /*-----------------------------------------------------------------*/
4068 static void genCmp (operand *left,operand *right,
4069 operand *result, iCode *ifx, int sign)
4071 int size; //, offset = 0 ;
4072 unsigned long lit = 0L,i = 0;
4073 resolvedIfx rFalseIfx;
4074 // resolvedIfx rTrueIfx;
4078 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4081 DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4082 DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4086 resolveIfx(&rFalseIfx,ifx);
4087 truelbl = newiTempLabel(NULL);
4088 size = max(AOP_SIZE(left),AOP_SIZE(right));
4090 DEBUGpic14_AopType(__LINE__,left,right,result);
4094 /* if literal is on the right then swap with left */
4095 if ((AOP_TYPE(right) == AOP_LIT)) {
4096 operand *tmp = right ;
4097 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4098 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4101 lit = (lit - 1) & mask;
4104 rFalseIfx.condition ^= 1;
4107 } else if ((AOP_TYPE(left) == AOP_LIT)) {
4108 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4112 //if(IC_TRUE(ifx) == NULL)
4113 /* if left & right are bit variables */
4114 if (AOP_TYPE(left) == AOP_CRY &&
4115 AOP_TYPE(right) == AOP_CRY ) {
4116 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4117 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4119 /* subtract right from left if at the
4120 end the carry flag is set then we know that
4121 left is greater than right */
4123 symbol *lbl = newiTempLabel(NULL);
4126 if(AOP_TYPE(right) == AOP_LIT) {
4128 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4130 DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4137 genSkipCond(&rFalseIfx,left,size-1,7);
4139 /* no need to compare to 0...*/
4140 /* NOTE: this is a de-generate compare that most certainly
4141 * creates some dead code. */
4142 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4144 if(ifx) ifx->generated = 1;
4151 //i = (lit >> (size*8)) & 0xff;
4152 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4154 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4156 i = ((0-lit) & 0xff);
4159 /* lit is 0x7f, all signed chars are less than
4160 * this except for 0x7f itself */
4161 emitpcode(POC_XORLW, popGetLit(0x7f));
4162 genSkipz2(&rFalseIfx,0);
4164 emitpcode(POC_ADDLW, popGetLit(0x80));
4165 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4166 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4171 genSkipz2(&rFalseIfx,1);
4173 emitpcode(POC_ADDLW, popGetLit(i));
4174 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4178 if(ifx) ifx->generated = 1;
4182 /* chars are out of the way. now do ints and longs */
4185 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4192 genSkipCond(&rFalseIfx,left,size,7);
4193 if(ifx) ifx->generated = 1;
4198 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4200 //rFalseIfx.condition ^= 1;
4201 //genSkipCond(&rFalseIfx,left,size,7);
4202 //rFalseIfx.condition ^= 1;
4204 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4205 if(rFalseIfx.condition)
4206 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4208 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4210 emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4211 emitpcode(POC_ADDFW, popGet(AOP(left),0));
4212 emitpcode(POC_MOVFW, popGet(AOP(left),1));
4215 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4217 if(rFalseIfx.condition) {
4219 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4225 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4226 emitpLabel(truelbl->key);
4227 if(ifx) ifx->generated = 1;
4234 if( (lit & 0xff) == 0) {
4235 /* lower byte is zero */
4236 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4237 i = ((lit >> 8) & 0xff) ^0x80;
4238 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4239 emitpcode(POC_ADDLW, popGetLit( 0x80));
4240 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4241 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4244 if(ifx) ifx->generated = 1;
4249 /* Special cases for signed longs */
4250 if( (lit & 0xffffff) == 0) {
4251 /* lower byte is zero */
4252 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4253 i = ((lit >> 8*3) & 0xff) ^0x80;
4254 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4255 emitpcode(POC_ADDLW, popGetLit( 0x80));
4256 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4257 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4260 if(ifx) ifx->generated = 1;
4268 if(lit & (0x80 << (size*8))) {
4269 /* lit is negative */
4270 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4272 //genSkipCond(&rFalseIfx,left,size,7);
4274 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4276 if(rFalseIfx.condition)
4277 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4279 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4283 /* lit is positive */
4284 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4285 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4286 if(rFalseIfx.condition)
4287 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4289 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4293 /* There are no more special cases, so perform a general compare */
4295 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4296 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4300 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4302 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4304 //rFalseIfx.condition ^= 1;
4305 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4307 emitpLabel(truelbl->key);
4309 if(ifx) ifx->generated = 1;
4316 /* sign is out of the way. So now do an unsigned compare */
4317 DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4320 /* General case - compare to an unsigned literal on the right.*/
4322 i = (lit >> (size*8)) & 0xff;
4323 emitpcode(POC_MOVLW, popGetLit(i));
4324 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4326 i = (lit >> (size*8)) & 0xff;
4329 emitpcode(POC_MOVLW, popGetLit(i));
4331 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4333 /* this byte of the lit is zero,
4334 *if it's not the last then OR in the variable */
4336 emitpcode(POC_IORFW, popGet(AOP(left),size));
4341 emitpLabel(lbl->key);
4342 //if(emitFinalCheck)
4343 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4345 emitpLabel(truelbl->key);
4347 if(ifx) ifx->generated = 1;
4354 if(AOP_TYPE(left) == AOP_LIT) {
4355 //symbol *lbl = newiTempLabel(NULL);
4357 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4360 DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4363 if((lit == 0) && (sign == 0)){
4366 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4368 emitpcode(POC_IORFW, popGet(AOP(right),--size));
4370 genSkipz2(&rFalseIfx,0);
4371 if(ifx) ifx->generated = 1;
4378 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4379 /* degenerate compare can never be true */
4380 if(rFalseIfx.condition == 0)
4381 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4383 if(ifx) ifx->generated = 1;
4388 /* signed comparisons to a literal byte */
4390 int lp1 = (lit+1) & 0xff;
4392 DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4395 rFalseIfx.condition ^= 1;
4396 genSkipCond(&rFalseIfx,right,0,7);
4399 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4400 emitpcode(POC_XORLW, popGetLit(0x7f));
4401 genSkipz2(&rFalseIfx,1);
4404 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4405 emitpcode(POC_ADDLW, popGetLit(0x80));
4406 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4407 rFalseIfx.condition ^= 1;
4408 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4411 if(ifx) ifx->generated = 1;
4413 /* unsigned comparisons to a literal byte */
4415 switch(lit & 0xff ) {
4417 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4418 genSkipz2(&rFalseIfx,0);
4419 if(ifx) ifx->generated = 1;
4422 genSkipCond(&rFalseIfx,right,0,7);
4423 if(ifx) ifx->generated = 1;
4427 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4428 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4429 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4430 rFalseIfx.condition ^= 1;
4431 if (AOP_TYPE(result) == AOP_CRY) {
4432 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4433 if(ifx) ifx->generated = 1;
4435 DEBUGpic14_emitcode ("; ***","%s %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4436 emitpcode(POC_CLRF, popGet(AOP(result),0));
4437 emitpcode(POC_RLF, popGet(AOP(result),0));
4438 emitpcode(POC_MOVLW, popGetLit(0x01));
4439 emitpcode(POC_XORWF, popGet(AOP(result),0));
4450 /* Size is greater than 1 */
4458 /* this means lit = 0xffffffff, or -1 */
4461 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4462 rFalseIfx.condition ^= 1;
4463 genSkipCond(&rFalseIfx,right,size,7);
4464 if(ifx) ifx->generated = 1;
4471 if(rFalseIfx.condition) {
4472 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4473 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4476 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4478 emitpcode(POC_IORFW, popGet(AOP(right),size));
4482 if(rFalseIfx.condition) {
4483 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4484 emitpLabel(truelbl->key);
4486 rFalseIfx.condition ^= 1;
4487 genSkipCond(&rFalseIfx,right,s,7);
4490 if(ifx) ifx->generated = 1;
4494 if((size == 1) && (0 == (lp1&0xff))) {
4495 /* lower byte of signed word is zero */
4496 DEBUGpic14_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
4497 i = ((lp1 >> 8) & 0xff) ^0x80;
4498 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4499 emitpcode(POC_ADDLW, popGetLit( 0x80));
4500 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4501 rFalseIfx.condition ^= 1;
4502 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4505 if(ifx) ifx->generated = 1;
4509 if(lit & (0x80 << (size*8))) {
4510 /* Lit is less than zero */
4511 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
4512 //rFalseIfx.condition ^= 1;
4513 //genSkipCond(&rFalseIfx,left,size,7);
4514 //rFalseIfx.condition ^= 1;
4515 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4516 //emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4518 if(rFalseIfx.condition)
4519 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4521 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4525 /* Lit is greater than or equal to zero */
4526 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
4527 //rFalseIfx.condition ^= 1;
4528 //genSkipCond(&rFalseIfx,right,size,7);
4529 //rFalseIfx.condition ^= 1;
4531 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4532 //emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4534 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4535 if(rFalseIfx.condition)
4536 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4538 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4543 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4544 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4548 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4550 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4552 rFalseIfx.condition ^= 1;
4553 //rFalseIfx.condition = 1;
4554 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4556 emitpLabel(truelbl->key);
4558 if(ifx) ifx->generated = 1;
4563 /* compare word or long to an unsigned literal on the right.*/
4568 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4571 break; /* handled above */
4574 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4576 emitpcode(POC_IORFW, popGet(AOP(right),size));
4577 genSkipz2(&rFalseIfx,0);
4581 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4583 emitpcode(POC_IORFW, popGet(AOP(right),size));
4586 if(rFalseIfx.condition)
4587 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4589 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4592 emitpcode(POC_MOVLW, popGetLit(lit+1));
4593 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4595 rFalseIfx.condition ^= 1;
4596 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4599 emitpLabel(truelbl->key);
4601 if(ifx) ifx->generated = 1;
4607 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4608 i = (lit >> (size*8)) & 0xff;
4610 emitpcode(POC_MOVLW, popGetLit(i));
4611 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4614 i = (lit >> (size*8)) & 0xff;
4617 emitpcode(POC_MOVLW, popGetLit(i));
4619 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4621 /* this byte of the lit is zero,
4622 *if it's not the last then OR in the variable */
4624 emitpcode(POC_IORFW, popGet(AOP(right),size));
4629 emitpLabel(lbl->key);
4631 rFalseIfx.condition ^= 1;
4632 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4636 emitpLabel(truelbl->key);
4637 if(ifx) ifx->generated = 1;
4641 /* Compare two variables */
4643 DEBUGpic14_emitcode(";sign","%d",sign);
4647 /* Sigh. thus sucks... */
4649 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4650 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4651 emitpcode(POC_MOVLW, popGetLit(0x80));
4652 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4653 emitpcode(POC_XORFW, popGet(AOP(right),size));
4654 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4656 /* Signed char comparison */
4657 /* Special thanks to Nikolai Golovchenko for this snippet */
4658 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4659 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4660 emitpcode(POC_RRFW, popGet(AOP(left),0)); /* could be any register */
4661 emitpcode(POC_XORFW, popGet(AOP(left),0));
4662 emitpcode(POC_XORFW, popGet(AOP(right),0));
4663 emitpcode(POC_ADDLW, popGetLit(0x80));
4665 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4666 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4668 if(ifx) ifx->generated = 1;
4674 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4675 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4679 /* The rest of the bytes of a multi-byte compare */
4683 emitpcode(POC_GOTO, popGetLabel(lbl->key));
4686 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4687 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4692 emitpLabel(lbl->key);
4694 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4695 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
4696 (AOP_TYPE(result) == AOP_REG)) {
4697 emitpcode(POC_CLRF, popGet(AOP(result),0));
4698 emitpcode(POC_RLF, popGet(AOP(result),0));
4700 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4702 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4703 if(ifx) ifx->generated = 1;
4710 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4711 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4712 pic14_outBitC(result);
4714 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4715 /* if the result is used in the next
4716 ifx conditional branch then generate
4717 code a little differently */
4719 genIfxJump (ifx,"c");
4721 pic14_outBitC(result);
4722 /* leave the result in acc */
4728 /*-----------------------------------------------------------------*/
4729 /* genCmpGt :- greater than comparison */
4730 /*-----------------------------------------------------------------*/
4731 static void genCmpGt (iCode *ic, iCode *ifx)
4733 operand *left, *right, *result;
4734 sym_link *letype , *retype;
4738 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4740 right= IC_RIGHT(ic);
4741 result = IC_RESULT(ic);
4743 letype = getSpec(operandType(left));
4744 retype =getSpec(operandType(right));
4745 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4746 /* assign the amsops */
4747 aopOp (left,ic,FALSE);
4748 aopOp (right,ic,FALSE);
4749 aopOp (result,ic,TRUE);
4751 genCmp(right, left, result, ifx, sign);
4753 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4754 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4755 freeAsmop(result,NULL,ic,TRUE);
4758 /*-----------------------------------------------------------------*/
4759 /* genCmpLt - less than comparisons */
4760 /*-----------------------------------------------------------------*/
4761 static void genCmpLt (iCode *ic, iCode *ifx)
4763 operand *left, *right, *result;
4764 sym_link *letype , *retype;
4768 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4770 right= IC_RIGHT(ic);
4771 result = IC_RESULT(ic);
4773 letype = getSpec(operandType(left));
4774 retype =getSpec(operandType(right));
4775 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4777 /* assign the amsops */
4778 aopOp (left,ic,FALSE);
4779 aopOp (right,ic,FALSE);
4780 aopOp (result,ic,TRUE);
4782 genCmp(left, right, result, ifx, sign);
4784 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4785 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4786 freeAsmop(result,NULL,ic,TRUE);
4790 /*-----------------------------------------------------------------*/
4791 /* genc16bit2lit - compare a 16 bit value to a literal */
4792 /*-----------------------------------------------------------------*/
4793 static void genc16bit2lit(operand *op, int lit, int offset)
4798 DEBUGpic14_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
4799 if( (lit&0xff) == 0)
4804 switch( BYTEofLONG(lit,i)) {
4806 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4809 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4812 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4815 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4816 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4821 switch( BYTEofLONG(lit,i)) {
4823 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4827 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4831 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4834 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4836 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4844 /*-----------------------------------------------------------------*/
4845 /* gencjneshort - compare and jump if not equal */
4846 /*-----------------------------------------------------------------*/
4847 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4849 int size = min(AOP_SIZE(left),AOP_SIZE(right));
4854 //unsigned long lit = 0L;
4856 if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4857 emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4860 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4861 DEBUGpic14_AopType(__LINE__,left,right,result);
4863 assert (!pic14_sameRegs (AOP(left), AOP(result)));
4864 assert (!pic14_sameRegs (AOP(right), AOP(result)));
4865 if (AOP_SIZE(result)) {
4866 for (offset = 0; offset < AOP_SIZE(result); offset++)
4867 emitpcode (POC_CLRF, popGet (AOP(result), offset));
4870 assert (AOP_SIZE(left) == AOP_SIZE(right));
4871 //resolveIfx(&rIfx,ifx);
4872 lbl = newiTempLabel (NULL);
4875 mov2w (AOP(right),size);
4876 emitpcode (POC_XORFW, popGet (AOP(left), size));
4880 emitpcode (POC_GOTO, popGetLabel (lbl->key));
4883 emitpLabel (lbl->key);
4884 if (AOP_SIZE(result)) {
4886 emitpcode (POC_INCF, popGet (AOP(result), 0));
4889 genSkipz (ifx, NULL != IC_TRUE(ifx));
4896 DEBUGpic14_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
4897 assert (!pic14_sameRegs (AOP(result), AOP(left)));
4898 assert (!pic14_sameRegs (AOP(result), AOP(right)));
4899 for (offset=0; offset < AOP_SIZE(result); offset++)
4901 emitpcode (POC_CLRF, popGet (AOP(result), offset));
4906 /* if the left side is a literal or
4907 if the right is in a pointer register and left
4909 if ((AOP_TYPE(left) == AOP_LIT) ||
4910 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4915 if(AOP_TYPE(right) == AOP_LIT)
4916 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4918 /* if the right side is a literal then anything goes */
4919 if (AOP_TYPE(right) == AOP_LIT &&
4920 AOP_TYPE(left) != AOP_DIR ) {
4923 genc16bit2lit(left, lit, 0);
4925 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4931 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4932 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4934 emitpcode(POC_MOVF,popGet(AOP(left),offset));
4938 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4946 /* if the right side is in a register or in direct space or
4947 if the left is a pointer register & right is not */
4948 else if (AOP_TYPE(right) == AOP_REG ||
4949 AOP_TYPE(right) == AOP_DIR ||
4950 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4951 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4952 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4953 int lbl_key = lbl->key;
4956 DEBUGpic14_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
4957 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
4958 __FUNCTION__,__LINE__);
4962 /* switch(size) { */
4964 /* genc16bit2lit(left, lit, 0); */
4966 /* emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
4972 if((AOP_TYPE(left) == AOP_DIR) &&
4973 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4975 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4976 emitpcode(POC_XORFW,popGet(AOP(right),offset));
4978 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4980 switch (lit & 0xff) {
4982 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4985 emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4986 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4987 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4991 emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4992 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4993 //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4994 emitpcode(POC_GOTO,popGetLabel(lbl_key));
4998 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4999 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5004 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5007 if(AOP_TYPE(result) == AOP_CRY) {
5008 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5013 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5015 /* fix me. probably need to check result size too */
5016 //emitpcode(POC_CLRF,popGet(AOP(result),0));
5021 emitpcode(POC_GOTO,popGetLabel(lbl_key));
5031 } else if(AOP_TYPE(right) == AOP_REG &&
5032 AOP_TYPE(left) != AOP_DIR){
5036 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5037 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5038 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5043 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5048 /* right is a pointer reg need both a & b */
5051 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5053 pic14_emitcode("mov","b,%s",l);
5054 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5055 pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
5060 emitpcode(POC_INCF,popGet(AOP(result),0));
5062 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5064 emitpLabel(lbl->key);
5066 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5075 /*-----------------------------------------------------------------*/
5076 /* gencjne - compare and jump if not equal */
5077 /*-----------------------------------------------------------------*/
5078 static void gencjne(operand *left, operand *right, iCode *ifx)
5080 symbol *tlbl = newiTempLabel(NULL);
5082 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5083 gencjneshort(left, right, lbl);
5085 pic14_emitcode("mov","a,%s",one);
5086 pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5087 pic14_emitcode("","%05d_DS_:",lbl->key+100);
5088 pic14_emitcode("clr","a");
5089 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5091 emitpLabel(lbl->key);
5092 emitpLabel(tlbl->key);
5097 /*-----------------------------------------------------------------*/
5098 /* genCmpEq - generates code for equal to */
5099 /*-----------------------------------------------------------------*/
5100 static void genCmpEq (iCode *ic, iCode *ifx)
5102 operand *left, *right, *result;
5104 symbol *false_label;
5107 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5110 DEBUGpic14_emitcode ("; ifx is non-null","");
5112 DEBUGpic14_emitcode ("; ifx is null","");
5114 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5115 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5116 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5118 DEBUGpic14_AopType(__LINE__,left,right,result);
5120 /* if literal, move literal to right */
5121 if (op_isLitLike (IC_LEFT(ic))) {
5122 operand *tmp = right ;
5128 if (ifx && !IC_TRUE(ifx))
5130 assert (IC_FALSE(ifx));
5131 false_label = IC_FALSE(ifx);
5134 size = min(AOP_SIZE(left),AOP_SIZE(right));
5135 assert(!pic14_sameRegs(AOP(result),AOP(left)));
5136 assert(!pic14_sameRegs(AOP(result),AOP(right)));
5138 /* assume left != right */
5141 for (i=0; i < AOP_SIZE(result); i++)
5143 emitpcode(POC_CLRF, popGet(AOP(result),i));
5147 if (AOP_TYPE(right) == AOP_LIT)
5149 unsigned long lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
5151 size = AOP_SIZE(left);
5152 assert(!op_isLitLike(left));
5157 mov2w(AOP(left), 0);
5158 for (i=1; i < size; i++)
5159 emitpcode(POC_IORFW,popGet(AOP(left),i));
5160 /* now Z is set iff `left == right' */
5162 if (!false_label) false_label = newiTempLabel(NULL);
5163 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5167 for (i=0; i < size; i++)
5170 emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
5171 /* now Z is cleared if `left != right' */
5173 if (!false_label) false_label = newiTempLabel(NULL);
5174 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5181 /* right is no literal */
5184 for (i=0; i < size; i++)
5186 mov2w(AOP(right),i);
5187 emitpcode(POC_XORFW,popGet(AOP(left),i));
5188 /* now Z is cleared if `left != right' */
5190 if (!false_label) false_label = newiTempLabel(NULL);
5191 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5195 /* if we reach here, left == right */
5197 if (AOP_SIZE(result) > 0)
5199 emitpcode(POC_INCF, popGet(AOP(result),0));
5202 if (ifx && IC_TRUE(ifx))
5204 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5207 if (false_label && (!ifx || IC_TRUE(ifx)))
5208 emitpLabel(false_label->key);
5210 if (ifx) ifx->generated = 1;
5212 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5213 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5214 freeAsmop(result,NULL,ic,TRUE);
5217 /*-----------------------------------------------------------------*/
5218 /* ifxForOp - returns the icode containing the ifx for operand */
5219 /*-----------------------------------------------------------------*/
5220 static iCode *ifxForOp ( operand *op, iCode *ic )
5223 /* if true symbol then needs to be assigned */
5224 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5225 if (IS_TRUE_SYMOP(op))
5228 /* if this has register type condition and
5229 the next instruction is ifx with the same operand
5230 and live to of the operand is upto the ifx only then */
5232 ic->next->op == IFX &&
5233 IC_COND(ic->next)->key == op->key &&
5234 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5238 ic->next->op == IFX &&
5239 IC_COND(ic->next)->key == op->key) {
5240 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5244 DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5246 ic->next->op == IFX)
5247 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5250 ic->next->op == IFX &&
5251 IC_COND(ic->next)->key == op->key) {
5252 DEBUGpic14_emitcode ("; "," key is okay");
5253 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5254 OP_SYMBOL(op)->liveTo,
5261 /*-----------------------------------------------------------------*/
5262 /* genAndOp - for && operation */
5263 /*-----------------------------------------------------------------*/
5264 static void genAndOp (iCode *ic)
5266 operand *left,*right, *result;
5270 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5271 /* note here that && operations that are in an
5272 if statement are taken away by backPatchLabels
5273 only those used in arthmetic operations remain */
5274 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5275 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5276 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5278 DEBUGpic14_AopType(__LINE__,left,right,result);
5280 emitpcode(POC_MOVFW,popGet(AOP(left),0));
5281 emitpcode(POC_ANDFW,popGet(AOP(right),0));
5282 emitpcode(POC_MOVWF,popGet(AOP(result),0));
5284 /* if both are bit variables */
5285 /* if (AOP_TYPE(left) == AOP_CRY && */
5286 /* AOP_TYPE(right) == AOP_CRY ) { */
5287 /* pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5288 /* pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5289 /* pic14_outBitC(result); */
5291 /* tlbl = newiTempLabel(NULL); */
5292 /* pic14_toBoolean(left); */
5293 /* pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5294 /* pic14_toBoolean(right); */
5295 /* pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5296 /* pic14_outBitAcc(result); */
5299 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5300 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5301 freeAsmop(result,NULL,ic,TRUE);
5305 /*-----------------------------------------------------------------*/
5306 /* genOrOp - for || operation */
5307 /*-----------------------------------------------------------------*/
5310 modified this code, but it doesn't appear to ever get called
5313 static void genOrOp (iCode *ic)
5315 operand *left,*right, *result;
5319 /* note here that || operations that are in an
5320 if statement are taken away by backPatchLabels
5321 only those used in arthmetic operations remain */
5323 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5324 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5325 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5326 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5328 DEBUGpic14_AopType(__LINE__,left,right,result);
5330 for (i=0; i < AOP_SIZE(result); i++)
5332 emitpcode(POC_CLRF, popGet(AOP(result), i));
5335 tlbl = newiTempLabel(NULL);
5336 pic14_toBoolean(left);
5338 emitpcode(POC_GOTO, popGetLabel(tlbl->key));
5339 pic14_toBoolean(right);
5340 emitpLabel(tlbl->key);
5341 /* here Z is clear IFF `left || right' */
5343 emitpcode(POC_INCF, popGet(AOP(result), 0));
5345 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5346 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5347 freeAsmop(result,NULL,ic,TRUE);
5350 /*-----------------------------------------------------------------*/
5351 /* isLiteralBit - test if lit == 2^n */
5352 /*-----------------------------------------------------------------*/
5353 static int isLiteralBit(unsigned long lit)
5355 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5356 0x100L,0x200L,0x400L,0x800L,
5357 0x1000L,0x2000L,0x4000L,0x8000L,
5358 0x10000L,0x20000L,0x40000L,0x80000L,
5359 0x100000L,0x200000L,0x400000L,0x800000L,
5360 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5361 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5365 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5366 for(idx = 0; idx < 32; idx++)
5372 /*-----------------------------------------------------------------*/
5373 /* continueIfTrue - */
5374 /*-----------------------------------------------------------------*/
5375 static void continueIfTrue (iCode *ic)
5378 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5382 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
5383 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5388 /*-----------------------------------------------------------------*/
5390 /*-----------------------------------------------------------------*/
5391 static void jumpIfTrue (iCode *ic)
5394 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5398 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
5399 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5404 /*-----------------------------------------------------------------*/
5405 /* jmpTrueOrFalse - */
5406 /*-----------------------------------------------------------------*/
5407 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5410 // ugly but optimized by peephole
5411 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5413 symbol *nlbl = newiTempLabel(NULL);
5414 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5415 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5416 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5417 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5420 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5421 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5426 /*-----------------------------------------------------------------*/
5427 /* genAnd - code for and */
5428 /*-----------------------------------------------------------------*/
5429 static void genAnd (iCode *ic, iCode *ifx)
5431 operand *left, *right, *result;
5433 unsigned long lit = 0L;
5438 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5439 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5440 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5441 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5443 resolveIfx(&rIfx,ifx);
5445 /* if left is a literal & right is not then exchange them */
5446 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5447 AOP_NEEDSACC(left)) {
5448 operand *tmp = right ;
5453 /* if result = right then exchange them */
5454 if(pic14_sameRegs(AOP(result),AOP(right))){
5455 operand *tmp = right ;
5460 /* if right is bit then exchange them */
5461 if (AOP_TYPE(right) == AOP_CRY &&
5462 AOP_TYPE(left) != AOP_CRY){
5463 operand *tmp = right ;
5467 if(AOP_TYPE(right) == AOP_LIT)
5468 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5470 size = AOP_SIZE(result);
5472 DEBUGpic14_AopType(__LINE__,left,right,result);
5475 // result = bit & yy;
5476 if (AOP_TYPE(left) == AOP_CRY){
5477 // c = bit & literal;
5478 if(AOP_TYPE(right) == AOP_LIT){
5480 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5483 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5486 if(size && (AOP_TYPE(result) == AOP_CRY)){
5487 pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5490 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5494 pic14_emitcode("clr","c");
5497 if (AOP_TYPE(right) == AOP_CRY){
5499 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5500 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5503 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5505 pic14_emitcode("rrc","a");
5506 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5512 pic14_outBitC(result);
5514 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5515 genIfxJump(ifx, "c");
5519 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5520 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5521 if((AOP_TYPE(right) == AOP_LIT) &&
5522 (AOP_TYPE(result) == AOP_CRY) &&
5523 (AOP_TYPE(left) != AOP_CRY)){
5524 int posbit = isLiteralBit(lit);
5528 //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5531 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5536 while (posbit > 7) {
5540 emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5541 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5542 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5549 symbol *tlbl = newiTempLabel(NULL);
5550 int sizel = AOP_SIZE(left);
5552 pic14_emitcode("setb","c");
5554 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5555 mov2w( AOP(left), offset);
5557 if((posbit = isLiteralBit(bytelit)) != 0) {
5558 emitpcode(rIfx.condition ? POC_BTFSC : POC_BTFSS, // XXX: or the other way round?
5559 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit - 1, 0));
5560 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5563 emitpcode(POC_ANDLW, newpCodeOpLit(bytelit & 0x0ff));
5564 if (rIfx.condition) emitSKPZ;
5567 if(bytelit != 0x0FFL)
5569 pic14_emitcode("anl","a,%s",
5570 aopGet(AOP(right),offset,FALSE,TRUE));
5572 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5575 emitpcode(POC_GOTO, popGetLabel(rIfx.lbl->key));
5581 // bit = left & literal
5583 pic14_emitcode("clr","c");
5584 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5586 // if(left & literal)
5589 jmpTrueOrFalse(ifx, tlbl);
5593 pic14_outBitC(result);
5597 /* if left is same as result */
5598 if(pic14_sameRegs(AOP(result),AOP(left))){
5600 for(;size--; offset++,lit>>=8) {
5601 if(AOP_TYPE(right) == AOP_LIT){
5602 switch(lit & 0xff) {
5604 /* and'ing with 0 has clears the result */
5605 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5608 /* and'ing with 0xff is a nop when the result and left are the same */
5613 int p = my_powof2( (~lit) & 0xff );
5615 /* only one bit is set in the literal, so use a bcf instruction */
5616 emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5619 if(know_W != (int)(lit&0xff))
5620 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5622 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5627 if (AOP_TYPE(left) == AOP_ACC) {
5628 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5630 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5631 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5638 // left & result in different registers
5639 if(AOP_TYPE(result) == AOP_CRY){
5641 // if(size), result in bit
5642 // if(!size && ifx), conditional oper: if(left & right)
5643 symbol *tlbl = newiTempLabel(NULL);
5644 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5646 pic14_emitcode("setb","c");
5648 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5649 pic14_emitcode("anl","a,%s",
5650 aopGet(AOP(left),offset,FALSE,FALSE));
5651 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5656 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5657 pic14_outBitC(result);
5659 jmpTrueOrFalse(ifx, tlbl);
5661 for(;(size--);offset++) {
5663 // result = left & right
5664 if(AOP_TYPE(right) == AOP_LIT){
5665 int t = (lit >> (offset*8)) & 0x0FFL;
5668 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5671 if(AOP_TYPE(left) != AOP_ACC) {
5672 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5674 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5677 if(AOP_TYPE(left) == AOP_ACC) {
5678 emitpcode(POC_ANDLW, popGetLit(t));
5680 emitpcode(POC_MOVLW, popGetLit(t));
5681 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5683 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5688 if (AOP_TYPE(left) == AOP_ACC) {
5689 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5691 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5692 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5694 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5700 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5701 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5702 freeAsmop(result,NULL,ic,TRUE);
5705 /*-----------------------------------------------------------------*/
5706 /* genOr - code for or */
5707 /*-----------------------------------------------------------------*/
5708 static void genOr (iCode *ic, iCode *ifx)
5710 operand *left, *right, *result;
5712 unsigned long lit = 0L;
5715 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5717 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5718 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5719 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5721 DEBUGpic14_AopType(__LINE__,left,right,result);
5723 /* if left is a literal & right is not then exchange them */
5724 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5725 AOP_NEEDSACC(left)) {
5726 operand *tmp = right ;
5731 /* if result = right then exchange them */
5732 if(pic14_sameRegs(AOP(result),AOP(right))){
5733 operand *tmp = right ;
5738 /* if right is bit then exchange them */
5739 if (AOP_TYPE(right) == AOP_CRY &&
5740 AOP_TYPE(left) != AOP_CRY){
5741 operand *tmp = right ;
5746 DEBUGpic14_AopType(__LINE__,left,right,result);
5748 if(AOP_TYPE(right) == AOP_LIT)
5749 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5751 size = AOP_SIZE(result);
5755 if (AOP_TYPE(left) == AOP_CRY){
5756 if(AOP_TYPE(right) == AOP_LIT){
5757 // c = bit & literal;
5759 // lit != 0 => result = 1
5760 if(AOP_TYPE(result) == AOP_CRY){
5762 emitpcode(POC_BSF, popGet(AOP(result),0));
5763 //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5764 // AOP(result)->aopu.aop_dir,
5765 // AOP(result)->aopu.aop_dir);
5767 continueIfTrue(ifx);
5771 // lit == 0 => result = left
5772 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5774 pic14_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5777 if (AOP_TYPE(right) == AOP_CRY){
5778 if(pic14_sameRegs(AOP(result),AOP(left))){
5780 emitpcode(POC_BCF, popGet(AOP(result),0));
5781 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5782 emitpcode(POC_BSF, popGet(AOP(result),0));
5784 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5785 AOP(result)->aopu.aop_dir,
5786 AOP(result)->aopu.aop_dir);
5787 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5788 AOP(right)->aopu.aop_dir,
5789 AOP(right)->aopu.aop_dir);
5790 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5791 AOP(result)->aopu.aop_dir,
5792 AOP(result)->aopu.aop_dir);
5794 if( AOP_TYPE(result) == AOP_ACC) {
5795 emitpcode(POC_MOVLW, popGetLit(0));
5796 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5797 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5798 emitpcode(POC_MOVLW, popGetLit(1));
5802 emitpcode(POC_BCF, popGet(AOP(result),0));
5803 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5804 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5805 emitpcode(POC_BSF, popGet(AOP(result),0));
5807 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5808 AOP(result)->aopu.aop_dir,
5809 AOP(result)->aopu.aop_dir);
5810 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5811 AOP(right)->aopu.aop_dir,
5812 AOP(right)->aopu.aop_dir);
5813 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5814 AOP(left)->aopu.aop_dir,
5815 AOP(left)->aopu.aop_dir);
5816 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5817 AOP(result)->aopu.aop_dir,
5818 AOP(result)->aopu.aop_dir);
5823 symbol *tlbl = newiTempLabel(NULL);
5824 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5827 emitpcode(POC_BCF, popGet(AOP(result),0));
5828 if( AOP_TYPE(right) == AOP_ACC) {
5829 emitpcode(POC_IORLW, popGetLit(0));
5831 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5832 emitpcode(POC_BSF, popGet(AOP(result),0));
5837 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5838 pic14_emitcode(";XXX setb","c");
5839 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5840 AOP(left)->aopu.aop_dir,tlbl->key+100);
5841 pic14_toBoolean(right);
5842 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5843 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5844 jmpTrueOrFalse(ifx, tlbl);
5848 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5855 pic14_outBitC(result);
5857 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5858 genIfxJump(ifx, "c");
5862 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5863 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5864 if((AOP_TYPE(right) == AOP_LIT) &&
5865 (AOP_TYPE(result) == AOP_CRY) &&
5866 (AOP_TYPE(left) != AOP_CRY)){
5868 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5871 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5873 continueIfTrue(ifx);
5876 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5877 // lit = 0, result = boolean(left)
5879 pic14_emitcode(";XXX setb","c");
5880 pic14_toBoolean(right);
5882 symbol *tlbl = newiTempLabel(NULL);
5883 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5885 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5887 genIfxJump (ifx,"a");
5891 pic14_outBitC(result);
5895 /* if left is same as result */
5896 if(pic14_sameRegs(AOP(result),AOP(left))){
5898 for(;size--; offset++,lit>>=8) {
5899 if(AOP_TYPE(right) == AOP_LIT){
5900 if((lit & 0xff) == 0)
5901 /* or'ing with 0 has no effect */
5904 int p = my_powof2(lit & 0xff);
5906 /* only one bit is set in the literal, so use a bsf instruction */
5908 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5910 if(know_W != (int)(lit & 0xff))
5911 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5912 know_W = lit & 0xff;
5913 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5918 if (AOP_TYPE(left) == AOP_ACC) {
5919 emitpcode(POC_IORFW, popGet(AOP(right),offset));
5920 pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5922 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
5923 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5925 pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5926 pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5932 // left & result in different registers
5933 if(AOP_TYPE(result) == AOP_CRY){
5935 // if(size), result in bit
5936 // if(!size && ifx), conditional oper: if(left | right)
5937 symbol *tlbl = newiTempLabel(NULL);
5938 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5939 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5943 pic14_emitcode(";XXX setb","c");
5945 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5946 pic14_emitcode(";XXX orl","a,%s",
5947 aopGet(AOP(left),offset,FALSE,FALSE));
5948 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5953 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5954 pic14_outBitC(result);
5956 jmpTrueOrFalse(ifx, tlbl);
5957 } else for(;(size--);offset++){
5959 // result = left | right
5960 if(AOP_TYPE(right) == AOP_LIT){
5961 int t = (lit >> (offset*8)) & 0x0FFL;
5964 if (AOP_TYPE(left) != AOP_ACC) {
5965 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
5967 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5971 if (AOP_TYPE(left) == AOP_ACC) {
5972 emitpcode(POC_IORLW, popGetLit(t));
5974 emitpcode(POC_MOVLW, popGetLit(t));
5975 emitpcode(POC_IORFW, popGet(AOP(left),offset));
5977 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5982 // faster than result <- left, anl result,right
5983 // and better if result is SFR
5984 if (AOP_TYPE(left) == AOP_ACC) {
5985 emitpcode(POC_IORFW,popGet(AOP(right),offset));
5987 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5988 emitpcode(POC_IORFW,popGet(AOP(left),offset));
5990 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5995 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5996 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5997 freeAsmop(result,NULL,ic,TRUE);
6000 /*-----------------------------------------------------------------*/
6001 /* genXor - code for xclusive or */
6002 /*-----------------------------------------------------------------*/
6003 static void genXor (iCode *ic, iCode *ifx)
6005 operand *left, *right, *result;
6007 unsigned long lit = 0L;
6010 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6012 aopOp((left = IC_LEFT(ic)),ic,FALSE);
6013 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6014 aopOp((result=IC_RESULT(ic)),ic,TRUE);
6016 /* if left is a literal & right is not ||
6017 if left needs acc & right does not */
6018 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6019 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6020 operand *tmp = right ;
6025 /* if result = right then exchange them */
6026 if(pic14_sameRegs(AOP(result),AOP(right))){
6027 operand *tmp = right ;
6032 /* if right is bit then exchange them */
6033 if (AOP_TYPE(right) == AOP_CRY &&
6034 AOP_TYPE(left) != AOP_CRY){
6035 operand *tmp = right ;
6039 if(AOP_TYPE(right) == AOP_LIT)
6040 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6042 size = AOP_SIZE(result);
6046 if (AOP_TYPE(left) == AOP_CRY){
6047 if(AOP_TYPE(right) == AOP_LIT){
6048 // c = bit & literal;
6050 // lit>>1 != 0 => result = 1
6051 if(AOP_TYPE(result) == AOP_CRY){
6053 {emitpcode(POC_BSF, popGet(AOP(result),offset));
6054 pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6056 continueIfTrue(ifx);
6059 pic14_emitcode("setb","c");
6063 // lit == 0, result = left
6064 if(size && pic14_sameRegs(AOP(result),AOP(left)))
6066 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6068 // lit == 1, result = not(left)
6069 if(size && pic14_sameRegs(AOP(result),AOP(left))){
6070 emitpcode(POC_MOVLW, popGet(AOP(result),offset));
6071 emitpcode(POC_XORWF, popGet(AOP(result),offset));
6072 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6075 assert ( !"incomplete genXor" );
6076 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6077 pic14_emitcode("cpl","c");
6084 symbol *tlbl = newiTempLabel(NULL);
6085 if (AOP_TYPE(right) == AOP_CRY){
6087 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6090 int sizer = AOP_SIZE(right);
6092 // if val>>1 != 0, result = 1
6093 pic14_emitcode("setb","c");
6095 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6097 // test the msb of the lsb
6098 pic14_emitcode("anl","a,#0xfe");
6099 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6103 pic14_emitcode("rrc","a");
6105 pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6106 pic14_emitcode("cpl","c");
6107 pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6112 pic14_outBitC(result);
6114 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6115 genIfxJump(ifx, "c");
6119 if(pic14_sameRegs(AOP(result),AOP(left))){
6120 /* if left is same as result */
6121 for(;size--; offset++) {
6122 if(AOP_TYPE(right) == AOP_LIT){
6123 int t = (lit >> (offset*8)) & 0x0FFL;
6127 if (IS_AOP_PREG(left)) {
6128 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6129 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6130 aopPut(AOP(result),"a",offset);
6132 emitpcode(POC_MOVLW, popGetLit(t));
6133 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6134 pic14_emitcode("xrl","%s,%s",
6135 aopGet(AOP(left),offset,FALSE,TRUE),
6136 aopGet(AOP(right),offset,FALSE,FALSE));
6139 if (AOP_TYPE(left) == AOP_ACC)
6140 pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6142 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6143 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6145 if (IS_AOP_PREG(left)) {
6146 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6147 aopPut(AOP(result),"a",offset);
6149 pic14_emitcode("xrl","%s,a",
6150 aopGet(AOP(left),offset,FALSE,TRUE));
6156 // left & result in different registers
6157 if(AOP_TYPE(result) == AOP_CRY){
6159 // if(size), result in bit
6160 // if(!size && ifx), conditional oper: if(left ^ right)
6161 symbol *tlbl = newiTempLabel(NULL);
6162 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6164 pic14_emitcode("setb","c");
6166 if((AOP_TYPE(right) == AOP_LIT) &&
6167 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6168 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6170 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6171 pic14_emitcode("xrl","a,%s",
6172 aopGet(AOP(left),offset,FALSE,FALSE));
6174 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6179 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6180 pic14_outBitC(result);
6182 jmpTrueOrFalse(ifx, tlbl);
6183 } else for(;(size--);offset++){
6185 // result = left & right
6186 if(AOP_TYPE(right) == AOP_LIT){
6187 int t = (lit >> (offset*8)) & 0x0FFL;
6190 if (AOP_TYPE(left) != AOP_ACC) {
6191 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6193 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6194 pic14_emitcode("movf","%s,w",
6195 aopGet(AOP(left),offset,FALSE,FALSE));
6196 pic14_emitcode("movwf","%s",
6197 aopGet(AOP(result),offset,FALSE,FALSE));
6200 if (AOP_TYPE(left) == AOP_ACC) {
6201 emitpcode(POC_XORLW, popGetLit(t));
6203 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6205 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6208 if (AOP_TYPE(left) == AOP_ACC) {
6209 emitpcode(POC_XORLW, popGetLit(t));
6211 emitpcode(POC_MOVLW, popGetLit(t));
6212 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6214 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6215 pic14_emitcode("movlw","0x%x",t);
6216 pic14_emitcode("xorwf","%s,w",
6217 aopGet(AOP(left),offset,FALSE,FALSE));
6218 pic14_emitcode("movwf","%s",
6219 aopGet(AOP(result),offset,FALSE,FALSE));
6225 // faster than result <- left, anl result,right
6226 // and better if result is SFR
6227 if (AOP_TYPE(left) == AOP_ACC) {
6228 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6230 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6231 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6233 if ( AOP_TYPE(result) != AOP_ACC){
6234 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6240 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6241 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6242 freeAsmop(result,NULL,ic,TRUE);
6245 /*-----------------------------------------------------------------*/
6246 /* genInline - write the inline code out */
6247 /*-----------------------------------------------------------------*/
6248 static void genInline (iCode *ic)
6250 char *buffer, *bp, *bp1;
6253 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6255 _G.inLine += (!options.asmpeep);
6257 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6258 strcpy(buffer,IC_INLINE(ic));
6260 /* emit each line as a code */
6266 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6274 /* print label, use this special format with NULL directive
6275 * to denote that the argument should not be indented with tab */
6276 addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6283 if ((bp1 != bp) && *bp1)
6284 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6288 _G.inLine -= (!options.asmpeep);
6291 /*-----------------------------------------------------------------*/
6292 /* genRRC - rotate right with carry */
6293 /*-----------------------------------------------------------------*/
6294 static void genRRC (iCode *ic)
6296 operand *left , *result ;
6297 int size, offset = 0, same;
6300 /* rotate right with carry */
6302 result=IC_RESULT(ic);
6303 aopOp (left,ic,FALSE);
6304 aopOp (result,ic,FALSE);
6306 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6308 same = pic14_sameRegs(AOP(result),AOP(left));
6310 size = AOP_SIZE(result);
6312 /* get the lsb and put it into the carry */
6313 emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6320 emitpcode(POC_RRF, popGet(AOP(left),offset));
6322 emitpcode(POC_RRFW, popGet(AOP(left),offset));
6323 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6329 freeAsmop(left,NULL,ic,TRUE);
6330 freeAsmop(result,NULL,ic,TRUE);
6333 /*-----------------------------------------------------------------*/
6334 /* genRLC - generate code for rotate left with carry */
6335 /*-----------------------------------------------------------------*/
6336 static void genRLC (iCode *ic)
6338 operand *left , *result ;
6339 int size, offset = 0;
6343 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6344 /* rotate right with carry */
6346 result=IC_RESULT(ic);
6347 aopOp (left,ic,FALSE);
6348 aopOp (result,ic,FALSE);
6350 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6352 same = pic14_sameRegs(AOP(result),AOP(left));
6354 /* move it to the result */
6355 size = AOP_SIZE(result);
6357 /* get the msb and put it into the carry */
6358 emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6365 emitpcode(POC_RLF, popGet(AOP(left),offset));
6367 emitpcode(POC_RLFW, popGet(AOP(left),offset));
6368 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6375 freeAsmop(left,NULL,ic,TRUE);
6376 freeAsmop(result,NULL,ic,TRUE);
6379 /*-----------------------------------------------------------------*/
6380 /* genGetHbit - generates code get highest order bit */
6381 /*-----------------------------------------------------------------*/
6382 static void genGetHbit (iCode *ic)
6384 operand *left, *result;
6386 result=IC_RESULT(ic);
6387 aopOp (left,ic,FALSE);
6388 aopOp (result,ic,FALSE);
6391 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6392 /* get the highest order byte into a */
6393 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6394 if(AOP_TYPE(result) == AOP_CRY){
6395 pic14_emitcode("rlc","a");
6396 pic14_outBitC(result);
6399 pic14_emitcode("rl","a");
6400 pic14_emitcode("anl","a,#0x01");
6401 pic14_outAcc(result);
6405 freeAsmop(left,NULL,ic,TRUE);
6406 freeAsmop(result,NULL,ic,TRUE);
6409 /*-----------------------------------------------------------------*/
6410 /* AccLsh - shift left accumulator by known count */
6411 /* MARK: pic14 always rotates through CARRY! */
6412 /*-----------------------------------------------------------------*/
6413 static void AccLsh (pCodeOp *pcop,int shCount)
6416 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6417 shCount &= 0x0007; // shCount : 0..7
6424 emitpcode(POC_RLF,pcop);
6428 emitpcode(POC_RLF,pcop);
6429 emitpcode(POC_RLF,pcop);
6432 emitpcode(POC_RLF,pcop);
6433 emitpcode(POC_RLF,pcop);
6434 emitpcode(POC_RLF,pcop);
6437 emitpcode(POC_SWAPF,pcop);
6440 emitpcode(POC_SWAPF,pcop);
6441 emitpcode(POC_RLF,pcop);
6444 emitpcode(POC_SWAPF,pcop);
6445 emitpcode(POC_RLF,pcop);
6446 emitpcode(POC_RLF,pcop);
6449 emitpcode(POC_RRFW,pcop);
6450 emitpcode(POC_RRF,pcop);
6453 /* clear invalid bits */
6454 emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6455 emitpcode(POC_ANDWF, pcop);
6458 /*-----------------------------------------------------------------*/
6459 /* AccRsh - shift right accumulator by known count */
6460 /* MARK: pic14 always rotates through CARRY! */
6461 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6462 /* 1: mask out invalid bits (zero-extend) */
6463 /* 2: sign-extend result (pretty slow) */
6464 /*-----------------------------------------------------------------*/
6465 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6468 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6469 shCount &= 0x0007; // shCount : 0..7
6475 /* load sign if needed */
6476 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6477 else if (mask_mode == 1) emitCLRC;
6478 emitpcode(POC_RRF,pcop);
6482 /* load sign if needed */
6483 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6484 emitpcode(POC_RRF,pcop);
6485 /* load sign if needed */
6486 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6487 emitpcode(POC_RRF,pcop);
6488 if (mask_mode == 2) return;
6491 /* load sign if needed */
6492 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6493 emitpcode(POC_RRF,pcop);
6494 /* load sign if needed */
6495 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6496 emitpcode(POC_RRF,pcop);
6497 /* load sign if needed */
6498 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6499 emitpcode(POC_RRF,pcop);
6500 if (mask_mode == 2) return;
6503 emitpcode(POC_SWAPF,pcop);
6506 emitpcode(POC_SWAPF,pcop);
6507 emitpcode(POC_RRF,pcop);
6510 emitpcode(POC_SWAPF,pcop);
6511 emitpcode(POC_RRF,pcop);
6512 emitpcode(POC_RRF,pcop);
6518 emitpcode(POC_RLFW,pcop);
6519 emitpcode(POC_CLRF,pcop);
6521 emitpcode(POC_COMF,pcop);
6524 emitpcode(POC_RLFW,pcop);
6525 emitpcode(POC_RLF,pcop);
6532 /* leave invalid bits undefined */
6536 /* clear invalid bits -- zero-extend */
6537 emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6538 emitpcode(POC_ANDWF, pcop);
6540 if (mask_mode == 2) {
6542 emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6543 emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6544 emitpcode(POC_IORWF, pcop);
6549 /*-----------------------------------------------------------------*/
6550 /* AccSRsh - signed right shift accumulator by known count */
6551 /*-----------------------------------------------------------------*/
6552 static void AccSRsh (int shCount)
6555 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6558 pic14_emitcode("mov","c,acc.7");
6559 pic14_emitcode("rrc","a");
6560 } else if(shCount == 2){
6561 pic14_emitcode("mov","c,acc.7");
6562 pic14_emitcode("rrc","a");
6563 pic14_emitcode("mov","c,acc.7");
6564 pic14_emitcode("rrc","a");
6566 tlbl = newiTempLabel(NULL);
6567 /* rotate right accumulator */
6568 AccRol(8 - shCount);
6569 /* and kill the higher order bits */
6570 pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6571 pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6572 pic14_emitcode("orl","a,#0x%02x",
6573 (unsigned char)~SRMask[shCount]);
6574 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6579 /*-----------------------------------------------------------------*/
6580 /* shiftR1Left2Result - shift right one byte from left to result */
6581 /*-----------------------------------------------------------------*/
6582 static void shiftR1Left2ResultSigned (operand *left, int offl,
6583 operand *result, int offr,
6589 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6591 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6595 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6597 emitpcode(POC_RRF, popGet(AOP(result),offr));
6599 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6600 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6606 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6608 emitpcode(POC_RRF, popGet(AOP(result),offr));
6610 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6611 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6613 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6614 emitpcode(POC_RRF, popGet(AOP(result),offr));
6620 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6622 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6623 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6626 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6627 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6628 emitpcode(POC_ANDLW, popGetLit(0x1f));
6630 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6631 emitpcode(POC_IORLW, popGetLit(0xe0));
6633 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6637 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6638 emitpcode(POC_ANDLW, popGetLit(0x0f));
6639 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6640 emitpcode(POC_IORLW, popGetLit(0xf0));
6641 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6645 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6647 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6648 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6650 emitpcode(POC_RRFW, popGet(AOP(result),offr));
6651 emitpcode(POC_ANDLW, popGetLit(0x07));
6652 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6653 emitpcode(POC_IORLW, popGetLit(0xf8));
6654 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6659 emitpcode(POC_MOVLW, popGetLit(0x00));
6660 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6661 emitpcode(POC_MOVLW, popGetLit(0xfe));
6662 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6663 emitpcode(POC_IORLW, popGetLit(0x01));
6664 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6666 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6667 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6668 emitpcode(POC_DECF, popGet(AOP(result),offr));
6669 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6670 emitpcode(POC_BCF, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6676 emitpcode(POC_MOVLW, popGetLit(0x00));
6677 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6678 emitpcode(POC_MOVLW, popGetLit(0xff));
6679 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6681 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6682 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6683 emitpcode(POC_DECF, popGet(AOP(result),offr));
6691 /*-----------------------------------------------------------------*/
6692 /* shiftR1Left2Result - shift right one byte from left to result */
6693 /*-----------------------------------------------------------------*/
6694 static void shiftR1Left2Result (operand *left, int offl,
6695 operand *result, int offr,
6696 int shCount, int sign)
6701 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6703 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6705 /* Copy the msb into the carry if signed. */
6707 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6717 emitpcode(POC_RRF, popGet(AOP(result),offr));
6719 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6720 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6726 emitpcode(POC_RRF, popGet(AOP(result),offr));
6728 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6729 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6732 emitpcode(POC_RRF, popGet(AOP(result),offr));
6737 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6739 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6740 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6743 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6744 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6745 emitpcode(POC_ANDLW, popGetLit(0x1f));
6746 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6750 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6751 emitpcode(POC_ANDLW, popGetLit(0x0f));
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));
6760 emitpcode(POC_RRF, popGet(AOP(result),offr));
6765 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6766 emitpcode(POC_ANDLW, popGetLit(0x80));
6767 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6768 emitpcode(POC_RLF, popGet(AOP(result),offr));
6769 emitpcode(POC_RLF, popGet(AOP(result),offr));
6774 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6775 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6776 emitpcode(POC_RLF, popGet(AOP(result),offr));
6785 /*-----------------------------------------------------------------*/
6786 /* shiftL1Left2Result - shift left one byte from left to result */
6787 /*-----------------------------------------------------------------*/
6788 static void shiftL1Left2Result (operand *left, int offl,
6789 operand *result, int offr, int shCount)
6795 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6797 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6798 DEBUGpic14_emitcode ("; ***","same = %d",same);
6799 // l = aopGet(AOP(left),offl,FALSE,FALSE);
6801 /* shift left accumulator */
6802 //AccLsh(shCount); // don't comment out just yet...
6803 // aopPut(AOP(result),"a",offr);
6807 /* Shift left 1 bit position */
6808 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6810 emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6812 emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6813 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6817 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6818 emitpcode(POC_ANDLW,popGetLit(0x7e));
6819 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6820 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6823 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6824 emitpcode(POC_ANDLW,popGetLit(0x3e));
6825 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6826 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6827 emitpcode(POC_RLF, popGet(AOP(result),offr));
6830 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6831 emitpcode(POC_ANDLW, popGetLit(0xf0));
6832 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6835 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6836 emitpcode(POC_ANDLW, popGetLit(0xf0));
6837 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6838 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6841 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6842 emitpcode(POC_ANDLW, popGetLit(0x30));
6843 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6844 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6845 emitpcode(POC_RLF, popGet(AOP(result),offr));
6848 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6849 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6850 emitpcode(POC_RRF, popGet(AOP(result),offr));
6854 DEBUGpic14_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6860 /*-----------------------------------------------------------------*/
6861 /* movLeft2Result - move byte from left to result */
6862 /*-----------------------------------------------------------------*/
6863 static void movLeft2Result (operand *left, int offl,
6864 operand *result, int offr)
6868 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6869 if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6870 l = aopGet(AOP(left),offl,FALSE,FALSE);
6872 if (*l == '@' && (IS_AOP_PREG(result))) {
6873 pic14_emitcode("mov","a,%s",l);
6874 aopPut(AOP(result),"a",offr);
6876 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6877 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6882 /*-----------------------------------------------------------------*/
6883 /* shiftLeft_Left2ResultLit - shift left by known count */
6884 /*-----------------------------------------------------------------*/
6886 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6888 int size, same, offr, i;
6890 size = AOP_SIZE(left);
6891 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6893 same = pic14_sameRegs (AOP(left), AOP(result));
6896 shCount = shCount & 0x07;
6902 case 0: /* takes 0 or 2N cycles (for offr==0) */
6903 if (!same || offr) {
6904 for (i=size-1; i >= 0; i--)
6905 movLeft2Result (left, i, result, offr + i);
6909 case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6911 shiftLeft_Left2ResultLit (left, result, 8 * offr);
6912 shiftLeft_Left2ResultLit (result, result, shCount);
6913 return; /* prevent clearing result again */
6916 for (i=0; i < size; i++) {
6917 if (same && !offr) {
6918 emitpcode (POC_RLF, popGet (AOP(left), i));
6920 emitpcode (POC_RLFW, popGet (AOP(left), i));
6921 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6927 case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
6928 /* works in-place/with offr as well */
6929 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
6930 emitpcode (POC_ANDLW, popGetLit (0xF0));
6931 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
6933 for (i = size - 2; i >= 0; i--)
6935 emitpcode (POC_SWAPFW, popGet (AOP(left), i));
6936 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6937 emitpcode (POC_ANDLW, popGetLit (0x0F));
6938 emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
6939 emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
6943 case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
6944 /* works in-place/with offr as well */
6945 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
6946 for (i = size-2; i >= 0; i--) {
6947 emitpcode (POC_RRFW, popGet (AOP(left), i));
6948 emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
6950 emitpcode (POC_CLRF, popGet (AOP(result), offr));
6951 emitpcode (POC_RRF, popGet (AOP(result), offr));
6955 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
6956 shiftLeft_Left2ResultLit (result, result, 1);
6957 return; /* prevent clearing result again */
6963 emitpcode (POC_CLRF, popGet (AOP(result), offr));
6967 /*-----------------------------------------------------------------*/
6968 /* shiftRight_Left2ResultLit - shift right by known count */
6969 /*-----------------------------------------------------------------*/
6971 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
6973 int size, same, offr, i;
6975 size = AOP_SIZE(left);
6976 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6978 same = pic14_sameRegs (AOP(left), AOP(result));
6981 shCount = shCount & 0x07;
6989 case 0: /* takes 0 or 2N cycles (for offr==0) */
6990 if (!same || offr) {
6991 for (i=0; i < size; i++)
6992 movLeft2Result (left, i + offr, result, i);
6996 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
6997 emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
6999 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7000 shiftRight_Left2ResultLit (result, result, shCount, sign);
7001 return; /* prevent sign-extending result again */
7005 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7008 for (i = size-1; i >= 0; i--) {
7009 if (same && !offr) {
7010 emitpcode (POC_RRF, popGet (AOP(left), i));
7012 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7013 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7019 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7020 /* works in-place/with offr as well */
7021 emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7022 emitpcode (POC_ANDLW, popGetLit (0x0F));
7023 emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7025 for (i = 1; i < size; i++)
7027 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7028 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7029 emitpcode (POC_ANDLW, popGetLit (0xF0));
7030 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7031 emitpcode (POC_XORWF, popGet (AOP(result), i));
7036 emitpcode (POC_MOVLW, popGetLit (0xF0));
7037 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7038 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7042 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7043 /* works in-place/with offr as well */
7044 emitpcode (POC_RLFW, popGet (AOP(left), offr));
7045 for (i = 0; i < size-1; i++) {
7046 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7047 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7049 emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7051 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7054 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7059 shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7060 shiftRight_Left2ResultLit (result, result, 1, sign);
7061 return; /* prevent sign extending result again */
7066 addSign (result, size, sign);
7070 /*-----------------------------------------------------------------*/
7071 /* shiftL2Left2Result - shift left two bytes from left to result */
7072 /*-----------------------------------------------------------------*/
7073 static void shiftL2Left2Result (operand *left, int offl,
7074 operand *result, int offr, int shCount)
7078 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7080 if(pic14_sameRegs(AOP(result), AOP(left))) {
7088 emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7089 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7090 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7094 emitpcode(POC_RLF, popGet(AOP(result),offr));
7095 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7101 emitpcode(POC_MOVLW, popGetLit(0x0f));
7102 emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7103 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7104 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7105 emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7106 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7107 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7109 emitpcode(POC_RLF, popGet(AOP(result),offr));
7110 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7114 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7115 emitpcode(POC_RRF, popGet(AOP(result),offr));
7116 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7117 emitpcode(POC_RRF, popGet(AOP(result),offr));
7118 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7119 emitpcode(POC_ANDLW,popGetLit(0xc0));
7120 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7121 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7122 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7123 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7126 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7127 emitpcode(POC_RRFW, popGet(AOP(result),offr));
7128 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7129 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7130 emitpcode(POC_RRF, popGet(AOP(result),offr));
7140 /* note, use a mov/add for the shift since the mov has a
7141 chance of getting optimized out */
7142 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7143 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7144 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7145 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7146 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7150 emitpcode(POC_RLF, popGet(AOP(result),offr));
7151 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7157 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7158 emitpcode(POC_ANDLW, popGetLit(0xF0));
7159 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7160 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7161 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7162 emitpcode(POC_ANDLW, popGetLit(0xF0));
7163 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7164 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7168 emitpcode(POC_RLF, popGet(AOP(result),offr));
7169 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7173 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7174 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7175 emitpcode(POC_RRFW, popGet(AOP(result),offl));
7176 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7178 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7179 emitpcode(POC_RRF, popGet(AOP(result),offr));
7180 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7181 emitpcode(POC_ANDLW,popGetLit(0xc0));
7182 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7183 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7184 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7185 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7188 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7189 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7190 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7191 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7192 emitpcode(POC_RRF, popGet(AOP(result),offr));
7198 /*-----------------------------------------------------------------*/
7199 /* shiftR2Left2Result - shift right two bytes from left to result */
7200 /*-----------------------------------------------------------------*/
7201 static void shiftR2Left2Result (operand *left, int offl,
7202 operand *result, int offr,
7203 int shCount, int sign)
7208 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7209 same = pic14_sameRegs(AOP(result), AOP(left));
7211 if(same && ((offl + MSB16) == offr)){
7213 /* don't crash result[offr] */
7214 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7215 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7218 movLeft2Result(left,offl, result, offr);
7219 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7222 /* a:x >> shCount (x = lsb(result))*/
7225 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7227 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7236 emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7241 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7242 emitpcode(POC_RRF,popGet(AOP(result),offr));
7244 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7245 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7246 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7247 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7252 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7255 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7256 emitpcode(POC_RRF,popGet(AOP(result),offr));
7263 emitpcode(POC_MOVLW, popGetLit(0xf0));
7264 emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7265 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7267 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7268 emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7269 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7270 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7272 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7273 emitpcode(POC_ANDLW, popGetLit(0x0f));
7274 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7276 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7277 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7278 emitpcode(POC_ANDLW, popGetLit(0xf0));
7279 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7280 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7284 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7285 emitpcode(POC_RRF, popGet(AOP(result),offr));
7289 emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7290 emitpcode(POC_BTFSC,
7291 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7292 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7300 emitpcode(POC_RLF, popGet(AOP(result),offr));
7301 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7303 emitpcode(POC_RLF, popGet(AOP(result),offr));
7304 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7305 emitpcode(POC_RLFW, popGet(AOP(result),offr));
7306 emitpcode(POC_ANDLW,popGetLit(0x03));
7308 emitpcode(POC_BTFSC,
7309 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7310 emitpcode(POC_IORLW,popGetLit(0xfc));
7312 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7313 emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7314 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7315 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7317 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7318 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7319 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7320 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7321 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7322 emitpcode(POC_RLF, popGet(AOP(result),offr));
7323 emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7324 emitpcode(POC_ANDLW,popGetLit(0x03));
7326 emitpcode(POC_BTFSC,
7327 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7328 emitpcode(POC_IORLW,popGetLit(0xfc));
7330 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7331 //emitpcode(POC_RLF, popGet(AOP(result),offr));
7338 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7339 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7340 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7341 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7344 emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7346 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7350 /*-----------------------------------------------------------------*/
7351 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7352 /*-----------------------------------------------------------------*/
7353 static void shiftLLeftOrResult (operand *left, int offl,
7354 operand *result, int offr, int shCount)
7357 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7359 /* shift left accumulator */
7360 AccLsh(left,offl,shCount);
7361 /* or with result */
7362 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7363 assert ( !"broken (modifies left, fails for left==result))" );
7366 /*-----------------------------------------------------------------*/
7367 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7368 /*-----------------------------------------------------------------*/
7369 static void shiftRLeftOrResult (operand *left, int offl,
7370 operand *result, int offr, int shCount)
7373 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7375 /* shift right accumulator */
7376 AccRsh(left,offl,shCount);
7377 /* or with result */
7378 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7379 assert ( !"broken (modifies left, fails for left==result))" );
7382 /*-----------------------------------------------------------------*/
7383 /* genlshOne - left shift a one byte quantity by known count */
7384 /*-----------------------------------------------------------------*/
7385 static void genlshOne (operand *result, operand *left, int shCount)
7388 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7389 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7392 /*-----------------------------------------------------------------*/
7393 /* genlshTwo - left shift two bytes by known amount != 0 */
7394 /*-----------------------------------------------------------------*/
7395 static void genlshTwo (operand *result,operand *left, int shCount)
7400 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7401 size = pic14_getDataSize(result);
7403 /* if shCount >= 8 */
7409 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7411 movLeft2Result(left, LSB, result, MSB16);
7413 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7416 /* 1 <= shCount <= 7 */
7419 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7421 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7425 /*-----------------------------------------------------------------*/
7426 /* shiftLLong - shift left one long from left to result */
7427 /* offl = LSB or MSB16 */
7428 /*-----------------------------------------------------------------*/
7429 static void shiftLLong (operand *left, operand *result, int offr )
7432 int size = AOP_SIZE(result);
7435 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7436 if(size >= LSB+offr){
7437 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7439 pic14_emitcode("add","a,acc");
7440 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7441 size >= MSB16+offr && offr != LSB )
7442 pic14_emitcode("xch","a,%s",
7443 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7445 aopPut(AOP(result),"a",LSB+offr);
7448 if(size >= MSB16+offr){
7449 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7450 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7453 pic14_emitcode("rlc","a");
7454 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7455 size >= MSB24+offr && offr != LSB)
7456 pic14_emitcode("xch","a,%s",
7457 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7459 aopPut(AOP(result),"a",MSB16+offr);
7462 if(size >= MSB24+offr){
7463 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7464 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7467 pic14_emitcode("rlc","a");
7468 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7469 size >= MSB32+offr && offr != LSB )
7470 pic14_emitcode("xch","a,%s",
7471 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7473 aopPut(AOP(result),"a",MSB24+offr);
7476 if(size > MSB32+offr){
7477 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7478 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7481 pic14_emitcode("rlc","a");
7482 aopPut(AOP(result),"a",MSB32+offr);
7485 aopPut(AOP(result),zero,LSB);
7488 /*-----------------------------------------------------------------*/
7489 /* genlshFour - shift four byte by a known amount != 0 */
7490 /*-----------------------------------------------------------------*/
7491 static void genlshFour (operand *result, operand *left, int shCount)
7496 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7497 size = AOP_SIZE(result);
7499 /* if shifting more that 3 bytes */
7500 if (shCount >= 24 ) {
7503 /* lowest order of left goes to the highest
7504 order of the destination */
7505 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7507 movLeft2Result(left, LSB, result, MSB32);
7508 aopPut(AOP(result),zero,LSB);
7509 aopPut(AOP(result),zero,MSB16);
7510 aopPut(AOP(result),zero,MSB32);
7514 /* more than two bytes */
7515 else if ( shCount >= 16 ) {
7516 /* lower order two bytes goes to higher order two bytes */
7518 /* if some more remaining */
7520 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7522 movLeft2Result(left, MSB16, result, MSB32);
7523 movLeft2Result(left, LSB, result, MSB24);
7525 aopPut(AOP(result),zero,MSB16);
7526 aopPut(AOP(result),zero,LSB);
7530 /* if more than 1 byte */
7531 else if ( shCount >= 8 ) {
7532 /* lower order three bytes goes to higher order three bytes */
7536 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7538 movLeft2Result(left, LSB, result, MSB16);
7540 else{ /* size = 4 */
7542 movLeft2Result(left, MSB24, result, MSB32);
7543 movLeft2Result(left, MSB16, result, MSB24);
7544 movLeft2Result(left, LSB, result, MSB16);
7545 aopPut(AOP(result),zero,LSB);
7547 else if(shCount == 1)
7548 shiftLLong(left, result, MSB16);
7550 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7551 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7552 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7553 aopPut(AOP(result),zero,LSB);
7558 /* 1 <= shCount <= 7 */
7559 else if(shCount <= 2){
7560 shiftLLong(left, result, LSB);
7562 shiftLLong(result, result, LSB);
7564 /* 3 <= shCount <= 7, optimize */
7566 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7567 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7568 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7574 /*-----------------------------------------------------------------*/
7575 /* genLeftShiftLiteral - left shifting by known count */
7576 /*-----------------------------------------------------------------*/
7577 static void genLeftShiftLiteral (operand *left,
7582 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7586 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7587 freeAsmop(right,NULL,ic,TRUE);
7589 aopOp(left,ic,FALSE);
7590 aopOp(result,ic,FALSE);
7592 size = getSize(operandType(result));
7595 pic14_emitcode("; shift left ","result %d, left %d",size,
7599 /* I suppose that the left size >= result size */
7602 movLeft2Result(left, size, result, size);
7606 else if(shCount >= (size * 8))
7608 aopPut(AOP(result),zero,size);
7612 genlshOne (result,left,shCount);
7617 genlshTwo (result,left,shCount);
7621 genlshFour (result,left,shCount);
7625 freeAsmop(left,NULL,ic,TRUE);
7626 freeAsmop(result,NULL,ic,TRUE);
7630 /*-----------------------------------------------------------------*
7631 * genMultiAsm - repeat assembly instruction for size of register.
7632 * if endian == 1, then the high byte (i.e base address + size of
7633 * register) is used first else the low byte is used first;
7634 *-----------------------------------------------------------------*/
7635 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7641 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7654 emitpcode(poc, popGet(AOP(reg),offset));
7661 /*-----------------------------------------------------------------*/
7662 /* genLeftShift - generates code for left shifting */
7663 /*-----------------------------------------------------------------*/
7664 static void genLeftShift (iCode *ic)
7666 operand *left,*right, *result;
7668 unsigned long lit = 0L;
7670 symbol *tlbl , *tlbl1;
7674 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7676 right = IC_RIGHT(ic);
7678 result = IC_RESULT(ic);
7680 aopOp(right,ic,FALSE);
7681 aopOp(left,ic,FALSE);
7682 aopOp(result,ic,FALSE);
7685 /* if the shift count is known then do it
7686 as efficiently as possible */
7687 if (AOP_TYPE(right) == AOP_LIT) {
7688 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7692 /* shift count is unknown then we have to form
7693 a loop get the loop count in B : Note: we take
7694 only the lower order byte since shifting
7695 more that 32 bits make no sense anyway, ( the
7696 largest size of an object can be only 32 bits ) */
7698 /* this code fails for RIGHT == RESULT */
7699 assert (!pic14_sameRegs (AOP(right), AOP(result)));
7701 /* now move the left to the result if they are not the
7703 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
7704 AOP_SIZE(result) > 1) {
7706 size = AOP_SIZE(result);
7709 l = aopGet(AOP(left),offset,FALSE,TRUE);
7710 if (*l == '@' && (IS_AOP_PREG(result))) {
7712 pic14_emitcode("mov","a,%s",l);
7713 aopPut(AOP(result),"a",offset);
7715 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
7716 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7717 //aopPut(AOP(result),l,offset);
7723 if(AOP_TYPE(left) == AOP_LIT)
7724 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7726 size = AOP_SIZE(result);
7728 /* if it is only one byte then */
7730 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7731 emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7732 emitpcode(POC_ANDLW, popGetLit(0xf0));
7733 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7734 emitpcode(POC_MOVFW, popGet(AOP(left),0));
7735 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7736 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7737 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7738 emitpcode(POC_RLFW, popGet(AOP(result),0));
7739 emitpcode(POC_ANDLW, popGetLit(0xfe));
7740 emitpcode(POC_ADDFW, popGet(AOP(result),0));
7741 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7742 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7745 tlbl = newiTempLabel(NULL);
7746 if (!pic14_sameRegs(AOP(left),AOP(result))) {
7747 mov2w (AOP(left), 0);
7748 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7751 emitpcode(POC_COMFW, popGet(AOP(right),0));
7752 emitpcode(POC_RRF, popGet(AOP(result),0));
7753 emitpLabel(tlbl->key);
7754 emitpcode(POC_RLF, popGet(AOP(result),0));
7755 emitpcode(POC_ADDLW, popGetLit(1));
7757 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7762 if (pic14_sameRegs(AOP(left),AOP(result))) {
7764 tlbl = newiTempLabel(NULL);
7765 emitpcode(POC_COMFW, popGet(AOP(right),0));
7766 genMultiAsm(POC_RRF, result, size,1);
7767 emitpLabel(tlbl->key);
7768 genMultiAsm(POC_RLF, result, size,0);
7769 emitpcode(POC_ADDLW, popGetLit(1));
7771 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7775 //tlbl = newiTempLabel(NULL);
7777 //tlbl1 = newiTempLabel(NULL);
7779 //reAdjustPreg(AOP(result));
7781 //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7782 //pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7783 //l = aopGet(AOP(result),offset,FALSE,FALSE);
7785 //pic14_emitcode("add","a,acc");
7786 //aopPut(AOP(result),"a",offset++);
7788 // l = aopGet(AOP(result),offset,FALSE,FALSE);
7790 // pic14_emitcode("rlc","a");
7791 // aopPut(AOP(result),"a",offset++);
7793 //reAdjustPreg(AOP(result));
7795 //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7796 //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7799 tlbl = newiTempLabel(NULL);
7800 tlbl1= newiTempLabel(NULL);
7802 size = AOP_SIZE(result);
7805 pctemp = popGetTempReg(); /* grab a temporary working register. */
7807 emitpcode(POC_MOVFW, popGet(AOP(right),0));
7809 /* offset should be 0, 1 or 3 */
7810 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7812 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
7814 emitpcode(POC_MOVWF, pctemp);
7817 emitpLabel(tlbl->key);
7820 emitpcode(POC_RLF, popGet(AOP(result),0));
7822 emitpcode(POC_RLF, popGet(AOP(result),offset++));
7824 emitpcode(POC_DECFSZ, pctemp);
7825 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7826 emitpLabel(tlbl1->key);
7828 popReleaseTempReg(pctemp);
7832 freeAsmop (right,NULL,ic,TRUE);
7833 freeAsmop(left,NULL,ic,TRUE);
7834 freeAsmop(result,NULL,ic,TRUE);
7839 /*-----------------------------------------------------------------*/
7840 /* genrshOne - right shift a one byte quantity by known count */
7841 /*-----------------------------------------------------------------*/
7842 static void genrshOne (operand *result, operand *left,
7843 int shCount, int sign)
7846 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7847 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7850 /*-----------------------------------------------------------------*/
7851 /* genrshTwo - right shift two bytes by known amount != 0 */
7852 /*-----------------------------------------------------------------*/
7853 static void genrshTwo (operand *result,operand *left,
7854 int shCount, int sign)
7857 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7858 /* if shCount >= 8 */
7862 shiftR1Left2Result(left, MSB16, result, LSB,
7865 movLeft2Result(left, MSB16, result, LSB);
7867 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7870 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7871 emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7875 /* 1 <= shCount <= 7 */
7877 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
7880 /*-----------------------------------------------------------------*/
7881 /* shiftRLong - shift right one long from left to result */
7882 /* offl = LSB or MSB16 */
7883 /*-----------------------------------------------------------------*/
7884 static void shiftRLong (operand *left, int offl,
7885 operand *result, int sign)
7890 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7892 size = AOP_SIZE(left);
7893 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7896 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7900 assert (offl >= 0 && offl < size);
7902 same = pic14_sameRegs (AOP(left), AOP(result));
7904 /* perform the shift */
7907 if (same && !offl) {
7908 emitpcode (POC_RRF, popGet (AOP(result), size));
7910 emitpcode (POC_RRFW, popGet (AOP(left), size));
7911 emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7915 addSign (result, AOP_SIZE(left) - offl, sign);
7918 /*-----------------------------------------------------------------*/
7919 /* genrshFour - shift four byte by a known amount != 0 */
7920 /*-----------------------------------------------------------------*/
7921 static void genrshFour (operand *result, operand *left,
7922 int shCount, int sign)
7925 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7926 /* if shifting more that 3 bytes */
7927 if(shCount >= 24 ) {
7930 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7932 movLeft2Result(left, MSB32, result, LSB);
7934 addSign(result, MSB16, sign);
7936 else if(shCount >= 16){
7939 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7941 movLeft2Result(left, MSB24, result, LSB);
7942 movLeft2Result(left, MSB32, result, MSB16);
7944 addSign(result, MSB24, sign);
7946 else if(shCount >= 8){
7949 shiftRLong(left, MSB16, result, sign);
7950 else if(shCount == 0){
7951 movLeft2Result(left, MSB16, result, LSB);
7952 movLeft2Result(left, MSB24, result, MSB16);
7953 movLeft2Result(left, MSB32, result, MSB24);
7954 addSign(result, MSB32, sign);
7957 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7958 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7959 /* the last shift is signed */
7960 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7961 addSign(result, MSB32, sign);
7964 else{ /* 1 <= shCount <= 7 */
7966 shiftRLong(left, LSB, result, sign);
7968 shiftRLong(result, LSB, result, sign);
7971 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7972 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7973 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7978 /*-----------------------------------------------------------------*/
7979 /* genRightShiftLiteral - right shifting by known count */
7980 /*-----------------------------------------------------------------*/
7981 static void genRightShiftLiteral (operand *left,
7987 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7991 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7992 freeAsmop(right,NULL,ic,TRUE);
7994 aopOp(left,ic,FALSE);
7995 aopOp(result,ic,FALSE);
7998 pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8002 lsize = pic14_getDataSize(left);
8003 res_size = pic14_getDataSize(result);
8004 /* test the LEFT size !!! */
8006 /* I suppose that the left size >= result size */
8009 movLeft2Result(left, res_size, result, res_size);
8012 else if(shCount >= (lsize * 8)){
8015 emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8017 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8018 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8023 emitpcode(POC_MOVLW, popGetLit(0));
8024 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8025 emitpcode(POC_MOVLW, popGetLit(0xff));
8027 emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8032 emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8039 genrshOne (result,left,shCount,sign);
8043 genrshTwo (result,left,shCount,sign);
8047 genrshFour (result,left,shCount,sign);
8055 freeAsmop(left,NULL,ic,TRUE);
8056 freeAsmop(result,NULL,ic,TRUE);
8061 /*-----------------------------------------------------------------*/
8062 /* genSignedRightShift - right shift of signed number */
8063 /*-----------------------------------------------------------------*/
8064 static void genSignedRightShift (iCode *ic)
8066 operand *right, *left, *result;
8069 symbol *tlbl, *tlbl1 ;
8072 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8074 /* we do it the hard way put the shift count in b
8075 and loop thru preserving the sign */
8077 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8079 right = IC_RIGHT(ic);
8081 result = IC_RESULT(ic);
8083 aopOp(right,ic,FALSE);
8084 aopOp(left,ic,FALSE);
8085 aopOp(result,ic,FALSE);
8088 if ( AOP_TYPE(right) == AOP_LIT) {
8089 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8090 //genRightShiftLiteral (left,right,result,ic,1);
8093 /* shift count is unknown then we have to form
8094 a loop get the loop count in B : Note: we take
8095 only the lower order byte since shifting
8096 more that 32 bits make no sense anyway, ( the
8097 largest size of an object can be only 32 bits ) */
8099 //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8100 //pic14_emitcode("inc","b");
8101 //freeAsmop (right,NULL,ic,TRUE);
8102 //aopOp(left,ic,FALSE);
8103 //aopOp(result,ic,FALSE);
8105 /* now move the left to the result if they are not the
8107 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
8108 AOP_SIZE(result) > 1) {
8110 size = AOP_SIZE(result);
8114 l = aopGet(AOP(left),offset,FALSE,TRUE);
8115 if (*l == '@' && IS_AOP_PREG(result)) {
8116 pic14_emitcode("mov","a,%s",l);
8117 aopPut(AOP(result),"a",offset);
8119 aopPut(AOP(result),l,offset);
8121 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8122 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8128 /* mov the highest order bit to OVR */
8129 tlbl = newiTempLabel(NULL);
8130 tlbl1= newiTempLabel(NULL);
8132 size = AOP_SIZE(result);
8135 pctemp = popGetTempReg(); /* grab a temporary working register. */
8137 emitpcode(POC_MOVFW, popGet(AOP(right),0));
8139 /* offset should be 0, 1 or 3 */
8140 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8142 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8144 emitpcode(POC_MOVWF, pctemp);
8147 emitpLabel(tlbl->key);
8149 emitpcode(POC_RLFW, popGet(AOP(result),offset));
8150 emitpcode(POC_RRF, popGet(AOP(result),offset));
8153 emitpcode(POC_RRF, popGet(AOP(result),--offset));
8156 emitpcode(POC_DECFSZ, pctemp);
8157 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8158 emitpLabel(tlbl1->key);
8160 popReleaseTempReg(pctemp);
8162 size = AOP_SIZE(result);
8164 pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8165 pic14_emitcode("rlc","a");
8166 pic14_emitcode("mov","ov,c");
8167 /* if it is only one byte then */
8169 l = aopGet(AOP(left),0,FALSE,FALSE);
8171 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8172 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8173 pic14_emitcode("mov","c,ov");
8174 pic14_emitcode("rrc","a");
8175 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8176 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8177 aopPut(AOP(result),"a",0);
8181 reAdjustPreg(AOP(result));
8182 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8183 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8184 pic14_emitcode("mov","c,ov");
8186 l = aopGet(AOP(result),offset,FALSE,FALSE);
8188 pic14_emitcode("rrc","a");
8189 aopPut(AOP(result),"a",offset--);
8191 reAdjustPreg(AOP(result));
8192 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8193 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8198 freeAsmop(left,NULL,ic,TRUE);
8199 freeAsmop(result,NULL,ic,TRUE);
8200 freeAsmop(right,NULL,ic,TRUE);
8204 /*-----------------------------------------------------------------*/
8205 /* loadSignToC - load the operand's sign bit into CARRY */
8206 /*-----------------------------------------------------------------*/
8208 static void loadSignToC (operand *op)
8211 assert (op && AOP(op) && AOP_SIZE(op));
8214 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8218 /*-----------------------------------------------------------------*/
8219 /* genRightShift - generate code for right shifting */
8220 /*-----------------------------------------------------------------*/
8221 static void genGenericShift (iCode *ic, int shiftRight)
8223 operand *right, *left, *result;
8226 symbol *tlbl, *tlbl1, *inverselbl;
8229 /* if signed then we do it the hard way preserve the
8230 sign bit moving it inwards */
8231 retype = getSpec(operandType(IC_RESULT(ic)));
8232 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8234 /* signed & unsigned types are treated the same : i.e. the
8235 signed is NOT propagated inwards : quoting from the
8236 ANSI - standard : "for E1 >> E2, is equivalent to division
8237 by 2**E2 if unsigned or if it has a non-negative value,
8238 otherwise the result is implementation defined ", MY definition
8239 is that the sign does not get propagated */
8241 right = IC_RIGHT(ic);
8243 result = IC_RESULT(ic);
8245 aopOp(right,ic,FALSE);
8246 aopOp(left,ic,FALSE);
8247 aopOp(result,ic,FALSE);
8249 /* if the shift count is known then do it
8250 as efficiently as possible */
8251 if (AOP_TYPE(right) == AOP_LIT) {
8252 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8256 shiftRight = !shiftRight;
8260 shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8262 shiftLeft_Left2ResultLit (left, result, lit);
8263 //genRightShiftLiteral (left,right,result,ic, 0);
8267 /* shift count is unknown then we have to form
8268 a loop get the loop count in B : Note: we take
8269 only the lower order byte since shifting
8270 more that 32 bits make no sense anyway, ( the
8271 largest size of an object can be only 32 bits ) */
8273 /* we must not overwrite the shift counter */
8274 assert (!pic14_sameRegs(AOP(right),AOP(result)));
8276 /* now move the left to the result if they are not the
8278 if (!pic14_sameRegs(AOP(left),AOP(result)))
8280 size = min(AOP_SIZE(result), AOP_SIZE(left));
8282 mov2w(AOP(left), size);
8283 movwf(AOP(result), size);
8285 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8288 tlbl = newiTempLabel(NULL);
8289 tlbl1= newiTempLabel(NULL);
8291 size = AOP_SIZE(result);
8293 mov2w(AOP(right),0);
8294 if (!SPEC_USIGN(operandType(right)))
8296 inverselbl = newiTempLabel(NULL);
8297 /* signed shift count -- invert shift direction for c<0 */
8298 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8299 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8301 emitpcode(POC_SUBLW, popGetLit(0)); /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8302 /* check for `a = b >> c' with `-c == 0' */
8304 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8305 emitpLabel(tlbl->key);
8306 /* propagate the sign bit inwards for SIGNED result */
8307 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8308 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8309 emitpcode(POC_ADDLW, popGetLit(1)); /* clears CARRY (unless W==0 afterwards) */
8311 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8313 if (!SPEC_USIGN(operandType(right)))
8315 symbol *inv_loop = newiTempLabel(NULL);
8317 shiftRight = !shiftRight; /* invert shift direction */
8319 /* we came here from the code above -- we are done */
8320 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8322 /* emit code for shifting N<0 steps, count is already in W */
8323 emitpLabel(inverselbl->key);
8324 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8325 emitpLabel(inv_loop->key);
8326 /* propagate the sign bit inwards for SIGNED result */
8327 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8328 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8329 emitpcode(POC_ADDLW, popGetLit(1));
8331 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8334 emitpLabel(tlbl1->key);
8336 freeAsmop(left,NULL,ic,TRUE);
8337 freeAsmop (right,NULL,ic,TRUE);
8338 freeAsmop(result,NULL,ic,TRUE);
8341 static void genRightShift (iCode *ic)
8343 genGenericShift(ic, 1);
8346 static void genLeftShift (iCode *ic)
8348 genGenericShift(ic, 0);
8351 /*-----------------------------------------------------------------*/
8352 /* SetIrp - Set IRP bit */
8353 /*-----------------------------------------------------------------*/
8354 void SetIrp(operand *result) {
8356 if (AOP_TYPE(result) == AOP_LIT) {
8357 unsigned lit = (unsigned)operandLitValue(result);
8363 if (PCOP(AOP(result))->type == PO_LITERAL) {
8364 int addrs = PCOL(AOP(result))->lit;
8370 emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8371 if(AOP_SIZE(result) > 1) {
8372 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8380 setup_fsr (operand *ptr)
8383 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8385 /* also setup-up IRP */
8389 /*-----------------------------------------------------------------*/
8390 /* emitPtrByteGet - emits code to get a byte into WREG from an */
8391 /* arbitrary pointer (__code, __data, generic) */
8392 /*-----------------------------------------------------------------*/
8394 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8401 if (!alreadyAddressed) setup_fsr (src);
8402 emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8406 assert( AOP_SIZE(src) == 2 );
8408 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8410 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8411 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
8412 call_libraryfunc ("__gptrget1");
8416 assert( AOP_SIZE(src) == 3 );
8418 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8420 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8422 call_libraryfunc ("__gptrget1");
8426 assert( !"unhandled pointer type" );
8431 /*-----------------------------------------------------------------*/
8432 /* emitPtrByteSet - emits code to set a byte from src through a */
8433 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR). */
8434 /*-----------------------------------------------------------------*/
8436 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8443 if (!alreadyAddressed) setup_fsr (dst);
8444 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8448 assert( !"trying to assign to __code pointer" );
8452 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8454 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8456 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8458 call_libraryfunc ("__gptrput1");
8462 assert( !"unhandled pointer type" );
8467 /*-----------------------------------------------------------------*/
8468 /* genUnpackBits - generates code for unpacking bits */
8469 /*-----------------------------------------------------------------*/
8470 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8472 int rsize; /* result size */
8473 sym_link *etype; /* bitfield type information */
8474 int blen; /* bitfield length */
8475 int bstr; /* bitfield starting bit within byte */
8478 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8479 etype = getSpec(operandType(result));
8480 rsize = getSize (operandType (result));
8481 blen = SPEC_BLEN (etype);
8482 bstr = SPEC_BSTR (etype);
8484 /* single bit field case */
8486 if (ifx) { /* that is for an if statement */
8489 resolveIfx(&rIfx,ifx);
8490 if (ptype == -1) /* direct */
8491 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8493 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8494 emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8495 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8499 assert (!pic14_sameRegs (AOP(result), AOP(left)));
8500 for (i=0; i < AOP_SIZE(result); i++)
8501 emitpcode (POC_CLRF, popGet (AOP(result), i));
8506 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8507 /* adjust result below */
8514 emitPtrByteGet (left, ptype, FALSE);
8515 emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8517 /* adjust result below */
8521 assert( !"unhandled pointer type" );
8524 /* move sign-/zero extended bit to result */
8525 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8526 emitpcode (POC_INCF, popGet (AOP(result), 0));
8528 emitpcode (POC_DECF, popGet (AOP(result), 0));
8530 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8534 else if (blen <= 8 && ((blen + bstr) <= 8))
8539 for (i=0; i < AOP_SIZE(result); i++)
8540 emitpcode (POC_CLRF, popGet (AOP(result), i));
8545 mov2w(AOP(left), 0);
8552 emitPtrByteGet (left, ptype, FALSE);
8556 assert( !"unhandled pointer type" );
8560 emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8561 movwf(AOP(result), 0);
8562 AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8564 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8566 /* signed bitfield */
8567 assert (bstr + blen > 0);
8568 emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8569 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8570 emitpcode(POC_IORWF, popGet(AOP(result),0));
8572 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8576 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8580 /*-----------------------------------------------------------------*/
8581 /* genDataPointerGet - generates code when ptr offset is known */
8582 /*-----------------------------------------------------------------*/
8583 static void genDataPointerGet (operand *left,
8587 int size , offset = 0;
8590 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8593 /* optimization - most of the time, left and result are the same
8594 * address, but different types. for the pic code, we could omit
8597 aopOp(result,ic,TRUE);
8599 if (pic14_sameRegs (AOP(left), AOP(result)))
8602 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8604 //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8606 size = AOP_SIZE(result);
8607 if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8611 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8612 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8616 freeAsmop(left,NULL,ic,TRUE);
8617 freeAsmop(result,NULL,ic,TRUE);
8621 /*-----------------------------------------------------------------*/
8622 /* genNearPointerGet - pic14_emitcode for near pointer fetch */
8623 /*-----------------------------------------------------------------*/
8624 static void genNearPointerGet (operand *left,
8629 sym_link *ltype = operandType(left);
8630 sym_link *rtype = operandType(result);
8631 sym_link *retype= getSpec(rtype); /* bitfield type information */
8635 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8638 aopOp(left,ic,FALSE);
8640 /* if left is rematerialisable and
8641 result is not bit variable type and
8642 the left is pointer to data space i.e
8643 lower 128 bytes of space */
8644 if (AOP_TYPE(left) == AOP_PCODE && //AOP_TYPE(left) == AOP_IMMD &&
8645 !IS_BITVAR(retype) &&
8646 PIC_IS_DATA_PTR(ltype)) {
8647 genDataPointerGet (left,result,ic);
8651 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8652 aopOp (result,ic,FALSE);
8654 /* Check if can access directly instead of via a pointer */
8655 if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8656 && AOP_SIZE(result) == 1)
8661 if (IS_BITFIELD(getSpec(operandType(result))))
8663 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8667 /* If the pointer value is not in a the FSR then need to put it in */
8668 /* Must set/reset IRP bit for use with FSR. */
8673 /* if bitfield then unpack the bits */
8675 /* we have can just get the values */
8676 int size = AOP_SIZE(result);
8679 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8683 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8685 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8686 if (AOP_TYPE(result) == AOP_LIT) {
8687 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8689 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8691 if (size && !direct)
8692 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8697 /* now some housekeeping stuff */
8699 /* we had to allocate for this iCode */
8700 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8701 freeAsmop(NULL,aop,ic,TRUE);
8703 /* we did not allocate which means left
8704 already in a pointer register, then
8705 if size > 0 && this could be used again
8706 we have to point it back to where it
8708 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8709 if (AOP_SIZE(result) > 1 &&
8710 !OP_SYMBOL(left)->remat &&
8711 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8713 int size = AOP_SIZE(result) - 1;
8715 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8721 freeAsmop(left,NULL,ic,TRUE);
8722 freeAsmop(result,NULL,ic,TRUE);
8727 /*-----------------------------------------------------------------*/
8728 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch */
8729 /*-----------------------------------------------------------------*/
8730 static void genPagedPointerGet (operand *left,
8737 sym_link *rtype, *retype;
8740 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8742 rtype = operandType(result);
8743 retype= getSpec(rtype);
8745 aopOp(left,ic,FALSE);
8747 /* if the value is already in a pointer register
8748 then don't need anything more */
8749 if (!AOP_INPREG(AOP(left))) {
8750 /* otherwise get a free pointer register */
8752 preg = getFreePtr(ic,&aop,FALSE);
8753 pic14_emitcode("mov","%s,%s",
8755 aopGet(AOP(left),0,FALSE,TRUE));
8756 rname = preg->name ;
8758 rname = aopGet(AOP(left),0,FALSE,FALSE);
8760 freeAsmop(left,NULL,ic,TRUE);
8761 aopOp (result,ic,FALSE);
8763 /* if bitfield then unpack the bits */
8764 if (IS_BITFIELD(retype))
8765 genUnpackBits (result,left,rname,PPOINTER,0);
8767 /* we have can just get the values */
8768 int size = AOP_SIZE(result);
8773 pic14_emitcode("movx","a,@%s",rname);
8774 aopPut(AOP(result),"a",offset);
8779 pic14_emitcode("inc","%s",rname);
8783 /* now some housekeeping stuff */
8785 /* we had to allocate for this iCode */
8786 freeAsmop(NULL,aop,ic,TRUE);
8788 /* we did not allocate which means left
8789 already in a pointer register, then
8790 if size > 0 && this could be used again
8791 we have to point it back to where it
8793 if (AOP_SIZE(result) > 1 &&
8794 !OP_SYMBOL(left)->remat &&
8795 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8797 int size = AOP_SIZE(result) - 1;
8799 pic14_emitcode("dec","%s",rname);
8804 freeAsmop(result,NULL,ic,TRUE);
8809 /*-----------------------------------------------------------------*/
8810 /* genFarPointerGet - gget value from far space */
8811 /*-----------------------------------------------------------------*/
8812 static void genFarPointerGet (operand *left,
8813 operand *result, iCode *ic)
8816 sym_link *retype = getSpec(operandType(result));
8819 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8821 aopOp(left,ic,FALSE);
8823 /* if the operand is already in dptr
8824 then we do nothing else we move the value to dptr */
8825 if (AOP_TYPE(left) != AOP_STR) {
8826 /* if this is remateriazable */
8827 if (AOP_TYPE(left) == AOP_IMMD)
8828 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8829 else { /* we need to get it byte by byte */
8830 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8831 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8832 if (options.model == MODEL_FLAT24)
8834 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8838 /* so dptr know contains the address */
8839 freeAsmop(left,NULL,ic,TRUE);
8840 aopOp(result,ic,FALSE);
8842 /* if bit then unpack */
8843 if (IS_BITFIELD(retype))
8844 genUnpackBits(result,left,"dptr",FPOINTER,0);
8846 size = AOP_SIZE(result);
8850 pic14_emitcode("movx","a,@dptr");
8851 aopPut(AOP(result),"a",offset++);
8853 pic14_emitcode("inc","dptr");
8857 freeAsmop(result,NULL,ic,TRUE);
8862 /*-----------------------------------------------------------------*/
8863 /* genCodePointerGet - get value from code space */
8864 /*-----------------------------------------------------------------*/
8865 static void genCodePointerGet (operand *left,
8866 operand *result, iCode *ic)
8869 sym_link *retype = getSpec(operandType(result));
8871 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8873 aopOp(left,ic,FALSE);
8875 /* if the operand is already in dptr
8876 then we do nothing else we move the value to dptr */
8877 if (AOP_TYPE(left) != AOP_STR) {
8878 /* if this is remateriazable */
8879 if (AOP_TYPE(left) == AOP_IMMD)
8880 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8881 else { /* we need to get it byte by byte */
8882 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8883 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8884 if (options.model == MODEL_FLAT24)
8886 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8890 /* so dptr know contains the address */
8891 freeAsmop(left,NULL,ic,TRUE);
8892 aopOp(result,ic,FALSE);
8894 /* if bit then unpack */
8895 if (IS_BITFIELD(retype))
8896 genUnpackBits(result,left,"dptr",CPOINTER,0);
8898 size = AOP_SIZE(result);
8902 pic14_emitcode("clr","a");
8903 pic14_emitcode("movc","a,@a+dptr");
8904 aopPut(AOP(result),"a",offset++);
8906 pic14_emitcode("inc","dptr");
8910 freeAsmop(result,NULL,ic,TRUE);
8913 /*-----------------------------------------------------------------*/
8914 /* genGenPointerGet - gget value from generic pointer space */
8915 /*-----------------------------------------------------------------*/
8916 static void genGenPointerGet (operand *left,
8917 operand *result, iCode *ic)
8920 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8921 aopOp(left,ic,FALSE);
8922 aopOp(result,ic,FALSE);
8925 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8927 if (IS_BITFIELD(getSpec(operandType(result))))
8929 genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
8934 /* emit call to __gptrget */
8935 char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
8936 int size = AOP_SIZE(result);
8939 assert (size > 0 && size <= 4);
8941 /* pass arguments */
8942 assert (AOP_SIZE(left) == 3);
8943 mov2w(AOP(left), 0);
8944 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8945 mov2w(AOP(left), 1);
8946 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8947 mov2w(AOP(left), 2);
8948 call_libraryfunc (func[size]);
8951 movwf (AOP(result), --size);
8953 emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
8954 movwf (AOP(result), size);
8958 freeAsmop(left,NULL,ic,TRUE);
8959 freeAsmop(result,NULL,ic,TRUE);
8963 /*-----------------------------------------------------------------*/
8964 /* genConstPointerGet - get value from const generic pointer space */
8965 /*-----------------------------------------------------------------*/
8966 static void genConstPointerGet (operand *left,
8967 operand *result, iCode *ic)
8969 //sym_link *retype = getSpec(operandType(result));
8971 symbol *albl, *blbl;//, *clbl;
8978 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8979 aopOp(left,ic,FALSE);
8980 aopOp(result,ic,FALSE);
8982 size = AOP_SIZE(result);
8984 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8986 DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
8988 lit = op_isLitLike (left);
8989 poc = lit ? POC_MOVLW : POC_MOVFW;
8991 if (IS_BITFIELD(getSpec(operandType(result))))
8993 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
8998 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
8999 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
9000 assert (size > 0 && size <= 4);
9003 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9005 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9006 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
9007 call_libraryfunc (func[size]);
9009 movwf(AOP(result),size-1);
9010 for (i = 1; i < size; i++)
9012 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
9013 movwf(AOP(result),size - 1 - i);
9018 freeAsmop(left,NULL,ic,TRUE);
9019 freeAsmop(result,NULL,ic,TRUE);
9022 /*-----------------------------------------------------------------*/
9023 /* genPointerGet - generate code for pointer get */
9024 /*-----------------------------------------------------------------*/
9025 static void genPointerGet (iCode *ic)
9027 operand *left, *result ;
9028 sym_link *type, *etype;
9032 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9035 result = IC_RESULT(ic) ;
9037 /* depending on the type of pointer we need to
9038 move it to the correct pointer register */
9039 type = operandType(left);
9040 etype = getSpec(type);
9042 if (IS_PTR_CONST(type))
9043 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9045 /* if left is of type of pointer then it is simple */
9046 if (IS_PTR(type) && !IS_FUNC(type->next))
9047 p_type = DCL_TYPE(type);
9049 /* we have to go by the storage class */
9050 p_type = PTR_TYPE(SPEC_OCLS(etype));
9052 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9054 if (SPEC_OCLS(etype)->codesp ) {
9055 DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9056 //p_type = CPOINTER ;
9059 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9060 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9061 /*p_type = FPOINTER ;*/
9063 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9064 DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9065 /* p_type = PPOINTER; */
9067 if (SPEC_OCLS(etype) == idata )
9068 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9069 /* p_type = IPOINTER; */
9071 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9072 /* p_type = POINTER ; */
9075 /* now that we have the pointer type we assign
9076 the pointer values */
9082 genNearPointerGet (left,result,ic);
9086 genPagedPointerGet(left,result,ic);
9090 genFarPointerGet (left,result,ic);
9094 genConstPointerGet (left,result,ic);
9098 genGenPointerGet (left,result,ic);
9101 assert ( !"unhandled pointer type" );
9107 /*-----------------------------------------------------------------*/
9108 /* genPackBits - generates code for packed bit storage */
9109 /*-----------------------------------------------------------------*/
9110 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9112 int blen; /* bitfield length */
9113 int bstr; /* bitfield starting bit within byte */
9114 int litval; /* source literal value (if AOP_LIT) */
9115 unsigned char mask; /* bitmask within current byte */
9118 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9120 blen = SPEC_BLEN (etype);
9121 bstr = SPEC_BSTR (etype);
9123 /* If the bitfield length is less than a byte and does not cross byte boundaries */
9124 if ((blen <= 8) && ((bstr + blen) <= 8))
9126 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9127 (unsigned char) (0xFF >> (8 - bstr)));
9129 if (AOP_TYPE (right) == AOP_LIT)
9131 /* Case with a bitfield length <8 and literal source */
9132 int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9139 if (AOP(result)->type == AOP_PCODE)
9140 pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9142 pcop = popGet(AOP(result),0);
9143 emitpcode(lit?POC_BSF:POC_BCF,pcop);
9149 emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9153 assert( !"trying to assign to bitfield via pointer to __code space" );
9157 emitPtrByteGet(result, p_type, FALSE);
9159 emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9161 emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9163 emitPtrByteSet(result, p_type, TRUE);
9167 assert( !"unhandled pointer type" );
9169 } // switch (p_type)
9172 litval = lit << bstr;
9173 litval &= (~mask) & 0x00ff;
9178 mov2w (AOP(result), 0);
9179 if ((litval|mask) != 0x00ff)
9180 emitpcode(POC_ANDLW, popGetLit (mask));
9182 emitpcode(POC_IORLW, popGetLit (litval));
9183 movwf (AOP(result), 0);
9189 emitPtrByteGet(result, p_type, FALSE);
9190 if ((litval|mask) != 0x00ff)
9191 emitpcode(POC_ANDLW, popGetLit (mask));
9193 emitpcode(POC_IORLW, popGetLit (litval));
9194 emitPtrByteSet(result, p_type, TRUE);
9198 assert( !"trying to assign to bitfield via pointer to __code space" );
9202 assert( !"unhandled pointer type" );
9209 /* right is no literal */
9214 /* Note more efficient code, of pre clearing bit then only setting it if required,
9215 * can only be done if it is known that the result is not a SFR */
9216 emitpcode(POC_RRFW,popGet(AOP(right),0));
9218 emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9220 emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9226 emitPtrByteGet (result, p_type, FALSE);
9227 emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9228 emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9229 emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9230 emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9231 emitPtrByteSet (result, p_type, TRUE);
9235 assert( !"trying to assign to bitfield via pointer to __code space" );
9239 assert( !"unhandled pointer type" );
9244 /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9245 pCodeOp *temp = popGetTempReg ();
9247 mov2w (AOP(right), 0);
9249 emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9251 emitpcode(POC_MOVWF, temp);
9253 AccLsh (temp, bstr);
9259 mov2w (AOP(result), 0);
9260 emitpcode(POC_ANDLW, popGetLit (mask));
9261 emitpcode(POC_IORFW, temp);
9262 movwf (AOP(result), 0);
9268 emitPtrByteGet (result, p_type, FALSE);
9269 emitpcode(POC_ANDLW, popGetLit (mask));
9270 emitpcode(POC_IORFW, temp);
9271 emitPtrByteSet (result, p_type, TRUE);
9275 assert( !"trying to assign to bitfield via pointer to __code space" );
9279 assert( !"unhandled pointer type" );
9283 popReleaseTempReg (temp);
9285 } // if (AOP(right)->type != AOP_LIT)
9287 } // if (blen <= 8 && ((blen + bstr) <= 8))
9289 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9292 /*-----------------------------------------------------------------*/
9293 /* genDataPointerSet - remat pointer to data space */
9294 /*-----------------------------------------------------------------*/
9295 static void genDataPointerSet(operand *right,
9299 int size, offset = 0 ;
9303 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9304 aopOp(right,ic,FALSE);
9305 aopOp(result,ic,FALSE);
9307 assert (IS_SYMOP(result));
9308 assert (IS_PTR(OP_SYM_TYPE(result)));
9310 if (AOP_TYPE(right) == AOP_LIT)
9313 size = AOP_SIZE(right);
9314 ressize = getSize(OP_SYM_ETYPE(result));
9315 if (size > ressize) size = ressize;
9316 //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9318 //assert( !"what's going on here?" );
9321 if ( AOP_TYPE(result) == AOP_PCODE) {
9322 fprintf(stderr,"genDataPointerSet %s, %d\n",
9323 AOP(result)->aopu.pcop->name,
9324 PCOI(AOP(result)->aopu.pcop)->offset);
9328 // tsd, was l+1 - the underline `_' prefix was being stripped
9330 emitpComment ("%s:%u: size=%d/%d, offset=%d, AOP_TYPE(res)=%d", __FILE__,__LINE__, size, ressize, offset, AOP_TYPE(result));
9332 if (AOP_TYPE(right) == AOP_LIT) {
9333 unsigned int lit = pic14aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
9334 //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9336 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9337 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9339 emitpcode(POC_CLRF, popGet(AOP(result), offset));
9342 //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9343 emitpcode(POC_MOVFW, popGet(AOP(right), offset));
9344 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9350 freeAsmop(right,NULL,ic,TRUE);
9351 freeAsmop(result,NULL,ic,TRUE);
9354 /*-----------------------------------------------------------------*/
9355 /* genNearPointerSet - pic14_emitcode for near pointer put */
9356 /*-----------------------------------------------------------------*/
9357 static void genNearPointerSet (operand *right,
9362 sym_link *ptype = operandType(result);
9363 sym_link *retype = getSpec(operandType(right));
9364 sym_link *letype = getSpec(ptype);
9369 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9370 aopOp(result,ic,FALSE);
9373 /* if the result is rematerializable &
9374 in data space & not a bit variable */
9375 //if (AOP_TYPE(result) == AOP_IMMD &&
9376 if (AOP_TYPE(result) == AOP_PCODE &&
9377 PIC_IS_DATA_PTR(ptype) &&
9378 !IS_BITVAR (retype) &&
9379 !IS_BITVAR (letype)) {
9380 genDataPointerSet (right,result,ic);
9381 freeAsmop(result,NULL,ic,TRUE);
9386 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9387 aopOp(right,ic,FALSE);
9388 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9390 /* Check if can access directly instead of via a pointer */
9391 if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9395 if (IS_BITFIELD (letype))
9397 genPackBits (letype, result, right, direct?-1:POINTER);
9401 /* If the pointer value is not in a the FSR then need to put it in */
9402 /* Must set/reset IRP bit for use with FSR. */
9403 /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9408 /* we have can just get the values */
9409 int size = AOP_SIZE(right);
9412 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9414 char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9416 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9418 if (AOP_TYPE(right) == AOP_LIT) {
9419 emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9421 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9424 emitpcode(POC_MOVWF,popGet(AOP(result),0));
9426 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9428 if (size && !direct)
9429 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9434 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9435 /* now some housekeeping stuff */
9437 /* we had to allocate for this iCode */
9438 freeAsmop(NULL,aop,ic,TRUE);
9440 /* we did not allocate which means left
9441 already in a pointer register, then
9442 if size > 0 && this could be used again
9443 we have to point it back to where it
9445 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9446 if (AOP_SIZE(right) > 1 &&
9447 !OP_SYMBOL(result)->remat &&
9448 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9450 int size = AOP_SIZE(right) - 1;
9452 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9456 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9459 freeAsmop(right,NULL,ic,TRUE);
9460 freeAsmop(result,NULL,ic,TRUE);
9464 /*-----------------------------------------------------------------*/
9465 /* genPagedPointerSet - pic14_emitcode for Paged pointer put */
9466 /*-----------------------------------------------------------------*/
9467 static void genPagedPointerSet (operand *right,
9477 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9479 retype= getSpec(operandType(right));
9481 aopOp(result,ic,FALSE);
9483 /* if the value is already in a pointer register
9484 then don't need anything more */
9485 if (!AOP_INPREG(AOP(result))) {
9486 /* otherwise get a free pointer register */
9488 preg = getFreePtr(ic,&aop,FALSE);
9489 pic14_emitcode("mov","%s,%s",
9491 aopGet(AOP(result),0,FALSE,TRUE));
9492 rname = preg->name ;
9494 rname = aopGet(AOP(result),0,FALSE,FALSE);
9496 freeAsmop(result,NULL,ic,TRUE);
9497 aopOp (right,ic,FALSE);
9499 /* if bitfield then unpack the bits */
9500 if (IS_BITFIELD(retype))
9501 genPackBits (retype,result,right,rname,PPOINTER);
9503 /* we have can just get the values */
9504 int size = AOP_SIZE(right);
9508 l = aopGet(AOP(right),offset,FALSE,TRUE);
9511 pic14_emitcode("movx","@%s,a",rname);
9514 pic14_emitcode("inc","%s",rname);
9520 /* now some housekeeping stuff */
9522 /* we had to allocate for this iCode */
9523 freeAsmop(NULL,aop,ic,TRUE);
9525 /* we did not allocate which means left
9526 already in a pointer register, then
9527 if size > 0 && this could be used again
9528 we have to point it back to where it
9530 if (AOP_SIZE(right) > 1 &&
9531 !OP_SYMBOL(result)->remat &&
9532 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9534 int size = AOP_SIZE(right) - 1;
9536 pic14_emitcode("dec","%s",rname);
9541 freeAsmop(right,NULL,ic,TRUE);
9546 /*-----------------------------------------------------------------*/
9547 /* genFarPointerSet - set value from far space */
9548 /*-----------------------------------------------------------------*/
9549 static void genFarPointerSet (operand *right,
9550 operand *result, iCode *ic)
9553 sym_link *retype = getSpec(operandType(right));
9556 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9557 aopOp(result,ic,FALSE);
9559 /* if the operand is already in dptr
9560 then we do nothing else we move the value to dptr */
9561 if (AOP_TYPE(result) != AOP_STR) {
9562 /* if this is remateriazable */
9563 if (AOP_TYPE(result) == AOP_IMMD)
9564 pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9565 else { /* we need to get it byte by byte */
9566 pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9567 pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9568 if (options.model == MODEL_FLAT24)
9570 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9574 /* so dptr know contains the address */
9575 freeAsmop(result,NULL,ic,TRUE);
9576 aopOp(right,ic,FALSE);
9578 /* if bit then unpack */
9579 if (IS_BITFIELD(retype))
9580 genPackBits(retype,result,right,"dptr",FPOINTER);
9582 size = AOP_SIZE(right);
9586 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9588 pic14_emitcode("movx","@dptr,a");
9590 pic14_emitcode("inc","dptr");
9594 freeAsmop(right,NULL,ic,TRUE);
9598 /*-----------------------------------------------------------------*/
9599 /* genGenPointerSet - set value from generic pointer space */
9600 /*-----------------------------------------------------------------*/
9601 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9603 sym_link *retype = getSpec(operandType(result));
9606 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9607 aopOp(right,ic,FALSE);
9608 aopOp(result,ic,FALSE);
9611 DEBUGpic14_AopType(__LINE__,right,NULL,result);
9613 if (IS_BITFIELD(retype))
9615 genPackBits (retype, result, right, GPOINTER);
9620 /* emit call to __gptrput */
9621 char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9622 int size = AOP_SIZE(right);
9625 assert (size == getSize(OP_SYM_ETYPE(result)));
9626 assert (size > 0 && size <= 4);
9628 /* pass arguments */
9629 /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9635 mov2w_op (right, off);
9636 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9641 assert (AOP_SIZE(result) == 3);
9642 mov2w(AOP(result), 0);
9643 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9644 mov2w(AOP(result), 1);
9645 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9646 mov2w(AOP(result), 2);
9647 call_libraryfunc (func[size]);
9650 freeAsmop(right,NULL,ic,TRUE);
9651 freeAsmop(result,NULL,ic,TRUE);
9654 /*-----------------------------------------------------------------*/
9655 /* genPointerSet - stores the value into a pointer location */
9656 /*-----------------------------------------------------------------*/
9657 static void genPointerSet (iCode *ic)
9659 operand *right, *result ;
9660 sym_link *type, *etype;
9664 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9666 right = IC_RIGHT(ic);
9667 result = IC_RESULT(ic) ;
9669 /* depending on the type of pointer we need to
9670 move it to the correct pointer register */
9671 type = operandType(result);
9672 etype = getSpec(type);
9673 /* if left is of type of pointer then it is simple */
9674 if (IS_PTR(type) && !IS_FUNC(type->next)) {
9675 p_type = DCL_TYPE(type);
9678 /* we have to go by the storage class */
9679 p_type = PTR_TYPE(SPEC_OCLS(etype));
9681 /* if (SPEC_OCLS(etype)->codesp ) { */
9682 /* p_type = CPOINTER ; */
9685 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9686 /* p_type = FPOINTER ; */
9688 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9689 /* p_type = PPOINTER ; */
9691 /* if (SPEC_OCLS(etype) == idata ) */
9692 /* p_type = IPOINTER ; */
9694 /* p_type = POINTER ; */
9697 /* now that we have the pointer type we assign
9698 the pointer values */
9704 genNearPointerSet (right,result,ic);
9708 genPagedPointerSet (right,result,ic);
9712 genFarPointerSet (right,result,ic);
9716 genGenPointerSet (right,result,ic);
9720 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9721 "genPointerSet: illegal pointer type");
9725 /*-----------------------------------------------------------------*/
9726 /* genIfx - generate code for Ifx statement */
9727 /*-----------------------------------------------------------------*/
9728 static void genIfx (iCode *ic, iCode *popIc)
9730 operand *cond = IC_COND(ic);
9734 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9736 aopOp(cond,ic,FALSE);
9738 /* get the value into acc */
9739 if (AOP_TYPE(cond) != AOP_CRY)
9740 pic14_toBoolean(cond);
9744 /* if there was something to be popped then do it */
9750 /* This assumes that CARRY is set iff cond is true */
9753 assert (!IC_FALSE(ic));
9754 emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
9756 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9758 assert (IC_FALSE(ic));
9759 emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
9761 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9765 static int hasWarned = 0;
9768 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
9775 /* now Z is set iff !cond */
9778 assert (!IC_FALSE(ic));
9780 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9783 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9789 /* the result is now in the accumulator */
9790 freeAsmop(cond,NULL,ic,TRUE);
9793 /*-----------------------------------------------------------------*/
9794 /* genAddrOf - generates code for address of */
9795 /*-----------------------------------------------------------------*/
9796 static void genAddrOf (iCode *ic)
9798 operand *right, *result, *left;
9802 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9805 //aopOp(IC_RESULT(ic),ic,FALSE);
9807 aopOp((left=IC_LEFT(ic)),ic,FALSE);
9808 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9809 aopOp((result=IC_RESULT(ic)),ic,TRUE);
9811 DEBUGpic14_AopType(__LINE__,left,right,result);
9812 assert (IS_SYMOP (left));
9814 /* sanity check: generic pointers to code space are not yet supported,
9815 * pionters to codespace must not be assigned addresses of __data values. */
9817 fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9818 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)));
9819 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)));
9820 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)));
9821 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)));
9824 if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9825 fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9826 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9827 OP_SYMBOL(left)->name);
9828 } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9829 fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9830 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9831 OP_SYMBOL(left)->name);
9834 size = AOP_SIZE(IC_RESULT(ic));
9835 if (IS_GENPTR(OP_SYM_TYPE(result))) {
9837 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9842 /* fixing bug #863624, reported from (errolv) */
9843 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9844 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9847 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9848 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9853 if (IS_GENPTR(OP_SYM_TYPE(result)))
9855 /* provide correct tag */
9856 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9857 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9858 movwf (AOP(result), 2);
9861 freeAsmop(left,NULL,ic,FALSE);
9862 freeAsmop(result,NULL,ic,TRUE);
9867 /*-----------------------------------------------------------------*/
9868 /* genFarFarAssign - assignment when both are in far space */
9869 /*-----------------------------------------------------------------*/
9870 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9872 int size = AOP_SIZE(right);
9875 /* first push the right side on to the stack */
9877 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9879 pic14_emitcode ("push","acc");
9882 freeAsmop(right,NULL,ic,FALSE);
9883 /* now assign DPTR to result */
9884 aopOp(result,ic,FALSE);
9885 size = AOP_SIZE(result);
9887 pic14_emitcode ("pop","acc");
9888 aopPut(AOP(result),"a",--offset);
9890 freeAsmop(result,NULL,ic,FALSE);
9895 /*-----------------------------------------------------------------*/
9896 /* genAssign - generate code for assignment */
9897 /*-----------------------------------------------------------------*/
9898 static void genAssign (iCode *ic)
9900 operand *result, *right;
9901 int size, offset,know_W;
9902 unsigned long lit = 0L;
9904 result = IC_RESULT(ic);
9905 right = IC_RIGHT(ic) ;
9908 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9910 /* if they are the same */
9911 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9914 aopOp(right,ic,FALSE);
9915 aopOp(result,ic,TRUE);
9917 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9919 /* if they are the same registers */
9920 if (pic14_sameRegs(AOP(right),AOP(result)))
9923 /* special case: assign from __code */
9924 if (!IS_ITEMP(right) /* --> iTemps never reside in __code */
9925 && IS_SYMOP (right) /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
9926 && !IS_FUNC(OP_SYM_TYPE(right)) /* --> we would want its address instead of the first instruction */
9927 && !IS_CODEPTR(OP_SYM_TYPE(right)) /* --> get symbols address instread */
9928 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
9930 emitpComment ("genAssign from CODESPACE");
9931 genConstPointerGet (right, result, ic);
9935 /* just for symmetry reasons... */
9936 if (!IS_ITEMP(result)
9937 && IS_SYMOP (result)
9938 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
9940 assert ( !"cannot write to CODESPACE" );
9943 /* if the result is a bit */
9944 if (AOP_TYPE(result) == AOP_CRY) {
9946 /* if the right size is a literal then
9947 we know what the value is */
9948 if (AOP_TYPE(right) == AOP_LIT) {
9950 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9951 popGet(AOP(result),0));
9953 if (((int) operandLitValue(right)))
9954 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9955 AOP(result)->aopu.aop_dir,
9956 AOP(result)->aopu.aop_dir);
9958 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9959 AOP(result)->aopu.aop_dir,
9960 AOP(result)->aopu.aop_dir);
9964 /* the right is also a bit variable */
9965 if (AOP_TYPE(right) == AOP_CRY) {
9966 emitpcode(POC_BCF, popGet(AOP(result),0));
9967 emitpcode(POC_BTFSC, popGet(AOP(right),0));
9968 emitpcode(POC_BSF, popGet(AOP(result),0));
9970 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9971 AOP(result)->aopu.aop_dir,
9972 AOP(result)->aopu.aop_dir);
9973 pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
9974 AOP(right)->aopu.aop_dir,
9975 AOP(right)->aopu.aop_dir);
9976 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9977 AOP(result)->aopu.aop_dir,
9978 AOP(result)->aopu.aop_dir);
9983 emitpcode(POC_BCF, popGet(AOP(result),0));
9984 pic14_toBoolean(right);
9986 emitpcode(POC_BSF, popGet(AOP(result),0));
9987 //aopPut(AOP(result),"a",0);
9991 /* bit variables done */
9993 size = AOP_SIZE(result);
9995 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
9996 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9997 if(aopIdx(AOP(result),0) == 4) {
9998 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9999 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10000 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10003 DEBUGpic14_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
10009 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10010 if(AOP_TYPE(right) == AOP_LIT) {
10011 lit = (unsigned long)pic14aopLiteral(AOP(right)->aopu.aop_lit, offset) & 0x0ff;
10013 if(know_W != (int)(lit&0xff))
10014 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10016 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10018 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10020 } else if (AOP_TYPE(right) == AOP_CRY) {
10021 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10023 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10024 emitpcode(POC_INCF, popGet(AOP(result),0));
10027 mov2w_op (right, offset);
10028 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10036 freeAsmop (right,NULL,ic,FALSE);
10037 freeAsmop (result,NULL,ic,TRUE);
10040 /*-----------------------------------------------------------------*/
10041 /* genJumpTab - genrates code for jump table */
10042 /*-----------------------------------------------------------------*/
10043 static void genJumpTab (iCode *ic)
10049 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10051 aopOp(IC_JTCOND(ic),ic,FALSE);
10052 /* get the condition into accumulator */
10053 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10055 /* multiply by three */
10056 pic14_emitcode("add","a,acc");
10057 pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10059 jtab = newiTempLabel(NULL);
10060 pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10061 pic14_emitcode("jmp","@a+dptr");
10062 pic14_emitcode("","%05d_DS_:",jtab->key+100);
10064 emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10065 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10066 emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10067 emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10069 emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10070 emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10071 emitpLabel(jtab->key);
10073 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10075 /* now generate the jump labels */
10076 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10077 jtab = setNextItem(IC_JTLABELS(ic))) {
10078 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10079 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10085 /*-----------------------------------------------------------------*/
10086 /* genMixedOperation - gen code for operators between mixed types */
10087 /*-----------------------------------------------------------------*/
10089 TSD - Written for the PIC port - but this unfortunately is buggy.
10090 This routine is good in that it is able to efficiently promote
10091 types to different (larger) sizes. Unfortunately, the temporary
10092 variables that are optimized out by this routine are sometimes
10093 used in other places. So until I know how to really parse the
10094 iCode tree, I'm going to not be using this routine :(.
10096 static int genMixedOperation (iCode *ic)
10100 operand *result = IC_RESULT(ic);
10101 sym_link *ctype = operandType(IC_LEFT(ic));
10102 operand *right = IC_RIGHT(ic);
10108 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10110 pic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10116 nextright = IC_RIGHT(nextic);
10117 nextleft = IC_LEFT(nextic);
10118 nextresult = IC_RESULT(nextic);
10120 aopOp(right,ic,FALSE);
10121 aopOp(result,ic,FALSE);
10122 aopOp(nextright, nextic, FALSE);
10123 aopOp(nextleft, nextic, FALSE);
10124 aopOp(nextresult, nextic, FALSE);
10126 if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10128 operand *t = right;
10132 pic14_emitcode(";remove right +","");
10134 } else if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10136 operand *t = right;
10140 pic14_emitcode(";remove left +","");
10144 big = AOP_SIZE(nextleft);
10145 small = AOP_SIZE(nextright);
10147 switch(nextic->op) {
10150 pic14_emitcode(";optimize a +","");
10151 /* if unsigned or not an integral type */
10152 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10153 pic14_emitcode(";add a bit to something","");
10156 pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10158 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10159 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10160 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10162 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10170 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10171 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10172 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10175 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10177 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10178 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10179 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10180 pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10181 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10184 pic14_emitcode("rlf","known_zero,w");
10191 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10192 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10193 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10195 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10205 freeAsmop(right,NULL,ic,TRUE);
10206 freeAsmop(result,NULL,ic,TRUE);
10207 freeAsmop(nextright,NULL,ic,TRUE);
10208 freeAsmop(nextleft,NULL,ic,TRUE);
10210 nextic->generated = 1;
10217 /*-----------------------------------------------------------------*/
10218 /* genCast - gen code for casting */
10219 /*-----------------------------------------------------------------*/
10220 static void genCast (iCode *ic)
10222 operand *result = IC_RESULT(ic);
10223 sym_link *restype = operandType(result);
10224 sym_link *rtype = operandType(IC_RIGHT(ic));
10225 operand *right = IC_RIGHT(ic);
10229 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10230 /* if they are equivalent then do nothing */
10231 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10234 aopOp(right,ic,FALSE) ;
10235 aopOp(result,ic,FALSE);
10237 DEBUGpic14_AopType(__LINE__,NULL,right,result);
10239 /* if the result is a bit */
10240 if (AOP_TYPE(result) == AOP_CRY) {
10241 assert(!"assigning to bit variables is not supported");
10244 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10246 size = AOP_SIZE(result);
10248 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10250 emitpcode(POC_CLRF, popGet(AOP(result),0));
10251 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10252 emitpcode(POC_INCF, popGet(AOP(result),0));
10255 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
10260 if (IS_PTR(restype))
10262 operand *result = IC_RESULT(ic);
10263 //operand *left = IC_LEFT(ic);
10264 operand *right = IC_RIGHT(ic);
10267 /* copy common part */
10268 int max, size = AOP_SIZE(result);
10269 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10270 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10272 /* warn if we discard generic opinter tag */
10273 if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10275 //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10281 mov2w_op (right, size);
10282 movwf (AOP(result), size);
10285 /* upcast into generic pointer type? */
10286 if (IS_GENPTR(restype)
10287 && (size < AOP_SIZE(result))
10288 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10290 //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10293 switch (DCL_TYPE(rtype))
10295 case POINTER: /* __data */
10296 case FPOINTER: /* __data */
10297 assert (AOP_SIZE(right) == 2);
10298 tag = GPTRTAG_DATA;
10301 case CPOINTER: /* __code */
10302 assert (AOP_SIZE(right) == 2);
10303 tag = GPTRTAG_CODE;
10306 case GPOINTER: /* unknown destination, __data or __code */
10307 /* assume __data space (address of immediate) */
10308 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10309 if (AOP(right)->code)
10310 tag = GPTRTAG_CODE;
10312 tag = GPTRTAG_DATA;
10316 assert (!"unhandled pointer type");
10319 /* convert other values into pointers to __data space */
10320 tag = GPTRTAG_DATA;
10323 assert (AOP_SIZE(result) == 3);
10325 emitpcode(POC_CLRF, popGet(AOP(result), 2));
10327 emitpcode(POC_MOVLW, popGetLit(tag));
10328 movwf(AOP(result), 2);
10331 addSign(result, max, 0);
10336 /* if they are the same size : or less */
10337 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10339 /* if they are in the same place */
10340 if (pic14_sameRegs(AOP(right),AOP(result)))
10343 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10344 if (IS_PTR_CONST(rtype))
10345 DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10346 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10347 DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10349 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10350 emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10351 emitpcode(POC_MOVWF, popGet(AOP(result),0));
10352 emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10353 emitpcode(POC_MOVWF, popGet(AOP(result),1));
10354 if(AOP_SIZE(result) <2)
10355 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10359 /* if they in different places then copy */
10360 size = AOP_SIZE(result);
10363 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10364 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10366 //aopPut(AOP(result),
10367 // aopGet(AOP(right),offset,FALSE,FALSE),
10376 /* so we now know that the size of destination is greater
10377 than the size of the source.
10378 Now, if the next iCode is an operator then we might be
10379 able to optimize the operation without performing a cast.
10381 if(0 && genMixedOperation(ic)) {
10382 /* XXX: cannot optimize: must copy regs! */
10386 /* we move to result for the size of source */
10387 size = AOP_SIZE(right);
10390 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10391 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10395 addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10398 freeAsmop(right,NULL,ic,TRUE);
10399 freeAsmop(result,NULL,ic,TRUE);
10403 /*-----------------------------------------------------------------*/
10404 /* genDjnz - generate decrement & jump if not zero instrucion */
10405 /*-----------------------------------------------------------------*/
10406 static int genDjnz (iCode *ic, iCode *ifx)
10408 symbol *lbl, *lbl1;
10410 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10415 /* if the if condition has a false label
10416 then we cannot save */
10420 /* if the minus is not of the form
10422 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10423 !IS_OP_LITERAL(IC_RIGHT(ic)))
10426 if (operandLitValue(IC_RIGHT(ic)) != 1)
10429 /* if the size of this greater than one then no
10431 if (getSize(operandType(IC_RESULT(ic))) > 1)
10434 /* otherwise we can save BIG */
10435 lbl = newiTempLabel(NULL);
10436 lbl1= newiTempLabel(NULL);
10438 aopOp(IC_RESULT(ic),ic,FALSE);
10440 if (IS_AOP_PREG(IC_RESULT(ic))) {
10441 pic14_emitcode("dec","%s",
10442 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10443 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10444 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10448 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10449 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10451 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10452 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10455 /* pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10456 /* pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10457 /* pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10458 /* pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10461 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10462 ifx->generated = 1;
10466 /*-----------------------------------------------------------------*/
10467 /* genReceive - generate code for a receive iCode */
10468 /*-----------------------------------------------------------------*/
10469 static void genReceive (iCode *ic)
10472 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10474 if (isOperandInFarSpace(IC_RESULT(ic)) &&
10475 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10476 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10478 int size = getSize(operandType(IC_RESULT(ic)));
10479 int offset = fReturnSizePic - size;
10481 pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10482 fReturn[fReturnSizePic - offset - 1] : "acc"));
10485 aopOp(IC_RESULT(ic),ic,FALSE);
10486 size = AOP_SIZE(IC_RESULT(ic));
10489 pic14_emitcode ("pop","acc");
10490 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10495 aopOp(IC_RESULT(ic),ic,FALSE);
10497 GpsuedoStkPtr = ic->parmBytes; // address used arg on stack
10498 assignResultValue(IC_RESULT(ic));
10501 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10504 /*-----------------------------------------------------------------*/
10505 /* genDummyRead - generate code for dummy read of volatiles */
10506 /*-----------------------------------------------------------------*/
10508 genDummyRead (iCode * ic)
10511 pic14_emitcode ("; genDummyRead","");
10512 pic14_emitcode ("; not implemented","");
10517 /*-----------------------------------------------------------------*/
10518 /* genpic14Code - generate code for pic14 based controllers */
10519 /*-----------------------------------------------------------------*/
10521 * At this point, ralloc.c has gone through the iCode and attempted
10522 * to optimize in a way suitable for a PIC. Now we've got to generate
10523 * PIC instructions that correspond to the iCode.
10525 * Once the instructions are generated, we'll pass through both the
10526 * peep hole optimizer and the pCode optimizer.
10527 *-----------------------------------------------------------------*/
10529 void genpic14Code (iCode *lic)
10536 lineHead = lineCurr = NULL;
10538 pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10541 /* if debug information required */
10542 if (options.debug && currFunc) {
10544 debugFile->writeFunction (currFunc, lic);
10549 for (ic = lic ; ic ; ic = ic->next ) {
10551 //DEBUGpic14_emitcode(";ic","");
10552 //fprintf (stderr, "in ic loop\n");
10553 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10554 //ic->lineno, printCLine(ic->filename, ic->lineno));
10556 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10558 //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10559 cline = printCLine (ic->filename, ic->lineno);
10560 if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10561 addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10562 //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10565 if (options.iCodeInAsm) {
10566 char *iLine = printILine(ic);
10567 emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10570 /* if the result is marked as
10571 spilt and rematerializable or code for
10572 this has already been generated then
10574 if (resultRemat(ic) || ic->generated )
10577 /* depending on the operation */
10596 /* IPOP happens only when trying to restore a
10597 spilt live range, if there is an ifx statement
10598 following this pop then the if statement might
10599 be using some of the registers being popped which
10600 would destory the contents of the register so
10601 we need to check for this condition and handle it */
10603 ic->next->op == IFX &&
10604 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10605 genIfx (ic->next,ic);
10623 genEndFunction (ic);
10643 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10660 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
10664 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10671 /* note these two are xlated by algebraic equivalence
10672 during parsing SDCC.y */
10673 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10674 "got '>=' or '<=' shouldn't have come here");
10678 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10690 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10694 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10698 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10722 genRightShift (ic);
10725 case GET_VALUE_AT_ADDRESS:
10730 if (POINTER_SET(ic))
10757 addSet(&_G.sendSet,ic);
10760 case DUMMY_READ_VOLATILE:
10765 fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10772 /* now we are ready to call the
10773 peep hole optimizer */
10774 if (!options.nopeep) {
10775 peepHole (&lineHead);
10777 /* now do the actual printing */
10778 printLine (lineHead,codeOutBuf);
10781 DFPRINTF((stderr,"printing pBlock\n\n"));
10782 printpBlock(stdout,pb);
10788 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10789 * (meaning: representing its own address) or not (referencing its contents).
10790 * This can only be decided based on the operand's type. */
10792 aop_isLitLike (asmop *aop)
10795 if (aop->type == AOP_LIT) return 1;
10796 if (aop->type == AOP_IMMD) return 1;
10797 if ((aop->type == AOP_PCODE) &&
10798 ((aop->aopu.pcop->type == PO_LITERAL)))
10800 /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10801 * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10808 op_isLitLike (operand *op)
10811 if (aop_isLitLike (AOP(op))) return 1;
10812 if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10813 if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;