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);
1282 for (sym = setFirstItem (externs); sym; sym = setNextItem (externs))
1284 if (!strcmp (str, sym->rname)) break;
1289 sym = newSymbol(str, 0);
1290 strncpy(sym->rname, str, SDCC_NAME_MAX);
1291 addSet (&externs, sym);
1298 /*-----------------------------------------------------------------*/
1299 /* popRegFromString - */
1300 /*-----------------------------------------------------------------*/
1301 pCodeOp *popRegFromString(char *str, int size, int offset)
1304 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1305 pcop->type = PO_DIR;
1307 DEBUGpic14_emitcode(";","%d",__LINE__);
1312 pcop->name = Safe_calloc(1,strlen(str)+1);
1313 strcpy(pcop->name,str);
1315 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1317 PCOR(pcop)->r = dirregWithName(pcop->name);
1318 if(PCOR(pcop)->r == NULL) {
1319 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1320 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1321 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1323 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1325 PCOR(pcop)->instance = offset;
1330 /*-----------------------------------------------------------------*/
1331 /*-----------------------------------------------------------------*/
1332 pCodeOp *popRegFromIdx(int rIdx)
1336 DEBUGpic14_emitcode ("; ***","%s,%d , rIdx=0x%x",
1337 __FUNCTION__,__LINE__,rIdx);
1339 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1341 PCOR(pcop)->rIdx = rIdx;
1342 PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1343 PCOR(pcop)->r->isFree = 0;
1344 PCOR(pcop)->r->wasUsed = 1;
1346 pcop->type = PCOR(pcop)->r->pc_type;
1352 /*-----------------------------------------------------------------*/
1353 /* popGet - asm operator to pcode operator conversion */
1354 /*-----------------------------------------------------------------*/
1355 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1357 //char *s = buffer ;
1362 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1363 /* offset is greater than
1369 /* XXX: still needed for BIT operands (AOP_CRY) */
1370 if (offset > (aop->size - 1) &&
1371 aop->type != AOP_LIT &&
1372 aop->type != AOP_PCODE)
1374 printf( "%s: (offset[%d] > AOP_SIZE(op)[%d]-1) && AOP_TYPE(op) != AOP_LIT)\n", __FUNCTION__, offset, aop->size);
1375 return NULL; //zero;
1378 /* depending on type */
1379 switch (aop->type) {
1386 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1390 DEBUGpic14_emitcode(";","%d",__LINE__);
1391 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1394 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1396 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1397 pcop->type = PO_DIR;
1399 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1400 strcpy(pcop->name,aop->aopu.aop_dir);
1401 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1402 if(PCOR(pcop)->r == NULL) {
1403 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1404 PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1405 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1407 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1409 PCOR(pcop)->instance = offset;
1417 assert (offset < aop->size);
1418 rIdx = aop->aopu.aop_reg[offset]->rIdx;
1420 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1421 PCOR(pcop)->rIdx = rIdx;
1422 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1423 PCOR(pcop)->r->wasUsed=1;
1424 PCOR(pcop)->r->isFree=0;
1426 PCOR(pcop)->instance = offset;
1427 pcop->type = PCOR(pcop)->r->pc_type;
1428 //rs = aop->aopu.aop_reg[offset]->name;
1429 DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1434 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1435 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1436 //if(PCOR(pcop)->r == NULL)
1437 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1441 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1444 DEBUGpic14_emitcode(";","%d %s",__LINE__,aop->aopu.aop_str[offset]);
1445 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1447 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1448 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1449 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1450 pcop->type = PCOR(pcop)->r->pc_type;
1451 pcop->name = PCOR(pcop)->r->name;
1458 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1460 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1461 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1462 switch (aop->aopu.pcop->type)
1465 pcop = pCodeOpCopy (aop->aopu.pcop);
1466 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1467 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1468 PCOI(pcop)->index += offset;
1469 //PCOI(pcop)->offset = 0;
1472 pcop = pCodeOpCopy (aop->aopu.pcop);
1473 PCOR(pcop)->instance = offset;
1476 assert ( !"unhandled pCode type" );
1482 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1483 "popGet got unsupported aop->type");
1487 /*-----------------------------------------------------------------*/
1488 /* popGetAddr - access the low/high word of a symbol (immediate) */
1489 /* (for non-PO_IMMEDIATEs this is the same as popGet) */
1490 /*-----------------------------------------------------------------*/
1491 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1493 if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1495 pCodeOp *pcop = aop->aopu.pcop;
1496 assert (offset <= GPTRSIZE);
1498 /* special case: index >= 2 should return GPOINTER-style values */
1501 pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1505 pcop = pCodeOpCopy (pcop);
1506 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1507 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1508 PCOI(pcop)->offset += offset;
1509 PCOI(pcop)->index += index;
1510 //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);
1513 return popGet (aop, offset + index);
1517 /*-----------------------------------------------------------------*/
1518 /* aopPut - puts a string for a aop */
1519 /*-----------------------------------------------------------------*/
1520 void aopPut (asmop *aop, char *s, int offset)
1525 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1527 if (aop->size && offset > ( aop->size - 1)) {
1528 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1529 "aopPut got offset > aop->size");
1533 /* will assign value to value */
1534 /* depending on where it is ofcourse */
1535 switch (aop->type) {
1538 sprintf(d,"(%s + %d)",
1539 aop->aopu.aop_dir,offset);
1540 fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1543 sprintf(d,"%s",aop->aopu.aop_dir);
1546 DEBUGpic14_emitcode(";","%d",__LINE__);
1548 pic14_emitcode("movf","%s,w",s);
1549 pic14_emitcode("movwf","%s",d);
1552 pic14_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
1553 if(offset >= aop->size) {
1554 emitpcode(POC_CLRF,popGet(aop,offset));
1557 emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
1560 emitpcode(POC_MOVWF,popGet(aop,offset));
1566 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1567 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1570 strcmp(s,"r0") == 0 ||
1571 strcmp(s,"r1") == 0 ||
1572 strcmp(s,"r2") == 0 ||
1573 strcmp(s,"r3") == 0 ||
1574 strcmp(s,"r4") == 0 ||
1575 strcmp(s,"r5") == 0 ||
1576 strcmp(s,"r6") == 0 ||
1577 strcmp(s,"r7") == 0 )
1578 pic14_emitcode("mov","%s,%s ; %d",
1579 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1583 if(strcmp(s,"W")==0 )
1584 pic14_emitcode("movf","%s,w ; %d",s,__LINE__);
1586 pic14_emitcode("movwf","%s",
1587 aop->aopu.aop_reg[offset]->name);
1589 if(strcmp(s,zero)==0) {
1590 emitpcode(POC_CLRF,popGet(aop,offset));
1592 } else if(strcmp(s,"W")==0) {
1593 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1594 pcop->type = PO_GPR_REGISTER;
1596 PCOR(pcop)->rIdx = -1;
1597 PCOR(pcop)->r = NULL;
1599 DEBUGpic14_emitcode(";","%d",__LINE__);
1600 pcop->name = Safe_strdup(s);
1601 emitpcode(POC_MOVFW,pcop);
1602 emitpcode(POC_MOVWF,popGet(aop,offset));
1603 } else if(strcmp(s,one)==0) {
1604 emitpcode(POC_CLRF,popGet(aop,offset));
1605 emitpcode(POC_INCF,popGet(aop,offset));
1607 emitpcode(POC_MOVWF,popGet(aop,offset));
1615 if (aop->type == AOP_DPTR2)
1621 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1622 "aopPut writting to code space");
1626 while (offset > aop->coff) {
1628 pic14_emitcode ("inc","dptr");
1631 while (offset < aop->coff) {
1633 pic14_emitcode("lcall","__decdptr");
1638 /* if not in accumulater */
1641 pic14_emitcode ("movx","@dptr,a");
1643 if (aop->type == AOP_DPTR2)
1651 while (offset > aop->coff) {
1653 pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1655 while (offset < aop->coff) {
1657 pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1663 pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1668 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1670 if (strcmp(s,"r0") == 0 ||
1671 strcmp(s,"r1") == 0 ||
1672 strcmp(s,"r2") == 0 ||
1673 strcmp(s,"r3") == 0 ||
1674 strcmp(s,"r4") == 0 ||
1675 strcmp(s,"r5") == 0 ||
1676 strcmp(s,"r6") == 0 ||
1677 strcmp(s,"r7") == 0 ) {
1679 sprintf(buffer,"a%s",s);
1680 pic14_emitcode("mov","@%s,%s",
1681 aop->aopu.aop_ptr->name,buffer);
1683 pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1688 if (strcmp(s,"a") == 0)
1689 pic14_emitcode("push","acc");
1691 pic14_emitcode("push","%s",s);
1696 /* if bit variable */
1697 if (!aop->aopu.aop_dir) {
1698 pic14_emitcode("clr","a");
1699 pic14_emitcode("rlc","a");
1702 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1705 pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1708 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1710 lbl = newiTempLabel(NULL);
1712 if (strcmp(s,"a")) {
1715 pic14_emitcode("clr","c");
1716 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1717 pic14_emitcode("cpl","c");
1718 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1719 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1726 if (strcmp(aop->aopu.aop_str[offset],s))
1727 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1732 if (!offset && (strcmp(s,"acc") == 0))
1735 if (strcmp(aop->aopu.aop_str[offset],s))
1736 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1740 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1741 "aopPut got unsupported aop->type");
1747 /*-----------------------------------------------------------------*/
1748 /* mov2w_op - generate either a MOVLW or MOVFW based operand type */
1749 /*-----------------------------------------------------------------*/
1750 static void mov2w_op (operand *op, int offset)
1755 /* for PO_IMMEDIATEs: use address or value? */
1756 if (op_isLitLike (op))
1758 /* access address of op */
1759 if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
1760 if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
1762 if (offset == GPTRSIZE-1)
1763 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1765 emitpcode (POC_MOVLW, popGetLit (0));
1768 emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
1770 /* access value stored in op */
1771 mov2w (AOP(op), offset);
1776 /*-----------------------------------------------------------------*/
1777 /* mov2w - generate either a MOVLW or MOVFW based operand type */
1778 /*-----------------------------------------------------------------*/
1779 void mov2w (asmop *aop, int offset)
1785 DEBUGpic14_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
1787 if ( aop_isLitLike (aop) )
1788 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1790 emitpcode(POC_MOVFW,popGet(aop,offset));
1794 static void movwf (asmop *op, int offset)
1796 emitpcode (POC_MOVWF, popGet(op, offset));
1799 static pCodeOp *get_argument_pcop (int idx)
1801 assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1802 return popRegFromIdx (Gstack_base_addr - (idx - 1));
1805 static pCodeOp *get_return_val_pcop (int offset)
1807 assert (offset > 0 && "the most significant byte is returned via WREG");
1808 return popRegFromIdx (Gstack_base_addr - (offset - 1));
1811 static void pass_argument (operand *op, int offset, int idx)
1814 mov2w_op (op, offset);
1816 emitpcode(POC_MOVWF, get_argument_pcop (idx));
1819 static void get_returnvalue (operand *op, int offset, int idx)
1822 emitpcode(POC_MOVFW, get_return_val_pcop (idx));
1823 movwf(AOP(op), offset);
1826 static void call_libraryfunc (char *name)
1830 /* library code might reside in different page... */
1831 emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1832 /* call the library function */
1833 emitpcode (POC_CALL, popGetExternal (name));
1834 /* might return from different page... */
1835 emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1837 /* create symbol, mark it as `extern' */
1838 sym = findSym(SymbolTab, NULL, name);
1840 sym = newSymbol(name, 0);
1841 strncpy(sym->rname, name, SDCC_NAME_MAX);
1842 addSym(SymbolTab, sym, sym->rname, 0, 0, 0);
1843 addSet(&externs, sym);
1849 /*-----------------------------------------------------------------*/
1850 /* reAdjustPreg - points a register back to where it should */
1851 /*-----------------------------------------------------------------*/
1852 static void reAdjustPreg (asmop *aop)
1856 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1858 if ((size = aop->size) <= 1)
1861 switch (aop->type) {
1865 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1869 if (aop->type == AOP_DPTR2)
1875 pic14_emitcode("lcall","__decdptr");
1878 if (aop->type == AOP_DPTR2)
1891 /*-----------------------------------------------------------------*/
1892 /* opIsGptr: returns non-zero if the passed operand is */
1893 /* a generic pointer type. */
1894 /*-----------------------------------------------------------------*/
1895 static int opIsGptr(operand *op)
1897 sym_link *type = operandType(op);
1899 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1900 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1908 /*-----------------------------------------------------------------*/
1909 /* pic14_getDataSize - get the operand data size */
1910 /*-----------------------------------------------------------------*/
1911 int pic14_getDataSize(operand *op)
1915 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1918 size = getSize(OP_SYM_ETYPE(op));
1920 //return AOP_SIZE(op);
1922 // tsd- in the pic port, the genptr size is 1, so this code here
1923 // fails. ( in the 8051 port, the size was 4).
1925 size = AOP_SIZE(op);
1926 if (IS_GENPTR(OP_SYM_TYPE(op)))
1928 sym_link *type = operandType(op);
1929 if (IS_GENPTR(type))
1931 /* generic pointer; arithmetic operations
1932 * should ignore the high byte (pointer type).
1935 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1942 /*-----------------------------------------------------------------*/
1943 /* pic14_outAcc - output Acc */
1944 /*-----------------------------------------------------------------*/
1945 void pic14_outAcc(operand *result)
1948 DEBUGpic14_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
1949 DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1952 size = pic14_getDataSize(result);
1954 emitpcode(POC_MOVWF,popGet(AOP(result),0));
1957 /* unsigned or positive */
1959 emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1964 /*-----------------------------------------------------------------*/
1965 /* pic14_outBitC - output a bit C */
1966 /*-----------------------------------------------------------------*/
1967 void pic14_outBitC(operand *result)
1970 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1971 /* if the result is bit */
1972 if (AOP_TYPE(result) == AOP_CRY)
1973 aopPut(AOP(result),"c",0);
1975 pic14_emitcode("clr","a ; %d", __LINE__);
1976 pic14_emitcode("rlc","a");
1977 pic14_outAcc(result);
1981 /*-----------------------------------------------------------------*/
1982 /* pic14_toBoolean - emit code for orl a,operator(sizeop) */
1983 /*-----------------------------------------------------------------*/
1984 void pic14_toBoolean(operand *oper)
1986 int size = AOP_SIZE(oper);
1989 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1994 /* MOVFW does not load the flags... */
1995 if (AOP_TYPE(oper) == AOP_ACC) {
1996 emitpcode(POC_IORLW, popGetLit(0));
1999 emitpcode(POC_MOVLW, popGetLit(0));
2003 if ( AOP_TYPE(oper) != AOP_ACC) {
2004 emitpcode(POC_MOVFW,popGet(AOP(oper),0));
2009 while (offset < size) {
2010 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
2012 /* Z is set iff (oper == 0) */
2016 /*-----------------------------------------------------------------*/
2017 /* genNot - generate code for ! operation */
2018 /*-----------------------------------------------------------------*/
2019 static void genNot (iCode *ic)
2026 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2027 /* assign asmOps to operand & result */
2028 aopOp (IC_LEFT(ic),ic,FALSE);
2029 aopOp (IC_RESULT(ic),ic,TRUE);
2031 DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2032 /* if in bit space then a special case */
2033 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2034 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2035 emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
2036 emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
2038 emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
2039 emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
2040 emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
2045 size = AOP_SIZE(IC_LEFT(ic));
2046 mov2w (AOP(IC_LEFT(ic)),0);
2049 if (op_isLitLike (IC_LEFT(ic)))
2050 emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
2052 emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
2054 emitpcode(POC_MOVLW, popGetLit (0));
2056 emitpcode(POC_MOVLW, popGetLit (1));
2057 movwf(AOP(IC_RESULT(ic)), 0);
2059 for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
2061 emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
2066 /* release the aops */
2067 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2068 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2072 /*-----------------------------------------------------------------*/
2073 /* genCpl - generate code for complement */
2074 /*-----------------------------------------------------------------*/
2075 static void genCpl (iCode *ic)
2077 operand *left, *result;
2082 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2083 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2084 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2086 /* if both are in bit space then
2088 if (AOP_TYPE(result) == AOP_CRY &&
2089 AOP_TYPE(left) == AOP_CRY ) {
2091 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir);
2092 pic14_emitcode("cpl","c");
2093 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir);
2097 size = AOP_SIZE(result);
2098 if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
2101 if(AOP_TYPE(left) == AOP_ACC)
2102 emitpcode(POC_XORLW, popGetLit(0xff));
2104 emitpcode(POC_COMFW,popGet(AOP(left),offset));
2106 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
2109 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2113 /* release the aops */
2114 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2115 freeAsmop(result,NULL,ic,TRUE);
2118 /*-----------------------------------------------------------------*/
2119 /* genUminusFloat - unary minus for floating points */
2120 /*-----------------------------------------------------------------*/
2121 static void genUminusFloat(operand *op,operand *result)
2123 int size ,offset =0 ;
2128 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2129 /* for this we just need to flip the
2130 first it then copy the rest in place */
2131 size = AOP_SIZE(op) - 1;
2132 l = aopGet(AOP(op),3,FALSE,FALSE);
2136 pic14_emitcode("cpl","acc.7");
2137 aopPut(AOP(result),"a",3);
2141 aopGet(AOP(op),offset,FALSE,FALSE),
2147 /*-----------------------------------------------------------------*/
2148 /* genUminus - unary minus code generation */
2149 /*-----------------------------------------------------------------*/
2150 static void genUminus (iCode *ic)
2153 sym_link *optype, *rtype;
2157 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2159 aopOp(IC_LEFT(ic),ic,FALSE);
2160 aopOp(IC_RESULT(ic),ic,TRUE);
2162 /* if both in bit space then special
2164 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2165 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2167 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0));
2168 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2169 emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0));
2174 optype = operandType(IC_LEFT(ic));
2175 rtype = operandType(IC_RESULT(ic));
2177 /* if float then do float stuff */
2178 if (IS_FLOAT(optype)) {
2179 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2183 /* otherwise subtract from zero by taking the 2's complement */
2184 size = AOP_SIZE(IC_LEFT(ic));
2186 for(i=0; i<size; i++) {
2187 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2188 emitpcode(POC_COMF, popGet(AOP(IC_LEFT(ic)),i));
2190 emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2191 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2195 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0));
2196 for(i=1; i<size; i++) {
2198 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),i));
2202 /* release the aops */
2203 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2204 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2207 /*-----------------------------------------------------------------*/
2208 /* saveRegisters - will look for a call and save the registers */
2209 /*-----------------------------------------------------------------*/
2210 static void saveRegisters(iCode *lic)
2219 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2221 for (ic = lic ; ic ; ic = ic->next)
2222 if (ic->op == CALL || ic->op == PCALL)
2226 fprintf(stderr,"found parameter push with no function call\n");
2230 /* if the registers have been saved already then
2232 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2235 /* find the registers in use at this time
2236 and push them away to safety */
2237 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2241 if (options.useXstack) {
2242 if (bitVectBitValue(rsave,R0_IDX))
2243 pic14_emitcode("mov","b,r0");
2244 pic14_emitcode("mov","r0,%s",spname);
2245 for (i = 0 ; i < pic14_nRegs ; i++) {
2246 if (bitVectBitValue(rsave,i)) {
2248 pic14_emitcode("mov","a,b");
2250 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2251 pic14_emitcode("movx","@r0,a");
2252 pic14_emitcode("inc","r0");
2255 pic14_emitcode("mov","%s,r0",spname);
2256 if (bitVectBitValue(rsave,R0_IDX))
2257 pic14_emitcode("mov","r0,b");
2259 //for (i = 0 ; i < pic14_nRegs ; i++) {
2260 // if (bitVectBitValue(rsave,i))
2261 // pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2264 dtype = operandType(IC_LEFT(ic));
2265 if (currFunc && dtype &&
2266 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2267 IFFUNC_ISISR(currFunc->type) &&
2270 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2273 /*-----------------------------------------------------------------*/
2274 /* unsaveRegisters - pop the pushed registers */
2275 /*-----------------------------------------------------------------*/
2276 static void unsaveRegisters (iCode *ic)
2283 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2284 /* find the registers in use at this time
2285 and push them away to safety */
2286 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2289 if (options.useXstack) {
2290 pic14_emitcode("mov","r0,%s",spname);
2291 for (i = pic14_nRegs ; i >= 0 ; i--) {
2292 if (bitVectBitValue(rsave,i)) {
2293 pic14_emitcode("dec","r0");
2294 pic14_emitcode("movx","a,@r0");
2296 pic14_emitcode("mov","b,a");
2298 pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2302 pic14_emitcode("mov","%s,r0",spname);
2303 if (bitVectBitValue(rsave,R0_IDX))
2304 pic14_emitcode("mov","r0,b");
2306 //for (i = pic14_nRegs ; i >= 0 ; i--) {
2307 // if (bitVectBitValue(rsave,i))
2308 // pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2314 /*-----------------------------------------------------------------*/
2316 /*-----------------------------------------------------------------*/
2317 static void pushSide(operand * oper, int size)
2321 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2323 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2324 if (AOP_TYPE(oper) != AOP_REG &&
2325 AOP_TYPE(oper) != AOP_DIR &&
2327 pic14_emitcode("mov","a,%s",l);
2328 pic14_emitcode("push","acc");
2330 pic14_emitcode("push","%s",l);
2335 /*-----------------------------------------------------------------*/
2336 /* assignResultValue - */
2337 /*-----------------------------------------------------------------*/
2338 static void assignResultValue(operand * oper)
2340 int size = AOP_SIZE(oper);
2345 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2347 DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2349 /* assign MSB first (passed via WREG) */
2351 get_returnvalue (oper, size, offset + GpsuedoStkPtr);
2357 /*-----------------------------------------------------------------*/
2358 /* genIpush - genrate code for pushing this gets a little complex */
2359 /*-----------------------------------------------------------------*/
2360 static void genIpush (iCode *ic)
2364 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2366 int size, offset = 0 ;
2370 /* if this is not a parm push : ie. it is spill push
2371 and spill push is always done on the local stack */
2372 if (!ic->parmPush) {
2374 /* and the item is spilt then do nothing */
2375 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2378 aopOp(IC_LEFT(ic),ic,FALSE);
2379 size = AOP_SIZE(IC_LEFT(ic));
2380 /* push it on the stack */
2382 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2387 pic14_emitcode("push","%s",l);
2392 /* this is a paramter push: in this case we call
2393 the routine to find the call and save those
2394 registers that need to be saved */
2397 /* then do the push */
2398 aopOp(IC_LEFT(ic),ic,FALSE);
2401 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2402 size = AOP_SIZE(IC_LEFT(ic));
2405 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2406 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
2407 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2409 pic14_emitcode("mov","a,%s",l);
2410 pic14_emitcode("push","acc");
2412 pic14_emitcode("push","%s",l);
2415 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2419 /*-----------------------------------------------------------------*/
2420 /* genIpop - recover the registers: can happen only for spilling */
2421 /*-----------------------------------------------------------------*/
2422 static void genIpop (iCode *ic)
2426 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2427 assert (!"genIpop -- unimplemented");
2432 /* if the temp was not pushed then */
2433 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2436 aopOp(IC_LEFT(ic),ic,FALSE);
2437 size = AOP_SIZE(IC_LEFT(ic));
2440 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2443 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2447 /*-----------------------------------------------------------------*/
2448 /* unsaverbank - restores the resgister bank from stack */
2449 /*-----------------------------------------------------------------*/
2450 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2454 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2460 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2462 if (options.useXstack) {
2464 r = getFreePtr(ic,&aop,FALSE);
2467 pic14_emitcode("mov","%s,_spx",r->name);
2468 pic14_emitcode("movx","a,@%s",r->name);
2469 pic14_emitcode("mov","psw,a");
2470 pic14_emitcode("dec","%s",r->name);
2473 pic14_emitcode ("pop","psw");
2476 for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2477 if (options.useXstack) {
2478 pic14_emitcode("movx","a,@%s",r->name);
2479 //pic14_emitcode("mov","(%s+%d),a",
2480 // regspic14[i].base,8*bank+regspic14[i].offset);
2481 pic14_emitcode("dec","%s",r->name);
2484 pic14_emitcode("pop",""); //"(%s+%d)",
2485 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2488 if (options.useXstack) {
2490 pic14_emitcode("mov","_spx,%s",r->name);
2491 freeAsmop(NULL,aop,ic,TRUE);
2497 /*-----------------------------------------------------------------*/
2498 /* saverbank - saves an entire register bank on the stack */
2499 /*-----------------------------------------------------------------*/
2500 static void saverbank (int bank, iCode *ic, bool pushPsw)
2504 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2510 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2511 if (options.useXstack) {
2514 r = getFreePtr(ic,&aop,FALSE);
2515 pic14_emitcode("mov","%s,_spx",r->name);
2519 for (i = 0 ; i < pic14_nRegs ;i++) {
2520 if (options.useXstack) {
2521 pic14_emitcode("inc","%s",r->name);
2522 //pic14_emitcode("mov","a,(%s+%d)",
2523 // regspic14[i].base,8*bank+regspic14[i].offset);
2524 pic14_emitcode("movx","@%s,a",r->name);
2526 pic14_emitcode("push","");// "(%s+%d)",
2527 //regspic14[i].base,8*bank+regspic14[i].offset);
2531 if (options.useXstack) {
2532 pic14_emitcode("mov","a,psw");
2533 pic14_emitcode("movx","@%s,a",r->name);
2534 pic14_emitcode("inc","%s",r->name);
2535 pic14_emitcode("mov","_spx,%s",r->name);
2536 freeAsmop (NULL,aop,ic,TRUE);
2539 pic14_emitcode("push","psw");
2541 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2547 /*-----------------------------------------------------------------*/
2548 /* genCall - generates a call statement */
2549 /*-----------------------------------------------------------------*/
2550 static void genCall (iCode *ic)
2559 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2561 /* if caller saves & we have not saved then */
2565 /* if we are calling a function that is not using
2566 the same register bank then we need to save the
2567 destination registers on the stack */
2568 dtype = operandType(IC_LEFT(ic));
2569 if (currFunc && dtype &&
2570 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2571 IFFUNC_ISISR(currFunc->type) &&
2574 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2576 /* if send set is not empty the assign */
2579 /* For the Pic port, there is no data stack.
2580 * So parameters passed to functions are stored
2581 * in registers. (The pCode optimizer will get
2582 * rid of most of these :).
2584 int psuedoStkPtr=-1;
2585 int firstTimeThruLoop = 1;
2587 _G.sendSet = reverseSet(_G.sendSet);
2589 /* First figure how many parameters are getting passed */
2590 for (sic = setFirstItem(_G.sendSet) ; sic ;
2591 sic = setNextItem(_G.sendSet)) {
2593 aopOp(IC_LEFT(sic),sic,FALSE);
2594 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2595 freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2598 for (sic = setFirstItem(_G.sendSet) ; sic ;
2599 sic = setNextItem(_G.sendSet)) {
2600 int size, offset = 0;
2602 aopOp(IC_LEFT(sic),sic,FALSE);
2603 size = AOP_SIZE(IC_LEFT(sic));
2606 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2607 AopType(AOP_TYPE(IC_LEFT(sic))));
2609 if(!firstTimeThruLoop) {
2610 /* If this is not the first time we've been through the loop
2611 * then we need to save the parameter in a temporary
2612 * register. The last byte of the last parameter is
2614 emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2617 firstTimeThruLoop=0;
2619 mov2w_op (IC_LEFT(sic), offset);
2622 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2627 sym = OP_SYMBOL(IC_LEFT(ic));
2628 name = sym->rname[0] ? sym->rname : sym->name;
2629 isExtern = IS_EXTERN(sym->etype) || pic14_inISR;
2631 /* Extern functions and ISRs maybe on a different page;
2632 * must call pagesel */
2633 emitpcode(POC_PAGESEL,popGetWithString(name,1));
2635 emitpcode(POC_CALL,popGetWithString(name,isExtern));
2637 /* May have returned from a different page;
2638 * must use pagesel to restore PCLATH before next
2639 * goto or call instruction */
2640 emitpcode(POC_PAGESEL,popGetWithString("$",0));
2643 /* if we need assign a result value */
2644 if ((IS_ITEMP(IC_RESULT(ic)) &&
2645 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2646 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2647 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2650 aopOp(IC_RESULT(ic),ic,FALSE);
2653 assignResultValue(IC_RESULT(ic));
2655 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2656 AopType(AOP_TYPE(IC_RESULT(ic))));
2658 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2661 /* if register bank was saved then pop them */
2663 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2665 /* if we hade saved some registers then unsave them */
2666 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2667 unsaveRegisters (ic);
2672 /*-----------------------------------------------------------------*/
2673 /* genPcall - generates a call by pointer statement */
2674 /*-----------------------------------------------------------------*/
2675 static void genPcall (iCode *ic)
2678 symbol *albl = newiTempLabel(NULL);
2679 symbol *blbl = newiTempLabel(NULL);
2686 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2687 /* if caller saves & we have not saved then */
2691 /* if we are calling a function that is not using
2692 the same register bank then we need to save the
2693 destination registers on the stack */
2694 dtype = operandType(IC_LEFT(ic));
2695 if (currFunc && dtype &&
2696 IFFUNC_ISISR(currFunc->type) &&
2697 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2698 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2701 aopOp(left,ic,FALSE);
2702 DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2704 poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2706 pushSide(IC_LEFT(ic), FPTRSIZE);
2708 /* if send set is not empty, assign parameters */
2711 DEBUGpic14_emitcode ("; ***","%s %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2712 /* no way to pass args - W always gets used to make the call */
2714 /* first idea - factor out a common helper function and call it.
2715 But don't know how to get it generated only once in its own block
2717 if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2720 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2721 DEBUGpic14_emitcode ("; ***","%s %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2722 buffer = Safe_calloc(1,strlen(rname)+16);
2723 sprintf(buffer, "%s_goto_helper", rname);
2724 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2728 emitpcode(POC_CALL,popGetLabel(albl->key));
2729 pcop = popGetLabel(blbl->key);
2730 emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
2731 emitpcode(POC_GOTO,pcop);
2732 emitpLabel(albl->key);
2734 emitpcode(poc,popGetAddr(AOP(left),1,0));
2735 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2736 emitpcode(poc,popGetAddr(AOP(left),0,0));
2737 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2739 emitpLabel(blbl->key);
2741 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2743 /* if we need to assign a result value */
2744 if ((IS_ITEMP(IC_RESULT(ic)) &&
2745 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2746 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2747 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2750 aopOp(IC_RESULT(ic),ic,FALSE);
2755 assignResultValue(IC_RESULT(ic));
2757 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2760 /* if register bank was saved then unsave them */
2761 if (currFunc && dtype &&
2762 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2763 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2765 /* if we hade saved some registers then
2768 unsaveRegisters (ic);
2772 /*-----------------------------------------------------------------*/
2773 /* resultRemat - result is rematerializable */
2774 /*-----------------------------------------------------------------*/
2775 static int resultRemat (iCode *ic)
2777 // DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2780 if (SKIP_IC(ic) || ic->op == IFX)
2783 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2784 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2785 if (sym->remat && !POINTER_SET(ic))
2793 /*-----------------------------------------------------------------*/
2794 /* inExcludeList - return 1 if the string is in exclude Reg list */
2795 /*-----------------------------------------------------------------*/
2796 static bool inExcludeList(char *s)
2798 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2801 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2802 if (options.excludeRegs[i] &&
2803 STRCASECMP(options.excludeRegs[i],"none") == 0)
2806 for ( i = 0 ; options.excludeRegs[i]; i++) {
2807 if (options.excludeRegs[i] &&
2808 STRCASECMP(s,options.excludeRegs[i]) == 0)
2815 /*-----------------------------------------------------------------*/
2816 /* genFunction - generated code for function entry */
2817 /*-----------------------------------------------------------------*/
2818 static void genFunction (iCode *ic)
2825 DEBUGpic14_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2827 labelOffset += (max_key+4);
2831 /* create the function header */
2832 pic14_emitcode(";","-----------------------------------------");
2833 pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2834 pic14_emitcode(";","-----------------------------------------");
2836 /* prevent this symbol from being emitted as 'extern' */
2837 pic14_stringInSet(sym->rname, &pic14_localFunctions, 1);
2839 pic14_emitcode("","%s:",sym->rname);
2840 addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2842 /* mark symbol as NOT extern (even if it was declared so previously) */
2843 assert(IS_SPEC(sym->etype));
2844 SPEC_EXTR(sym->etype) = 0;
2846 if (!SPEC_OCLS(sym->etype)) SPEC_OCLS(sym->etype) = code;
2847 addSetIfnotP(&SPEC_OCLS(sym->etype)->syms, sym);
2849 ftype = operandType(IC_LEFT(ic));
2851 /* if critical function then turn interrupts off */
2852 if (IFFUNC_ISCRITICAL(ftype))
2853 pic14_emitcode("clr","ea");
2855 /* here we need to generate the equates for the
2856 register bank if required */
2858 if (FUNC_REGBANK(ftype) != rbank) {
2861 rbank = FUNC_REGBANK(ftype);
2862 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2863 if (strcmp(regspic14[i].base,"0") == 0)
2864 pic14_emitcode("","%s = 0x%02x",
2866 8*rbank+regspic14[i].offset);
2868 pic14_emitcode ("","%s = %s + 0x%02x",
2871 8*rbank+regspic14[i].offset);
2876 /* if this is an interrupt service routine */
2878 if (IFFUNC_ISISR(sym->type)) {
2880 /* already done in pic14createInterruptVect() - delete me
2881 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2882 emitpcodeNULLop(POC_NOP);
2883 emitpcodeNULLop(POC_NOP);
2884 emitpcodeNULLop(POC_NOP);
2886 emitpcode(POC_MOVWF, popCopyReg(&pc_wsave));
2887 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2888 emitpcode(POC_CLRF, popCopyReg(&pc_status));
2889 emitpcode(POC_MOVWF, popCopyReg(&pc_ssave));
2890 emitpcode(POC_MOVFW, popCopyReg(&pc_pclath));
2891 emitpcode(POC_MOVWF, popCopyReg(&pc_psave));
2892 emitpcode(POC_CLRF, popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2894 pBlockConvert2ISR(pb);
2895 pic14_hasInterrupt = 1;
2897 if (!inExcludeList("acc"))
2898 pic14_emitcode ("push","acc");
2899 if (!inExcludeList("b"))
2900 pic14_emitcode ("push","b");
2901 if (!inExcludeList("dpl"))
2902 pic14_emitcode ("push","dpl");
2903 if (!inExcludeList("dph"))
2904 pic14_emitcode ("push","dph");
2905 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2907 pic14_emitcode ("push", "dpx");
2908 /* Make sure we're using standard DPTR */
2909 pic14_emitcode ("push", "dps");
2910 pic14_emitcode ("mov", "dps, #0x00");
2911 if (options.stack10bit)
2913 /* This ISR could conceivably use DPTR2. Better save it. */
2914 pic14_emitcode ("push", "dpl1");
2915 pic14_emitcode ("push", "dph1");
2916 pic14_emitcode ("push", "dpx1");
2919 /* if this isr has no bank i.e. is going to
2920 run with bank 0 , then we need to save more
2922 if (!FUNC_REGBANK(sym->type)) {
2924 /* if this function does not call any other
2925 function then we can be economical and
2926 save only those registers that are used */
2927 if (! IFFUNC_HASFCALL(sym->type)) {
2930 /* if any registers used */
2931 if (sym->regsUsed) {
2932 /* save the registers used */
2933 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2934 if (bitVectBitValue(sym->regsUsed,i) ||
2935 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2936 pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);
2941 /* this function has a function call cannot
2942 determines register usage so we will have the
2944 saverbank(0,ic,FALSE);
2949 /* if callee-save to be used for this function
2950 then save the registers being used in this function */
2951 if (IFFUNC_CALLEESAVES(sym->type)) {
2954 /* if any registers used */
2955 if (sym->regsUsed) {
2956 /* save the registers used */
2957 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2958 if (bitVectBitValue(sym->regsUsed,i) ||
2959 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2960 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2968 /* set the register bank to the desired value */
2969 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2970 pic14_emitcode("push","psw");
2971 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);
2974 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2976 if (options.useXstack) {
2977 pic14_emitcode("mov","r0,%s",spname);
2978 pic14_emitcode("mov","a,_bp");
2979 pic14_emitcode("movx","@r0,a");
2980 pic14_emitcode("inc","%s",spname);
2984 /* set up the stack */
2985 pic14_emitcode ("push","_bp"); /* save the callers stack */
2987 pic14_emitcode ("mov","_bp,%s",spname);
2990 /* adjust the stack for the function */
2995 werror(W_STACK_OVERFLOW,sym->name);
2997 if (i > 3 && sym->recvSize < 4) {
2999 pic14_emitcode ("mov","a,sp");
3000 pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3001 pic14_emitcode ("mov","sp,a");
3006 pic14_emitcode("inc","sp");
3011 pic14_emitcode ("mov","a,_spx");
3012 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3013 pic14_emitcode ("mov","_spx,a");
3018 /*-----------------------------------------------------------------*/
3019 /* genEndFunction - generates epilogue for functions */
3020 /*-----------------------------------------------------------------*/
3021 static void genEndFunction (iCode *ic)
3023 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3027 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3029 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3031 pic14_emitcode ("mov","%s,_bp",spname);
3034 /* if use external stack but some variables were
3035 added to the local stack then decrement the
3037 if (options.useXstack && sym->stack) {
3038 pic14_emitcode("mov","a,sp");
3039 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3040 pic14_emitcode("mov","sp,a");
3044 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3045 if (options.useXstack) {
3046 pic14_emitcode("mov","r0,%s",spname);
3047 pic14_emitcode("movx","a,@r0");
3048 pic14_emitcode("mov","_bp,a");
3049 pic14_emitcode("dec","%s",spname);
3053 pic14_emitcode ("pop","_bp");
3057 /* restore the register bank */
3058 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3059 pic14_emitcode ("pop","psw");
3061 if (IFFUNC_ISISR(sym->type)) {
3063 /* now we need to restore the registers */
3064 /* if this isr has no bank i.e. is going to
3065 run with bank 0 , then we need to save more
3067 if (!FUNC_REGBANK(sym->type)) {
3069 /* if this function does not call any other
3070 function then we can be economical and
3071 save only those registers that are used */
3072 if (! IFFUNC_HASFCALL(sym->type)) {
3075 /* if any registers used */
3076 if (sym->regsUsed) {
3077 /* save the registers used */
3078 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3079 if (bitVectBitValue(sym->regsUsed,i) ||
3080 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3081 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3086 /* this function has a function call cannot
3087 determines register usage so we will have the
3089 unsaverbank(0,ic,FALSE);
3093 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3095 if (options.stack10bit)
3097 pic14_emitcode ("pop", "dpx1");
3098 pic14_emitcode ("pop", "dph1");
3099 pic14_emitcode ("pop", "dpl1");
3101 pic14_emitcode ("pop", "dps");
3102 pic14_emitcode ("pop", "dpx");
3104 if (!inExcludeList("dph"))
3105 pic14_emitcode ("pop","dph");
3106 if (!inExcludeList("dpl"))
3107 pic14_emitcode ("pop","dpl");
3108 if (!inExcludeList("b"))
3109 pic14_emitcode ("pop","b");
3110 if (!inExcludeList("acc"))
3111 pic14_emitcode ("pop","acc");
3113 if (IFFUNC_ISCRITICAL(sym->type))
3114 pic14_emitcode("setb","ea");
3117 /* if debug then send end of function */
3118 /* if (options.debug && currFunc) { */
3120 debugFile->writeEndFunction (currFunc, ic, 1);
3123 pic14_emitcode ("reti","");
3124 emitpcode(POC_MOVFW, popCopyReg(&pc_psave));
3125 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
3126 emitpcode(POC_CLRF, popCopyReg(&pc_status));
3127 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3128 emitpcode(POC_MOVWF, popCopyReg(&pc_status));
3129 emitpcode(POC_SWAPF, popCopyReg(&pc_wsave));
3130 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3131 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3132 emitpcodeNULLop(POC_RETFIE);
3135 if (IFFUNC_ISCRITICAL(sym->type))
3136 pic14_emitcode("setb","ea");
3138 if (IFFUNC_CALLEESAVES(sym->type)) {
3141 /* if any registers used */
3142 if (sym->regsUsed) {
3143 /* save the registers used */
3144 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3145 if (bitVectBitValue(sym->regsUsed,i) ||
3146 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3147 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3153 /* if debug then send end of function */
3155 debugFile->writeEndFunction (currFunc, ic, 1);
3158 pic14_emitcode ("return","");
3159 emitpcodeNULLop(POC_RETURN);
3161 /* Mark the end of a function */
3162 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3167 /*-----------------------------------------------------------------*/
3168 /* genRet - generate code for return statement */
3169 /*-----------------------------------------------------------------*/
3170 static void genRet (iCode *ic)
3172 int size,offset = 0;
3176 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3177 /* if we have no return value then
3178 just generate the "ret" */
3182 /* we have something to return then
3183 move the return value into place */
3184 aopOp(IC_LEFT(ic),ic,FALSE);
3185 size = AOP_SIZE(IC_LEFT(ic));
3187 for (offset = 0; offset < size; offset++)
3189 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
3192 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3195 /* generate a jump to the return label
3196 if the next is not the return statement */
3197 if (!(ic->next && ic->next->op == LABEL &&
3198 IC_LABEL(ic->next) == returnLabel)) {
3200 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3205 /*-----------------------------------------------------------------*/
3206 /* genLabel - generates a label */
3207 /*-----------------------------------------------------------------*/
3208 static void genLabel (iCode *ic)
3212 /* special case never generate */
3213 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3214 if (IC_LABEL(ic) == entryLabel)
3217 emitpLabel(IC_LABEL(ic)->key);
3218 pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3221 /*-----------------------------------------------------------------*/
3222 /* genGoto - generates a goto */
3223 /*-----------------------------------------------------------------*/
3225 static void genGoto (iCode *ic)
3229 emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3230 pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3234 /*-----------------------------------------------------------------*/
3235 /* genMultbits :- multiplication of bits */
3236 /*-----------------------------------------------------------------*/
3237 static void genMultbits (operand *left,
3242 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3244 if(!pic14_sameRegs(AOP(result),AOP(right)))
3245 emitpcode(POC_BSF, popGet(AOP(result),0));
3247 emitpcode(POC_BTFSC,popGet(AOP(right),0));
3248 emitpcode(POC_BTFSS,popGet(AOP(left),0));
3249 emitpcode(POC_BCF, popGet(AOP(result),0));
3254 /*-----------------------------------------------------------------*/
3255 /* genMultOneByte : 8 bit multiplication & division */
3256 /*-----------------------------------------------------------------*/
3257 static void genMultOneByte (operand *left,
3261 char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
3269 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3270 DEBUGpic14_AopType(__LINE__,left,right,result);
3271 DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3273 /* (if two literals, the value is computed before) */
3274 /* if one literal, literal on the right */
3275 if (AOP_TYPE(left) == AOP_LIT){
3281 assert (AOP_SIZE(left) == AOP_SIZE(right));
3283 size = min(AOP_SIZE(result),AOP_SIZE(left));
3284 offset = Gstack_base_addr - (2*size - 1);
3286 /* pass right operand as argument */
3287 for (i=0; i < size; i++)
3289 mov2w (AOP(right), i);
3290 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3293 /* pass left operand as argument */
3294 for (i=0; i < size; i++)
3296 mov2w (AOP(left), i);
3297 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3299 assert (offset == Gstack_base_addr);
3301 /* call library routine */
3302 assert (size > 0 && size <= 4);
3303 call_libraryfunc (func[size]);
3306 movwf (AOP(result), size-1);
3307 for (i=0; i < size - 1; i++)
3309 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
3310 movwf (AOP(result), size - 2 - i);
3313 /* now (zero-/sign) extend the result to its size */
3314 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
3317 /*-----------------------------------------------------------------*/
3318 /* genMult - generates code for multiplication */
3319 /*-----------------------------------------------------------------*/
3320 static void genMult (iCode *ic)
3322 operand *left = IC_LEFT(ic);
3323 operand *right = IC_RIGHT(ic);
3324 operand *result= IC_RESULT(ic);
3328 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3329 /* assign the amsops */
3330 aopOp (left,ic,FALSE);
3331 aopOp (right,ic,FALSE);
3332 aopOp (result,ic,TRUE);
3334 DEBUGpic14_AopType(__LINE__,left,right,result);
3336 /* special cases first */
3338 if (AOP_TYPE(left) == AOP_CRY &&
3339 AOP_TYPE(right)== AOP_CRY) {
3340 genMultbits(left,right,result);
3344 /* if both are of size == 1 */
3345 if (AOP_SIZE(left) == 1 &&
3346 AOP_SIZE(right) == 1 ) {
3347 genMultOneByte(left,right,result);
3351 /* should have been converted to function call */
3355 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3356 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3357 freeAsmop(result,NULL,ic,TRUE);
3360 /*-----------------------------------------------------------------*/
3361 /* genDivbits :- division of bits */
3362 /*-----------------------------------------------------------------*/
3363 static void genDivbits (operand *left,
3372 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3373 /* the result must be bit */
3374 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3375 l = aopGet(AOP(left),0,FALSE,FALSE);
3379 pic14_emitcode("div","ab");
3380 pic14_emitcode("rrc","a");
3381 aopPut(AOP(result),"c",0);
3384 /*-----------------------------------------------------------------*/
3385 /* genDivOneByte : 8 bit division */
3386 /*-----------------------------------------------------------------*/
3387 static void genDivOneByte (operand *left,
3395 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3397 assert (AOP_SIZE(right) == 1);
3398 assert (AOP_SIZE(left) == 1);
3400 size = min(AOP_SIZE(result),AOP_SIZE(left));
3401 sign = !(SPEC_USIGN(operandType(left))
3402 && SPEC_USIGN(operandType(right)));
3404 if (AOP_TYPE(right) == AOP_LIT)
3406 /* XXX: might add specialized code */
3411 /* unsigned division */
3413 mov2w(AOP(right),0);
3414 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3416 call_libraryfunc("__divuchar");
3417 movwf(AOP(result),0);
3422 temp = popGetTempReg();
3423 lbl = newiTempLabel(NULL);
3425 /* XXX: improve this naive approach:
3426 [result] = [a] / [b]
3427 ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
3431 movwf temp // temp <-- left
3432 movf right,W // W <-- right
3436 subwf temp,F // temp <-- temp - W
3437 skipNC // subwf clears CARRY (i.e. sets BORROW) if temp < W
3439 decf result // we just subtract once too often
3442 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3443 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
3446 emitpcode(POC_MOVWF, temp);
3447 mov2w(AOP(right),0);
3448 emitpcode(POC_CLRF, popGet(AOP(result),0));
3450 emitpLabel(lbl->key);
3451 emitpcode(POC_INCF, popGet(AOP(result),0));
3452 emitpcode(POC_SUBWF, temp);
3454 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3455 emitpcode(POC_DECF, popGet(AOP(result),0));
3460 /* signed division */
3461 mov2w(AOP(right),0);
3462 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3464 call_libraryfunc("__divschar");
3465 movwf(AOP(result),0);
3468 /* now performed the signed/unsigned division -- extend result */
3469 addSign(result, 1, sign);
3472 /*-----------------------------------------------------------------*/
3473 /* genDiv - generates code for division */
3474 /*-----------------------------------------------------------------*/
3475 static void genDiv (iCode *ic)
3477 operand *left = IC_LEFT(ic);
3478 operand *right = IC_RIGHT(ic);
3479 operand *result= IC_RESULT(ic);
3482 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3483 /* assign the amsops */
3484 aopOp (left,ic,FALSE);
3485 aopOp (right,ic,FALSE);
3486 aopOp (result,ic,TRUE);
3488 /* special cases first */
3490 if (AOP_TYPE(left) == AOP_CRY &&
3491 AOP_TYPE(right)== AOP_CRY) {
3492 genDivbits(left,right,result);
3496 /* if both are of size == 1 */
3497 if (AOP_SIZE(left) == 1 &&
3498 AOP_SIZE(right) == 1 ) {
3499 genDivOneByte(left,right,result);
3503 /* should have been converted to function call */
3506 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3507 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3508 freeAsmop(result,NULL,ic,TRUE);
3511 /*-----------------------------------------------------------------*/
3512 /* genModOneByte : 8 bit modulus */
3513 /*-----------------------------------------------------------------*/
3514 static void genModOneByte (operand *left,
3522 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3524 assert (AOP_SIZE(right) == 1);
3525 assert (AOP_SIZE(left) == 1);
3527 size = min(AOP_SIZE(result),AOP_SIZE(left));
3528 sign = !(SPEC_USIGN(operandType(left))
3529 && SPEC_USIGN(operandType(right)));
3531 if (AOP_TYPE(right) == AOP_LIT)
3533 /* XXX: might add specialized code */
3538 /* unsigned division */
3540 mov2w(AOP(right),0);
3541 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3543 call_libraryfunc("__moduchar");
3544 movwf(AOP(result),0);
3549 lbl = newiTempLabel(NULL);
3551 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3553 /* XXX: improve this naive approach:
3554 [result] = [a] % [b]
3555 ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3559 movwf result // result <-- left
3560 movf right,W // W <-- right
3562 subwf result,F // result <-- result - W
3563 skipNC // subwf clears CARRY (i.e. sets BORROW) if result < W
3565 addwf result, F // we just subtract once too often
3568 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3569 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3571 if (!pic14_sameRegs(AOP(left), AOP(result)))
3574 emitpcode(POC_MOVWF, popGet(AOP(result),0));
3576 mov2w(AOP(right),0);
3578 emitpLabel(lbl->key);
3579 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3581 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3582 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3587 /* signed division */
3588 mov2w(AOP(right),0);
3589 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3591 call_libraryfunc("__modschar");
3592 movwf(AOP(result),0);
3595 /* now we performed the signed/unsigned modulus -- extend result */
3596 addSign(result, 1, sign);
3599 /*-----------------------------------------------------------------*/
3600 /* genMod - generates code for division */
3601 /*-----------------------------------------------------------------*/
3602 static void genMod (iCode *ic)
3604 operand *left = IC_LEFT(ic);
3605 operand *right = IC_RIGHT(ic);
3606 operand *result= IC_RESULT(ic);
3609 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3610 /* assign the amsops */
3611 aopOp (left,ic,FALSE);
3612 aopOp (right,ic,FALSE);
3613 aopOp (result,ic,TRUE);
3615 /* if both are of size == 1 */
3616 if (AOP_SIZE(left) == 1 &&
3617 AOP_SIZE(right) == 1 ) {
3618 genModOneByte(left,right,result);
3622 /* should have been converted to function call */
3626 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3627 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3628 freeAsmop(result,NULL,ic,TRUE);
3631 /*-----------------------------------------------------------------*/
3632 /* genIfxJump :- will create a jump depending on the ifx */
3633 /*-----------------------------------------------------------------*/
3635 note: May need to add parameter to indicate when a variable is in bit space.
3637 static void genIfxJump (iCode *ic, char *jval)
3641 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3642 /* if true label then we jump if condition
3644 if ( IC_TRUE(ic) ) {
3646 if(strcmp(jval,"a") == 0)
3648 else if (strcmp(jval,"c") == 0)
3651 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3652 emitpcode(POC_BTFSC, newpCodeOpBit(jval,-1,1));
3655 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3656 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3660 /* false label is present */
3661 if(strcmp(jval,"a") == 0)
3663 else if (strcmp(jval,"c") == 0)
3666 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3667 emitpcode(POC_BTFSS, newpCodeOpBit(jval,-1,1));
3670 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3671 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3676 /* mark the icode as generated */
3681 /*-----------------------------------------------------------------*/
3683 /*-----------------------------------------------------------------*/
3684 static void genSkip(iCode *ifx,int status_bit)
3690 if ( IC_TRUE(ifx) ) {
3691 switch(status_bit) {
3706 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3707 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3711 switch(status_bit) {
3725 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3726 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3733 /*-----------------------------------------------------------------*/
3735 /*-----------------------------------------------------------------*/
3736 static void genSkipc(resolvedIfx *rifx)
3747 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3748 emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3749 rifx->generated = 1;
3753 /*-----------------------------------------------------------------*/
3755 /*-----------------------------------------------------------------*/
3756 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3762 if( (rifx->condition ^ invert_condition) & 1)
3767 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3768 rifx->generated = 1;
3773 /*-----------------------------------------------------------------*/
3775 /*-----------------------------------------------------------------*/
3776 static void genSkipz(iCode *ifx, int condition)
3779 assert (ifx != NULL);
3787 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3789 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3792 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3794 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3800 /*-----------------------------------------------------------------*/
3802 /*-----------------------------------------------------------------*/
3803 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3810 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3812 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3815 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3816 rifx->generated = 1;
3821 /*-----------------------------------------------------------------*/
3822 /* genChkZeroes :- greater or less than comparison */
3823 /* For each byte in a literal that is zero, inclusive or the */
3824 /* the corresponding byte in the operand with W */
3825 /* returns true if any of the bytes are zero */
3826 /*-----------------------------------------------------------------*/
3827 static int genChkZeroes(operand *op, int lit, int size)
3834 i = (lit >> (size*8)) & 0xff;
3838 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3840 emitpcode(POC_IORFW, popGet(AOP(op),size));
3850 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3851 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
3852 #define DEBUGpc emitpComment
3854 /*-----------------------------------------------------------------*/
3855 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
3856 /* aop (if it's NOT a literal) or from lit (if */
3857 /* aop is a literal) */
3858 /*-----------------------------------------------------------------*/
3859 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3860 if (aop->type == AOP_LIT) {
3861 emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3863 emitpcode (POC_MOVFW, popGet (aop, offset));
3867 /* genCmp performs a left < right comparison, stores
3868 * the outcome in result (if != NULL) and generates
3869 * control flow code for the ifx (if != NULL).
3871 * This version leaves in sequences like
3872 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3873 * which should be optmized by the peephole
3874 * optimizer - RN 2005-01-01 */
3875 static void genCmp (operand *left,operand *right,
3876 operand *result, iCode *ifx, int sign)
3886 int invert_result = 0;
3890 assert (AOP_SIZE(left) == AOP_SIZE(right));
3891 assert (left && right);
3893 size = AOP_SIZE(right) - 1;
3894 mask = (0x100UL << (size*8)) - 1;
3895 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3900 resolveIfx (&rIfx, ifx);
3902 /**********************************************************************
3903 * handle bits - bit compares are promoted to int compares seemingly! *
3904 **********************************************************************/
3906 // THIS IS COMPLETELY UNTESTED!
3907 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3908 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3909 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3910 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3913 // 1 < {0,1} is false --> clear C by skipping the next instruction
3914 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3915 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3916 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3917 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3918 emitCLRC; // only skipped for left=0 && right=1
3920 goto correct_result_in_carry;
3924 /*************************************************
3925 * make sure that left is register (or the like) *
3926 *************************************************/
3927 if (!isAOP_REGlike(left)) {
3928 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
3929 assert (isAOP_LIT(left));
3930 assert (isAOP_REGlike(right));
3931 // swap left and right
3932 // left < right <==> right > left <==> (right >= left + 1)
3933 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3935 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
3936 // MAXVALUE < right? always false
3937 if (performedLt) emitCLRC; else emitSETC;
3938 goto correct_result_in_carry;
3941 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
3942 // that's why we handled it above.
3949 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
3950 } else if (isAOP_LIT(right)) {
3951 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3954 assert (isAOP_REGlike(left)); // left must be register or the like
3955 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
3957 /*************************************************
3958 * special cases go here *
3959 *************************************************/
3961 if (isAOP_LIT(right)) {
3963 // unsigned comparison to a literal
3964 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
3966 // unsigned left < 0? always false
3967 if (performedLt) emitCLRC; else emitSETC;
3968 goto correct_result_in_carry;
3971 // signed comparison to a literal
3972 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
3973 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
3974 // signed left < 0x80000000? always false
3975 if (performedLt) emitCLRC; else emitSETC;
3976 goto correct_result_in_carry;
3977 } else if (lit == 0) {
3978 // compare left < 0; set CARRY if SIGNBIT(left) is set
3979 if (performedLt) emitSETC; else emitCLRC;
3980 emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
3981 if (performedLt) emitCLRC; else emitSETC;
3982 goto correct_result_in_carry;
3985 } // right is literal
3987 /*************************************************
3988 * perform a general case comparison *
3989 * make sure we get CARRY==1 <==> left >= right *
3990 *************************************************/
3991 // compare most significant bytes
3992 //DEBUGpc ("comparing bytes at offset %d", size);
3994 // unsigned comparison
3995 pic14_mov2w_regOrLit (AOP(right), lit, size);
3996 emitpcode (POC_SUBFW, popGet (AOP(left), size));
3998 // signed comparison
3999 // (add 2^n to both operands then perform an unsigned comparison)
4000 if (isAOP_LIT(right)) {
4001 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4002 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4004 if (litbyte == 0x80) {
4005 // left >= 0x80 -- always true, but more bytes to come
4006 mov2w (AOP(left), size);
4007 emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
4010 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4011 mov2w (AOP(left), size);
4012 emitpcode (POC_ADDLW, popGetLit (0x80));
4013 emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4016 pCodeOp *pctemp = popGetTempReg();
4017 mov2w (AOP(left), size);
4018 emitpcode (POC_ADDLW, popGetLit (0x80));
4019 emitpcode (POC_MOVWF, pctemp);
4020 mov2w (AOP(right), size);
4021 emitpcode (POC_ADDLW, popGetLit (0x80));
4022 emitpcode (POC_SUBFW, pctemp);
4023 popReleaseTempReg(pctemp);
4027 // compare remaining bytes (treat as unsigned case from above)
4028 templbl = newiTempLabel ( NULL );
4031 //DEBUGpc ("comparing bytes at offset %d", offs);
4033 emitpcode (POC_GOTO, popGetLabel (templbl->key));
4034 pic14_mov2w_regOrLit (AOP(right), lit, offs);
4035 emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4037 emitpLabel (templbl->key);
4038 goto result_in_carry;
4042 /****************************************************
4043 * now CARRY contains the result of the comparison: *
4044 * SUBWF sets CARRY iff *
4045 * F-W >= 0 <==> F >= W <==> !(F < W) *
4046 * (F=left, W=right) *
4047 ****************************************************/
4051 // value will be used in the following genSkipc()
4052 rIfx.condition ^= 1;
4055 correct_result_in_carry:
4057 // assign result to variable (if neccessary)
4058 if (result && AOP_TYPE(result) != AOP_CRY) {
4059 //DEBUGpc ("assign result");
4060 size = AOP_SIZE(result);
4062 emitpcode (POC_CLRF, popGet (AOP(result), size));
4064 if (invert_result) {
4066 emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4068 emitpcode (POC_RLF, popGet (AOP(result), 0));
4072 // perform conditional jump
4074 //DEBUGpc ("generate control flow");
4082 /* OLD VERSION -- BUGGY, DO NOT USE */
4084 /*-----------------------------------------------------------------*/
4085 /* genCmp :- greater or less than comparison */
4086 /*-----------------------------------------------------------------*/
4087 static void genCmp (operand *left,operand *right,
4088 operand *result, iCode *ifx, int sign)
4090 int size; //, offset = 0 ;
4091 unsigned long lit = 0L,i = 0;
4092 resolvedIfx rFalseIfx;
4093 // resolvedIfx rTrueIfx;
4097 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4100 DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4101 DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4105 resolveIfx(&rFalseIfx,ifx);
4106 truelbl = newiTempLabel(NULL);
4107 size = max(AOP_SIZE(left),AOP_SIZE(right));
4109 DEBUGpic14_AopType(__LINE__,left,right,result);
4113 /* if literal is on the right then swap with left */
4114 if ((AOP_TYPE(right) == AOP_LIT)) {
4115 operand *tmp = right ;
4116 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4117 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4120 lit = (lit - 1) & mask;
4123 rFalseIfx.condition ^= 1;
4126 } else if ((AOP_TYPE(left) == AOP_LIT)) {
4127 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4131 //if(IC_TRUE(ifx) == NULL)
4132 /* if left & right are bit variables */
4133 if (AOP_TYPE(left) == AOP_CRY &&
4134 AOP_TYPE(right) == AOP_CRY ) {
4135 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4136 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4138 /* subtract right from left if at the
4139 end the carry flag is set then we know that
4140 left is greater than right */
4142 symbol *lbl = newiTempLabel(NULL);
4145 if(AOP_TYPE(right) == AOP_LIT) {
4147 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4149 DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4156 genSkipCond(&rFalseIfx,left,size-1,7);
4158 /* no need to compare to 0...*/
4159 /* NOTE: this is a de-generate compare that most certainly
4160 * creates some dead code. */
4161 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4163 if(ifx) ifx->generated = 1;
4170 //i = (lit >> (size*8)) & 0xff;
4171 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4173 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4175 i = ((0-lit) & 0xff);
4178 /* lit is 0x7f, all signed chars are less than
4179 * this except for 0x7f itself */
4180 emitpcode(POC_XORLW, popGetLit(0x7f));
4181 genSkipz2(&rFalseIfx,0);
4183 emitpcode(POC_ADDLW, popGetLit(0x80));
4184 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4185 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4190 genSkipz2(&rFalseIfx,1);
4192 emitpcode(POC_ADDLW, popGetLit(i));
4193 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4197 if(ifx) ifx->generated = 1;
4201 /* chars are out of the way. now do ints and longs */
4204 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4211 genSkipCond(&rFalseIfx,left,size,7);
4212 if(ifx) ifx->generated = 1;
4217 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4219 //rFalseIfx.condition ^= 1;
4220 //genSkipCond(&rFalseIfx,left,size,7);
4221 //rFalseIfx.condition ^= 1;
4223 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4224 if(rFalseIfx.condition)
4225 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4227 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4229 emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4230 emitpcode(POC_ADDFW, popGet(AOP(left),0));
4231 emitpcode(POC_MOVFW, popGet(AOP(left),1));
4234 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4236 if(rFalseIfx.condition) {
4238 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4244 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4245 emitpLabel(truelbl->key);
4246 if(ifx) ifx->generated = 1;
4253 if( (lit & 0xff) == 0) {
4254 /* lower byte is zero */
4255 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4256 i = ((lit >> 8) & 0xff) ^0x80;
4257 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4258 emitpcode(POC_ADDLW, popGetLit( 0x80));
4259 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4260 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4263 if(ifx) ifx->generated = 1;
4268 /* Special cases for signed longs */
4269 if( (lit & 0xffffff) == 0) {
4270 /* lower byte is zero */
4271 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4272 i = ((lit >> 8*3) & 0xff) ^0x80;
4273 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4274 emitpcode(POC_ADDLW, popGetLit( 0x80));
4275 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4276 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4279 if(ifx) ifx->generated = 1;
4287 if(lit & (0x80 << (size*8))) {
4288 /* lit is negative */
4289 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4291 //genSkipCond(&rFalseIfx,left,size,7);
4293 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4295 if(rFalseIfx.condition)
4296 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4298 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4302 /* lit is positive */
4303 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4304 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4305 if(rFalseIfx.condition)
4306 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4308 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4312 /* There are no more special cases, so perform a general compare */
4314 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4315 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4319 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4321 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4323 //rFalseIfx.condition ^= 1;
4324 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4326 emitpLabel(truelbl->key);
4328 if(ifx) ifx->generated = 1;
4335 /* sign is out of the way. So now do an unsigned compare */
4336 DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4339 /* General case - compare to an unsigned literal on the right.*/
4341 i = (lit >> (size*8)) & 0xff;
4342 emitpcode(POC_MOVLW, popGetLit(i));
4343 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4345 i = (lit >> (size*8)) & 0xff;
4348 emitpcode(POC_MOVLW, popGetLit(i));
4350 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4352 /* this byte of the lit is zero,
4353 *if it's not the last then OR in the variable */
4355 emitpcode(POC_IORFW, popGet(AOP(left),size));
4360 emitpLabel(lbl->key);
4361 //if(emitFinalCheck)
4362 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4364 emitpLabel(truelbl->key);
4366 if(ifx) ifx->generated = 1;
4373 if(AOP_TYPE(left) == AOP_LIT) {
4374 //symbol *lbl = newiTempLabel(NULL);
4376 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4379 DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4382 if((lit == 0) && (sign == 0)){
4385 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4387 emitpcode(POC_IORFW, popGet(AOP(right),--size));
4389 genSkipz2(&rFalseIfx,0);
4390 if(ifx) ifx->generated = 1;
4397 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4398 /* degenerate compare can never be true */
4399 if(rFalseIfx.condition == 0)
4400 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4402 if(ifx) ifx->generated = 1;
4407 /* signed comparisons to a literal byte */
4409 int lp1 = (lit+1) & 0xff;
4411 DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4414 rFalseIfx.condition ^= 1;
4415 genSkipCond(&rFalseIfx,right,0,7);
4418 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4419 emitpcode(POC_XORLW, popGetLit(0x7f));
4420 genSkipz2(&rFalseIfx,1);
4423 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4424 emitpcode(POC_ADDLW, popGetLit(0x80));
4425 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4426 rFalseIfx.condition ^= 1;
4427 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4430 if(ifx) ifx->generated = 1;
4432 /* unsigned comparisons to a literal byte */
4434 switch(lit & 0xff ) {
4436 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4437 genSkipz2(&rFalseIfx,0);
4438 if(ifx) ifx->generated = 1;
4441 genSkipCond(&rFalseIfx,right,0,7);
4442 if(ifx) ifx->generated = 1;
4446 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4447 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4448 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4449 rFalseIfx.condition ^= 1;
4450 if (AOP_TYPE(result) == AOP_CRY) {
4451 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4452 if(ifx) ifx->generated = 1;
4454 DEBUGpic14_emitcode ("; ***","%s %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4455 emitpcode(POC_CLRF, popGet(AOP(result),0));
4456 emitpcode(POC_RLF, popGet(AOP(result),0));
4457 emitpcode(POC_MOVLW, popGetLit(0x01));
4458 emitpcode(POC_XORWF, popGet(AOP(result),0));
4469 /* Size is greater than 1 */
4477 /* this means lit = 0xffffffff, or -1 */
4480 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4481 rFalseIfx.condition ^= 1;
4482 genSkipCond(&rFalseIfx,right,size,7);
4483 if(ifx) ifx->generated = 1;
4490 if(rFalseIfx.condition) {
4491 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4492 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4495 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4497 emitpcode(POC_IORFW, popGet(AOP(right),size));
4501 if(rFalseIfx.condition) {
4502 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4503 emitpLabel(truelbl->key);
4505 rFalseIfx.condition ^= 1;
4506 genSkipCond(&rFalseIfx,right,s,7);
4509 if(ifx) ifx->generated = 1;
4513 if((size == 1) && (0 == (lp1&0xff))) {
4514 /* lower byte of signed word is zero */
4515 DEBUGpic14_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
4516 i = ((lp1 >> 8) & 0xff) ^0x80;
4517 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4518 emitpcode(POC_ADDLW, popGetLit( 0x80));
4519 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4520 rFalseIfx.condition ^= 1;
4521 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4524 if(ifx) ifx->generated = 1;
4528 if(lit & (0x80 << (size*8))) {
4529 /* Lit is less than zero */
4530 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
4531 //rFalseIfx.condition ^= 1;
4532 //genSkipCond(&rFalseIfx,left,size,7);
4533 //rFalseIfx.condition ^= 1;
4534 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4535 //emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4537 if(rFalseIfx.condition)
4538 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4540 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4544 /* Lit is greater than or equal to zero */
4545 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
4546 //rFalseIfx.condition ^= 1;
4547 //genSkipCond(&rFalseIfx,right,size,7);
4548 //rFalseIfx.condition ^= 1;
4550 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4551 //emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4553 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4554 if(rFalseIfx.condition)
4555 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4557 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4562 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4563 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4567 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4569 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4571 rFalseIfx.condition ^= 1;
4572 //rFalseIfx.condition = 1;
4573 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4575 emitpLabel(truelbl->key);
4577 if(ifx) ifx->generated = 1;
4582 /* compare word or long to an unsigned literal on the right.*/
4587 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4590 break; /* handled above */
4593 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4595 emitpcode(POC_IORFW, popGet(AOP(right),size));
4596 genSkipz2(&rFalseIfx,0);
4600 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4602 emitpcode(POC_IORFW, popGet(AOP(right),size));
4605 if(rFalseIfx.condition)
4606 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4608 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4611 emitpcode(POC_MOVLW, popGetLit(lit+1));
4612 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4614 rFalseIfx.condition ^= 1;
4615 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4618 emitpLabel(truelbl->key);
4620 if(ifx) ifx->generated = 1;
4626 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4627 i = (lit >> (size*8)) & 0xff;
4629 emitpcode(POC_MOVLW, popGetLit(i));
4630 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4633 i = (lit >> (size*8)) & 0xff;
4636 emitpcode(POC_MOVLW, popGetLit(i));
4638 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4640 /* this byte of the lit is zero,
4641 *if it's not the last then OR in the variable */
4643 emitpcode(POC_IORFW, popGet(AOP(right),size));
4648 emitpLabel(lbl->key);
4650 rFalseIfx.condition ^= 1;
4651 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4655 emitpLabel(truelbl->key);
4656 if(ifx) ifx->generated = 1;
4660 /* Compare two variables */
4662 DEBUGpic14_emitcode(";sign","%d",sign);
4666 /* Sigh. thus sucks... */
4668 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4669 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4670 emitpcode(POC_MOVLW, popGetLit(0x80));
4671 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4672 emitpcode(POC_XORFW, popGet(AOP(right),size));
4673 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4675 /* Signed char comparison */
4676 /* Special thanks to Nikolai Golovchenko for this snippet */
4677 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4678 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4679 emitpcode(POC_RRFW, popGet(AOP(left),0)); /* could be any register */
4680 emitpcode(POC_XORFW, popGet(AOP(left),0));
4681 emitpcode(POC_XORFW, popGet(AOP(right),0));
4682 emitpcode(POC_ADDLW, popGetLit(0x80));
4684 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4685 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4687 if(ifx) ifx->generated = 1;
4693 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4694 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4698 /* The rest of the bytes of a multi-byte compare */
4702 emitpcode(POC_GOTO, popGetLabel(lbl->key));
4705 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4706 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4711 emitpLabel(lbl->key);
4713 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4714 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
4715 (AOP_TYPE(result) == AOP_REG)) {
4716 emitpcode(POC_CLRF, popGet(AOP(result),0));
4717 emitpcode(POC_RLF, popGet(AOP(result),0));
4719 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4721 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4722 if(ifx) ifx->generated = 1;
4729 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4730 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4731 pic14_outBitC(result);
4733 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4734 /* if the result is used in the next
4735 ifx conditional branch then generate
4736 code a little differently */
4738 genIfxJump (ifx,"c");
4740 pic14_outBitC(result);
4741 /* leave the result in acc */
4747 /*-----------------------------------------------------------------*/
4748 /* genCmpGt :- greater than comparison */
4749 /*-----------------------------------------------------------------*/
4750 static void genCmpGt (iCode *ic, iCode *ifx)
4752 operand *left, *right, *result;
4753 sym_link *letype , *retype;
4757 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4759 right= IC_RIGHT(ic);
4760 result = IC_RESULT(ic);
4762 letype = getSpec(operandType(left));
4763 retype =getSpec(operandType(right));
4764 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4765 /* assign the amsops */
4766 aopOp (left,ic,FALSE);
4767 aopOp (right,ic,FALSE);
4768 aopOp (result,ic,TRUE);
4770 genCmp(right, left, result, ifx, sign);
4772 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4773 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4774 freeAsmop(result,NULL,ic,TRUE);
4777 /*-----------------------------------------------------------------*/
4778 /* genCmpLt - less than comparisons */
4779 /*-----------------------------------------------------------------*/
4780 static void genCmpLt (iCode *ic, iCode *ifx)
4782 operand *left, *right, *result;
4783 sym_link *letype , *retype;
4787 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4789 right= IC_RIGHT(ic);
4790 result = IC_RESULT(ic);
4792 letype = getSpec(operandType(left));
4793 retype =getSpec(operandType(right));
4794 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4796 /* assign the amsops */
4797 aopOp (left,ic,FALSE);
4798 aopOp (right,ic,FALSE);
4799 aopOp (result,ic,TRUE);
4801 genCmp(left, right, result, ifx, sign);
4803 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4804 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4805 freeAsmop(result,NULL,ic,TRUE);
4809 /*-----------------------------------------------------------------*/
4810 /* genc16bit2lit - compare a 16 bit value to a literal */
4811 /*-----------------------------------------------------------------*/
4812 static void genc16bit2lit(operand *op, int lit, int offset)
4817 DEBUGpic14_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
4818 if( (lit&0xff) == 0)
4823 switch( BYTEofLONG(lit,i)) {
4825 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4828 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4831 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4834 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4835 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4840 switch( BYTEofLONG(lit,i)) {
4842 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4846 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4850 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4853 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4855 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4863 /*-----------------------------------------------------------------*/
4864 /* gencjneshort - compare and jump if not equal */
4865 /*-----------------------------------------------------------------*/
4866 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4868 int size = min(AOP_SIZE(left),AOP_SIZE(right));
4873 //unsigned long lit = 0L;
4875 if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4876 emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4879 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4880 DEBUGpic14_AopType(__LINE__,left,right,result);
4882 assert (!pic14_sameRegs (AOP(left), AOP(result)));
4883 assert (!pic14_sameRegs (AOP(right), AOP(result)));
4884 if (AOP_SIZE(result)) {
4885 for (offset = 0; offset < AOP_SIZE(result); offset++)
4886 emitpcode (POC_CLRF, popGet (AOP(result), offset));
4889 assert (AOP_SIZE(left) == AOP_SIZE(right));
4890 //resolveIfx(&rIfx,ifx);
4891 lbl = newiTempLabel (NULL);
4894 mov2w (AOP(right),size);
4895 emitpcode (POC_XORFW, popGet (AOP(left), size));
4899 emitpcode (POC_GOTO, popGetLabel (lbl->key));
4902 emitpLabel (lbl->key);
4903 if (AOP_SIZE(result)) {
4905 emitpcode (POC_INCF, popGet (AOP(result), 0));
4908 genSkipz (ifx, NULL != IC_TRUE(ifx));
4915 DEBUGpic14_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
4916 assert (!pic14_sameRegs (AOP(result), AOP(left)));
4917 assert (!pic14_sameRegs (AOP(result), AOP(right)));
4918 for (offset=0; offset < AOP_SIZE(result); offset++)
4920 emitpcode (POC_CLRF, popGet (AOP(result), offset));
4925 /* if the left side is a literal or
4926 if the right is in a pointer register and left
4928 if ((AOP_TYPE(left) == AOP_LIT) ||
4929 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4934 if(AOP_TYPE(right) == AOP_LIT)
4935 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4937 /* if the right side is a literal then anything goes */
4938 if (AOP_TYPE(right) == AOP_LIT &&
4939 AOP_TYPE(left) != AOP_DIR ) {
4942 genc16bit2lit(left, lit, 0);
4944 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4950 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4951 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4953 emitpcode(POC_MOVF,popGet(AOP(left),offset));
4957 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4965 /* if the right side is in a register or in direct space or
4966 if the left is a pointer register & right is not */
4967 else if (AOP_TYPE(right) == AOP_REG ||
4968 AOP_TYPE(right) == AOP_DIR ||
4969 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4970 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4971 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4972 int lbl_key = lbl->key;
4975 DEBUGpic14_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
4976 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
4977 __FUNCTION__,__LINE__);
4981 /* switch(size) { */
4983 /* genc16bit2lit(left, lit, 0); */
4985 /* emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
4991 if((AOP_TYPE(left) == AOP_DIR) &&
4992 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4994 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4995 emitpcode(POC_XORFW,popGet(AOP(right),offset));
4997 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4999 switch (lit & 0xff) {
5001 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5004 emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
5005 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5006 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5010 emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5011 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5012 //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5013 emitpcode(POC_GOTO,popGetLabel(lbl_key));
5017 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5018 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5023 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5026 if(AOP_TYPE(result) == AOP_CRY) {
5027 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5032 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5034 /* fix me. probably need to check result size too */
5035 //emitpcode(POC_CLRF,popGet(AOP(result),0));
5040 emitpcode(POC_GOTO,popGetLabel(lbl_key));
5050 } else if(AOP_TYPE(right) == AOP_REG &&
5051 AOP_TYPE(left) != AOP_DIR){
5055 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5056 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5057 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5062 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5067 /* right is a pointer reg need both a & b */
5070 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5072 pic14_emitcode("mov","b,%s",l);
5073 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5074 pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
5079 emitpcode(POC_INCF,popGet(AOP(result),0));
5081 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5083 emitpLabel(lbl->key);
5085 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5094 /*-----------------------------------------------------------------*/
5095 /* gencjne - compare and jump if not equal */
5096 /*-----------------------------------------------------------------*/
5097 static void gencjne(operand *left, operand *right, iCode *ifx)
5099 symbol *tlbl = newiTempLabel(NULL);
5101 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5102 gencjneshort(left, right, lbl);
5104 pic14_emitcode("mov","a,%s",one);
5105 pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5106 pic14_emitcode("","%05d_DS_:",lbl->key+100);
5107 pic14_emitcode("clr","a");
5108 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5110 emitpLabel(lbl->key);
5111 emitpLabel(tlbl->key);
5116 /*-----------------------------------------------------------------*/
5117 /* genCmpEq - generates code for equal to */
5118 /*-----------------------------------------------------------------*/
5119 static void genCmpEq (iCode *ic, iCode *ifx)
5121 operand *left, *right, *result;
5123 symbol *false_label;
5126 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5129 DEBUGpic14_emitcode ("; ifx is non-null","");
5131 DEBUGpic14_emitcode ("; ifx is null","");
5133 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5134 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5135 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5137 DEBUGpic14_AopType(__LINE__,left,right,result);
5139 /* if literal, move literal to right */
5140 if (op_isLitLike (IC_LEFT(ic))) {
5141 operand *tmp = right ;
5147 if (ifx && !IC_TRUE(ifx))
5149 assert (IC_FALSE(ifx));
5150 false_label = IC_FALSE(ifx);
5153 size = min(AOP_SIZE(left),AOP_SIZE(right));
5154 assert(!pic14_sameRegs(AOP(result),AOP(left)));
5155 assert(!pic14_sameRegs(AOP(result),AOP(right)));
5157 /* assume left != right */
5160 for (i=0; i < AOP_SIZE(result); i++)
5162 emitpcode(POC_CLRF, popGet(AOP(result),i));
5166 if (AOP_TYPE(right) == AOP_LIT)
5168 unsigned long lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
5170 size = AOP_SIZE(left);
5171 assert(!op_isLitLike(left));
5176 mov2w(AOP(left), 0);
5177 for (i=1; i < size; i++)
5178 emitpcode(POC_IORFW,popGet(AOP(left),i));
5179 /* now Z is set iff `left == right' */
5181 if (!false_label) false_label = newiTempLabel(NULL);
5182 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5186 for (i=0; i < size; i++)
5189 emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
5190 /* now Z is cleared if `left != right' */
5192 if (!false_label) false_label = newiTempLabel(NULL);
5193 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5200 /* right is no literal */
5203 for (i=0; i < size; i++)
5205 mov2w(AOP(right),i);
5206 emitpcode(POC_XORFW,popGet(AOP(left),i));
5207 /* now Z is cleared if `left != right' */
5209 if (!false_label) false_label = newiTempLabel(NULL);
5210 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5214 /* if we reach here, left == right */
5216 if (AOP_SIZE(result) > 0)
5218 emitpcode(POC_INCF, popGet(AOP(result),0));
5221 if (ifx && IC_TRUE(ifx))
5223 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5226 if (false_label && (!ifx || IC_TRUE(ifx)))
5227 emitpLabel(false_label->key);
5229 if (ifx) ifx->generated = 1;
5231 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5232 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5233 freeAsmop(result,NULL,ic,TRUE);
5236 /*-----------------------------------------------------------------*/
5237 /* ifxForOp - returns the icode containing the ifx for operand */
5238 /*-----------------------------------------------------------------*/
5239 static iCode *ifxForOp ( operand *op, iCode *ic )
5242 /* if true symbol then needs to be assigned */
5243 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5244 if (IS_TRUE_SYMOP(op))
5247 /* if this has register type condition and
5248 the next instruction is ifx with the same operand
5249 and live to of the operand is upto the ifx only then */
5251 ic->next->op == IFX &&
5252 IC_COND(ic->next)->key == op->key &&
5253 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5257 ic->next->op == IFX &&
5258 IC_COND(ic->next)->key == op->key) {
5259 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5263 DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5265 ic->next->op == IFX)
5266 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5269 ic->next->op == IFX &&
5270 IC_COND(ic->next)->key == op->key) {
5271 DEBUGpic14_emitcode ("; "," key is okay");
5272 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5273 OP_SYMBOL(op)->liveTo,
5280 /*-----------------------------------------------------------------*/
5281 /* genAndOp - for && operation */
5282 /*-----------------------------------------------------------------*/
5283 static void genAndOp (iCode *ic)
5285 operand *left,*right, *result;
5289 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5290 /* note here that && operations that are in an
5291 if statement are taken away by backPatchLabels
5292 only those used in arthmetic operations remain */
5293 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5294 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5295 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5297 DEBUGpic14_AopType(__LINE__,left,right,result);
5299 emitpcode(POC_MOVFW,popGet(AOP(left),0));
5300 emitpcode(POC_ANDFW,popGet(AOP(right),0));
5301 emitpcode(POC_MOVWF,popGet(AOP(result),0));
5303 /* if both are bit variables */
5304 /* if (AOP_TYPE(left) == AOP_CRY && */
5305 /* AOP_TYPE(right) == AOP_CRY ) { */
5306 /* pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5307 /* pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5308 /* pic14_outBitC(result); */
5310 /* tlbl = newiTempLabel(NULL); */
5311 /* pic14_toBoolean(left); */
5312 /* pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5313 /* pic14_toBoolean(right); */
5314 /* pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5315 /* pic14_outBitAcc(result); */
5318 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5319 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5320 freeAsmop(result,NULL,ic,TRUE);
5324 /*-----------------------------------------------------------------*/
5325 /* genOrOp - for || operation */
5326 /*-----------------------------------------------------------------*/
5329 modified this code, but it doesn't appear to ever get called
5332 static void genOrOp (iCode *ic)
5334 operand *left,*right, *result;
5338 /* note here that || operations that are in an
5339 if statement are taken away by backPatchLabels
5340 only those used in arthmetic operations remain */
5342 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5343 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5344 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5345 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5347 DEBUGpic14_AopType(__LINE__,left,right,result);
5349 for (i=0; i < AOP_SIZE(result); i++)
5351 emitpcode(POC_CLRF, popGet(AOP(result), i));
5354 tlbl = newiTempLabel(NULL);
5355 pic14_toBoolean(left);
5357 emitpcode(POC_GOTO, popGetLabel(tlbl->key));
5358 pic14_toBoolean(right);
5359 emitpLabel(tlbl->key);
5360 /* here Z is clear IFF `left || right' */
5362 emitpcode(POC_INCF, popGet(AOP(result), 0));
5364 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5365 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5366 freeAsmop(result,NULL,ic,TRUE);
5369 /*-----------------------------------------------------------------*/
5370 /* isLiteralBit - test if lit == 2^n */
5371 /*-----------------------------------------------------------------*/
5372 static int isLiteralBit(unsigned long lit)
5374 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5375 0x100L,0x200L,0x400L,0x800L,
5376 0x1000L,0x2000L,0x4000L,0x8000L,
5377 0x10000L,0x20000L,0x40000L,0x80000L,
5378 0x100000L,0x200000L,0x400000L,0x800000L,
5379 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5380 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5384 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5385 for(idx = 0; idx < 32; idx++)
5391 /*-----------------------------------------------------------------*/
5392 /* continueIfTrue - */
5393 /*-----------------------------------------------------------------*/
5394 static void continueIfTrue (iCode *ic)
5397 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5401 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
5402 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5407 /*-----------------------------------------------------------------*/
5409 /*-----------------------------------------------------------------*/
5410 static void jumpIfTrue (iCode *ic)
5413 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5417 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
5418 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5423 /*-----------------------------------------------------------------*/
5424 /* jmpTrueOrFalse - */
5425 /*-----------------------------------------------------------------*/
5426 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5429 // ugly but optimized by peephole
5430 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5432 symbol *nlbl = newiTempLabel(NULL);
5433 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5434 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5435 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5436 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5439 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5440 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5445 /*-----------------------------------------------------------------*/
5446 /* genAnd - code for and */
5447 /*-----------------------------------------------------------------*/
5448 static void genAnd (iCode *ic, iCode *ifx)
5450 operand *left, *right, *result;
5452 unsigned long lit = 0L;
5457 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5458 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5459 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5460 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5462 resolveIfx(&rIfx,ifx);
5464 /* if left is a literal & right is not then exchange them */
5465 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5466 AOP_NEEDSACC(left)) {
5467 operand *tmp = right ;
5472 /* if result = right then exchange them */
5473 if(pic14_sameRegs(AOP(result),AOP(right))){
5474 operand *tmp = right ;
5479 /* if right is bit then exchange them */
5480 if (AOP_TYPE(right) == AOP_CRY &&
5481 AOP_TYPE(left) != AOP_CRY){
5482 operand *tmp = right ;
5486 if(AOP_TYPE(right) == AOP_LIT)
5487 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5489 size = AOP_SIZE(result);
5491 DEBUGpic14_AopType(__LINE__,left,right,result);
5494 // result = bit & yy;
5495 if (AOP_TYPE(left) == AOP_CRY){
5496 // c = bit & literal;
5497 if(AOP_TYPE(right) == AOP_LIT){
5499 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5502 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5505 if(size && (AOP_TYPE(result) == AOP_CRY)){
5506 pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5509 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5513 pic14_emitcode("clr","c");
5516 if (AOP_TYPE(right) == AOP_CRY){
5518 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5519 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5522 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5524 pic14_emitcode("rrc","a");
5525 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5531 pic14_outBitC(result);
5533 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5534 genIfxJump(ifx, "c");
5538 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5539 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5540 if((AOP_TYPE(right) == AOP_LIT) &&
5541 (AOP_TYPE(result) == AOP_CRY) &&
5542 (AOP_TYPE(left) != AOP_CRY)){
5543 int posbit = isLiteralBit(lit);
5547 //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5550 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5555 while (posbit > 7) {
5559 emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5560 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5561 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5568 symbol *tlbl = newiTempLabel(NULL);
5569 int sizel = AOP_SIZE(left);
5571 pic14_emitcode("setb","c");
5573 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5574 mov2w( AOP(left), offset);
5576 if((posbit = isLiteralBit(bytelit)) != 0) {
5577 emitpcode(rIfx.condition ? POC_BTFSC : POC_BTFSS, // XXX: or the other way round?
5578 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit - 1, 0));
5579 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5582 emitpcode(POC_ANDLW, newpCodeOpLit(bytelit & 0x0ff));
5583 if (rIfx.condition) emitSKPZ;
5586 if(bytelit != 0x0FFL)
5588 pic14_emitcode("anl","a,%s",
5589 aopGet(AOP(right),offset,FALSE,TRUE));
5591 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5594 emitpcode(POC_GOTO, popGetLabel(rIfx.lbl->key));
5600 // bit = left & literal
5602 pic14_emitcode("clr","c");
5603 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5605 // if(left & literal)
5608 jmpTrueOrFalse(ifx, tlbl);
5612 pic14_outBitC(result);
5616 /* if left is same as result */
5617 if(pic14_sameRegs(AOP(result),AOP(left))){
5619 for(;size--; offset++,lit>>=8) {
5620 if(AOP_TYPE(right) == AOP_LIT){
5621 switch(lit & 0xff) {
5623 /* and'ing with 0 has clears the result */
5624 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5627 /* and'ing with 0xff is a nop when the result and left are the same */
5632 int p = my_powof2( (~lit) & 0xff );
5634 /* only one bit is set in the literal, so use a bcf instruction */
5635 emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5638 if(know_W != (int)(lit&0xff))
5639 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5641 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5646 if (AOP_TYPE(left) == AOP_ACC) {
5647 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5649 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5650 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5657 // left & result in different registers
5658 if(AOP_TYPE(result) == AOP_CRY){
5660 // if(size), result in bit
5661 // if(!size && ifx), conditional oper: if(left & right)
5662 symbol *tlbl = newiTempLabel(NULL);
5663 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5665 pic14_emitcode("setb","c");
5667 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5668 pic14_emitcode("anl","a,%s",
5669 aopGet(AOP(left),offset,FALSE,FALSE));
5670 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5675 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5676 pic14_outBitC(result);
5678 jmpTrueOrFalse(ifx, tlbl);
5680 for(;(size--);offset++) {
5682 // result = left & right
5683 if(AOP_TYPE(right) == AOP_LIT){
5684 int t = (lit >> (offset*8)) & 0x0FFL;
5687 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5690 if(AOP_TYPE(left) != AOP_ACC) {
5691 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5693 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5696 if(AOP_TYPE(left) == AOP_ACC) {
5697 emitpcode(POC_ANDLW, popGetLit(t));
5699 emitpcode(POC_MOVLW, popGetLit(t));
5700 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5702 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5707 if (AOP_TYPE(left) == AOP_ACC) {
5708 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5710 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5711 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5713 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5719 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5720 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5721 freeAsmop(result,NULL,ic,TRUE);
5724 /*-----------------------------------------------------------------*/
5725 /* genOr - code for or */
5726 /*-----------------------------------------------------------------*/
5727 static void genOr (iCode *ic, iCode *ifx)
5729 operand *left, *right, *result;
5731 unsigned long lit = 0L;
5734 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5736 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5737 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5738 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5740 DEBUGpic14_AopType(__LINE__,left,right,result);
5742 /* if left is a literal & right is not then exchange them */
5743 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5744 AOP_NEEDSACC(left)) {
5745 operand *tmp = right ;
5750 /* if result = right then exchange them */
5751 if(pic14_sameRegs(AOP(result),AOP(right))){
5752 operand *tmp = right ;
5757 /* if right is bit then exchange them */
5758 if (AOP_TYPE(right) == AOP_CRY &&
5759 AOP_TYPE(left) != AOP_CRY){
5760 operand *tmp = right ;
5765 DEBUGpic14_AopType(__LINE__,left,right,result);
5767 if(AOP_TYPE(right) == AOP_LIT)
5768 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5770 size = AOP_SIZE(result);
5774 if (AOP_TYPE(left) == AOP_CRY){
5775 if(AOP_TYPE(right) == AOP_LIT){
5776 // c = bit & literal;
5778 // lit != 0 => result = 1
5779 if(AOP_TYPE(result) == AOP_CRY){
5781 emitpcode(POC_BSF, popGet(AOP(result),0));
5782 //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5783 // AOP(result)->aopu.aop_dir,
5784 // AOP(result)->aopu.aop_dir);
5786 continueIfTrue(ifx);
5790 // lit == 0 => result = left
5791 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5793 pic14_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5796 if (AOP_TYPE(right) == AOP_CRY){
5797 if(pic14_sameRegs(AOP(result),AOP(left))){
5799 emitpcode(POC_BCF, popGet(AOP(result),0));
5800 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5801 emitpcode(POC_BSF, popGet(AOP(result),0));
5803 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5804 AOP(result)->aopu.aop_dir,
5805 AOP(result)->aopu.aop_dir);
5806 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5807 AOP(right)->aopu.aop_dir,
5808 AOP(right)->aopu.aop_dir);
5809 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5810 AOP(result)->aopu.aop_dir,
5811 AOP(result)->aopu.aop_dir);
5813 if( AOP_TYPE(result) == AOP_ACC) {
5814 emitpcode(POC_MOVLW, popGetLit(0));
5815 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5816 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5817 emitpcode(POC_MOVLW, popGetLit(1));
5821 emitpcode(POC_BCF, popGet(AOP(result),0));
5822 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5823 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5824 emitpcode(POC_BSF, popGet(AOP(result),0));
5826 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5827 AOP(result)->aopu.aop_dir,
5828 AOP(result)->aopu.aop_dir);
5829 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5830 AOP(right)->aopu.aop_dir,
5831 AOP(right)->aopu.aop_dir);
5832 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5833 AOP(left)->aopu.aop_dir,
5834 AOP(left)->aopu.aop_dir);
5835 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5836 AOP(result)->aopu.aop_dir,
5837 AOP(result)->aopu.aop_dir);
5842 symbol *tlbl = newiTempLabel(NULL);
5843 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5846 emitpcode(POC_BCF, popGet(AOP(result),0));
5847 if( AOP_TYPE(right) == AOP_ACC) {
5848 emitpcode(POC_IORLW, popGetLit(0));
5850 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5851 emitpcode(POC_BSF, popGet(AOP(result),0));
5856 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5857 pic14_emitcode(";XXX setb","c");
5858 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5859 AOP(left)->aopu.aop_dir,tlbl->key+100);
5860 pic14_toBoolean(right);
5861 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5862 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5863 jmpTrueOrFalse(ifx, tlbl);
5867 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5874 pic14_outBitC(result);
5876 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5877 genIfxJump(ifx, "c");
5881 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5882 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5883 if((AOP_TYPE(right) == AOP_LIT) &&
5884 (AOP_TYPE(result) == AOP_CRY) &&
5885 (AOP_TYPE(left) != AOP_CRY)){
5887 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5890 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5892 continueIfTrue(ifx);
5895 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5896 // lit = 0, result = boolean(left)
5898 pic14_emitcode(";XXX setb","c");
5899 pic14_toBoolean(right);
5901 symbol *tlbl = newiTempLabel(NULL);
5902 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5904 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5906 genIfxJump (ifx,"a");
5910 pic14_outBitC(result);
5914 /* if left is same as result */
5915 if(pic14_sameRegs(AOP(result),AOP(left))){
5917 for(;size--; offset++,lit>>=8) {
5918 if(AOP_TYPE(right) == AOP_LIT){
5919 if((lit & 0xff) == 0)
5920 /* or'ing with 0 has no effect */
5923 int p = my_powof2(lit & 0xff);
5925 /* only one bit is set in the literal, so use a bsf instruction */
5927 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5929 if(know_W != (int)(lit & 0xff))
5930 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5931 know_W = lit & 0xff;
5932 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5937 if (AOP_TYPE(left) == AOP_ACC) {
5938 emitpcode(POC_IORFW, popGet(AOP(right),offset));
5939 pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5941 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
5942 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5944 pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5945 pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5951 // left & result in different registers
5952 if(AOP_TYPE(result) == AOP_CRY){
5954 // if(size), result in bit
5955 // if(!size && ifx), conditional oper: if(left | right)
5956 symbol *tlbl = newiTempLabel(NULL);
5957 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5958 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5962 pic14_emitcode(";XXX setb","c");
5964 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5965 pic14_emitcode(";XXX orl","a,%s",
5966 aopGet(AOP(left),offset,FALSE,FALSE));
5967 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5972 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5973 pic14_outBitC(result);
5975 jmpTrueOrFalse(ifx, tlbl);
5976 } else for(;(size--);offset++){
5978 // result = left | right
5979 if(AOP_TYPE(right) == AOP_LIT){
5980 int t = (lit >> (offset*8)) & 0x0FFL;
5983 if (AOP_TYPE(left) != AOP_ACC) {
5984 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
5986 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5990 if (AOP_TYPE(left) == AOP_ACC) {
5991 emitpcode(POC_IORLW, popGetLit(t));
5993 emitpcode(POC_MOVLW, popGetLit(t));
5994 emitpcode(POC_IORFW, popGet(AOP(left),offset));
5996 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6001 // faster than result <- left, anl result,right
6002 // and better if result is SFR
6003 if (AOP_TYPE(left) == AOP_ACC) {
6004 emitpcode(POC_IORFW,popGet(AOP(right),offset));
6006 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6007 emitpcode(POC_IORFW,popGet(AOP(left),offset));
6009 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6014 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6015 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6016 freeAsmop(result,NULL,ic,TRUE);
6019 /*-----------------------------------------------------------------*/
6020 /* genXor - code for xclusive or */
6021 /*-----------------------------------------------------------------*/
6022 static void genXor (iCode *ic, iCode *ifx)
6024 operand *left, *right, *result;
6026 unsigned long lit = 0L;
6029 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6031 aopOp((left = IC_LEFT(ic)),ic,FALSE);
6032 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6033 aopOp((result=IC_RESULT(ic)),ic,TRUE);
6035 /* if left is a literal & right is not ||
6036 if left needs acc & right does not */
6037 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6038 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6039 operand *tmp = right ;
6044 /* if result = right then exchange them */
6045 if(pic14_sameRegs(AOP(result),AOP(right))){
6046 operand *tmp = right ;
6051 /* if right is bit then exchange them */
6052 if (AOP_TYPE(right) == AOP_CRY &&
6053 AOP_TYPE(left) != AOP_CRY){
6054 operand *tmp = right ;
6058 if(AOP_TYPE(right) == AOP_LIT)
6059 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6061 size = AOP_SIZE(result);
6065 if (AOP_TYPE(left) == AOP_CRY){
6066 if(AOP_TYPE(right) == AOP_LIT){
6067 // c = bit & literal;
6069 // lit>>1 != 0 => result = 1
6070 if(AOP_TYPE(result) == AOP_CRY){
6072 {emitpcode(POC_BSF, popGet(AOP(result),offset));
6073 pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6075 continueIfTrue(ifx);
6078 pic14_emitcode("setb","c");
6082 // lit == 0, result = left
6083 if(size && pic14_sameRegs(AOP(result),AOP(left)))
6085 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6087 // lit == 1, result = not(left)
6088 if(size && pic14_sameRegs(AOP(result),AOP(left))){
6089 emitpcode(POC_MOVLW, popGet(AOP(result),offset));
6090 emitpcode(POC_XORWF, popGet(AOP(result),offset));
6091 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6094 assert ( !"incomplete genXor" );
6095 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6096 pic14_emitcode("cpl","c");
6103 symbol *tlbl = newiTempLabel(NULL);
6104 if (AOP_TYPE(right) == AOP_CRY){
6106 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6109 int sizer = AOP_SIZE(right);
6111 // if val>>1 != 0, result = 1
6112 pic14_emitcode("setb","c");
6114 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6116 // test the msb of the lsb
6117 pic14_emitcode("anl","a,#0xfe");
6118 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6122 pic14_emitcode("rrc","a");
6124 pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6125 pic14_emitcode("cpl","c");
6126 pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6131 pic14_outBitC(result);
6133 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6134 genIfxJump(ifx, "c");
6138 if(pic14_sameRegs(AOP(result),AOP(left))){
6139 /* if left is same as result */
6140 for(;size--; offset++) {
6141 if(AOP_TYPE(right) == AOP_LIT){
6142 int t = (lit >> (offset*8)) & 0x0FFL;
6146 if (IS_AOP_PREG(left)) {
6147 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6148 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6149 aopPut(AOP(result),"a",offset);
6151 emitpcode(POC_MOVLW, popGetLit(t));
6152 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6153 pic14_emitcode("xrl","%s,%s",
6154 aopGet(AOP(left),offset,FALSE,TRUE),
6155 aopGet(AOP(right),offset,FALSE,FALSE));
6158 if (AOP_TYPE(left) == AOP_ACC)
6159 pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6161 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6162 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6164 if (IS_AOP_PREG(left)) {
6165 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6166 aopPut(AOP(result),"a",offset);
6168 pic14_emitcode("xrl","%s,a",
6169 aopGet(AOP(left),offset,FALSE,TRUE));
6175 // left & result in different registers
6176 if(AOP_TYPE(result) == AOP_CRY){
6178 // if(size), result in bit
6179 // if(!size && ifx), conditional oper: if(left ^ right)
6180 symbol *tlbl = newiTempLabel(NULL);
6181 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6183 pic14_emitcode("setb","c");
6185 if((AOP_TYPE(right) == AOP_LIT) &&
6186 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6187 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6189 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6190 pic14_emitcode("xrl","a,%s",
6191 aopGet(AOP(left),offset,FALSE,FALSE));
6193 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6198 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6199 pic14_outBitC(result);
6201 jmpTrueOrFalse(ifx, tlbl);
6202 } else for(;(size--);offset++){
6204 // result = left & right
6205 if(AOP_TYPE(right) == AOP_LIT){
6206 int t = (lit >> (offset*8)) & 0x0FFL;
6209 if (AOP_TYPE(left) != AOP_ACC) {
6210 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6212 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6213 pic14_emitcode("movf","%s,w",
6214 aopGet(AOP(left),offset,FALSE,FALSE));
6215 pic14_emitcode("movwf","%s",
6216 aopGet(AOP(result),offset,FALSE,FALSE));
6219 if (AOP_TYPE(left) == AOP_ACC) {
6220 emitpcode(POC_XORLW, popGetLit(t));
6222 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6224 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6227 if (AOP_TYPE(left) == AOP_ACC) {
6228 emitpcode(POC_XORLW, popGetLit(t));
6230 emitpcode(POC_MOVLW, popGetLit(t));
6231 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6233 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6234 pic14_emitcode("movlw","0x%x",t);
6235 pic14_emitcode("xorwf","%s,w",
6236 aopGet(AOP(left),offset,FALSE,FALSE));
6237 pic14_emitcode("movwf","%s",
6238 aopGet(AOP(result),offset,FALSE,FALSE));
6244 // faster than result <- left, anl result,right
6245 // and better if result is SFR
6246 if (AOP_TYPE(left) == AOP_ACC) {
6247 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6249 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6250 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6252 if ( AOP_TYPE(result) != AOP_ACC){
6253 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6259 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6260 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6261 freeAsmop(result,NULL,ic,TRUE);
6264 /*-----------------------------------------------------------------*/
6265 /* genInline - write the inline code out */
6266 /*-----------------------------------------------------------------*/
6267 static void genInline (iCode *ic)
6269 char *buffer, *bp, *bp1;
6272 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6274 _G.inLine += (!options.asmpeep);
6276 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6277 strcpy(buffer,IC_INLINE(ic));
6279 /* emit each line as a code */
6285 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6293 /* print label, use this special format with NULL directive
6294 * to denote that the argument should not be indented with tab */
6295 addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6302 if ((bp1 != bp) && *bp1)
6303 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6307 _G.inLine -= (!options.asmpeep);
6310 /*-----------------------------------------------------------------*/
6311 /* genRRC - rotate right with carry */
6312 /*-----------------------------------------------------------------*/
6313 static void genRRC (iCode *ic)
6315 operand *left , *result ;
6316 int size, offset = 0, same;
6319 /* rotate right with carry */
6321 result=IC_RESULT(ic);
6322 aopOp (left,ic,FALSE);
6323 aopOp (result,ic,FALSE);
6325 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6327 same = pic14_sameRegs(AOP(result),AOP(left));
6329 size = AOP_SIZE(result);
6331 /* get the lsb and put it into the carry */
6332 emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6339 emitpcode(POC_RRF, popGet(AOP(left),offset));
6341 emitpcode(POC_RRFW, popGet(AOP(left),offset));
6342 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6348 freeAsmop(left,NULL,ic,TRUE);
6349 freeAsmop(result,NULL,ic,TRUE);
6352 /*-----------------------------------------------------------------*/
6353 /* genRLC - generate code for rotate left with carry */
6354 /*-----------------------------------------------------------------*/
6355 static void genRLC (iCode *ic)
6357 operand *left , *result ;
6358 int size, offset = 0;
6362 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6363 /* rotate right with carry */
6365 result=IC_RESULT(ic);
6366 aopOp (left,ic,FALSE);
6367 aopOp (result,ic,FALSE);
6369 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6371 same = pic14_sameRegs(AOP(result),AOP(left));
6373 /* move it to the result */
6374 size = AOP_SIZE(result);
6376 /* get the msb and put it into the carry */
6377 emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6384 emitpcode(POC_RLF, popGet(AOP(left),offset));
6386 emitpcode(POC_RLFW, popGet(AOP(left),offset));
6387 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6394 freeAsmop(left,NULL,ic,TRUE);
6395 freeAsmop(result,NULL,ic,TRUE);
6398 /*-----------------------------------------------------------------*/
6399 /* genGetHbit - generates code get highest order bit */
6400 /*-----------------------------------------------------------------*/
6401 static void genGetHbit (iCode *ic)
6403 operand *left, *result;
6405 result=IC_RESULT(ic);
6406 aopOp (left,ic,FALSE);
6407 aopOp (result,ic,FALSE);
6410 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6411 /* get the highest order byte into a */
6412 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6413 if(AOP_TYPE(result) == AOP_CRY){
6414 pic14_emitcode("rlc","a");
6415 pic14_outBitC(result);
6418 pic14_emitcode("rl","a");
6419 pic14_emitcode("anl","a,#0x01");
6420 pic14_outAcc(result);
6424 freeAsmop(left,NULL,ic,TRUE);
6425 freeAsmop(result,NULL,ic,TRUE);
6428 /*-----------------------------------------------------------------*/
6429 /* AccLsh - shift left accumulator by known count */
6430 /* MARK: pic14 always rotates through CARRY! */
6431 /*-----------------------------------------------------------------*/
6432 static void AccLsh (pCodeOp *pcop,int shCount)
6435 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6436 shCount &= 0x0007; // shCount : 0..7
6443 emitpcode(POC_RLF,pcop);
6447 emitpcode(POC_RLF,pcop);
6448 emitpcode(POC_RLF,pcop);
6451 emitpcode(POC_RLF,pcop);
6452 emitpcode(POC_RLF,pcop);
6453 emitpcode(POC_RLF,pcop);
6456 emitpcode(POC_SWAPF,pcop);
6459 emitpcode(POC_SWAPF,pcop);
6460 emitpcode(POC_RLF,pcop);
6463 emitpcode(POC_SWAPF,pcop);
6464 emitpcode(POC_RLF,pcop);
6465 emitpcode(POC_RLF,pcop);
6468 emitpcode(POC_RRFW,pcop);
6469 emitpcode(POC_RRF,pcop);
6472 /* clear invalid bits */
6473 emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6474 emitpcode(POC_ANDWF, pcop);
6477 /*-----------------------------------------------------------------*/
6478 /* AccRsh - shift right accumulator by known count */
6479 /* MARK: pic14 always rotates through CARRY! */
6480 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6481 /* 1: mask out invalid bits (zero-extend) */
6482 /* 2: sign-extend result (pretty slow) */
6483 /*-----------------------------------------------------------------*/
6484 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6487 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6488 shCount &= 0x0007; // shCount : 0..7
6494 /* load sign if needed */
6495 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6496 else if (mask_mode == 1) emitCLRC;
6497 emitpcode(POC_RRF,pcop);
6501 /* load sign if needed */
6502 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6503 emitpcode(POC_RRF,pcop);
6504 /* load sign if needed */
6505 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6506 emitpcode(POC_RRF,pcop);
6507 if (mask_mode == 2) return;
6510 /* load sign if needed */
6511 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6512 emitpcode(POC_RRF,pcop);
6513 /* load sign if needed */
6514 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6515 emitpcode(POC_RRF,pcop);
6516 /* load sign if needed */
6517 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6518 emitpcode(POC_RRF,pcop);
6519 if (mask_mode == 2) return;
6522 emitpcode(POC_SWAPF,pcop);
6525 emitpcode(POC_SWAPF,pcop);
6526 emitpcode(POC_RRF,pcop);
6529 emitpcode(POC_SWAPF,pcop);
6530 emitpcode(POC_RRF,pcop);
6531 emitpcode(POC_RRF,pcop);
6537 emitpcode(POC_RLFW,pcop);
6538 emitpcode(POC_CLRF,pcop);
6540 emitpcode(POC_COMF,pcop);
6543 emitpcode(POC_RLFW,pcop);
6544 emitpcode(POC_RLF,pcop);
6551 /* leave invalid bits undefined */
6555 /* clear invalid bits -- zero-extend */
6556 emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6557 emitpcode(POC_ANDWF, pcop);
6559 if (mask_mode == 2) {
6561 emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6562 emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6563 emitpcode(POC_IORWF, pcop);
6568 /*-----------------------------------------------------------------*/
6569 /* AccSRsh - signed right shift accumulator by known count */
6570 /*-----------------------------------------------------------------*/
6571 static void AccSRsh (int shCount)
6574 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6577 pic14_emitcode("mov","c,acc.7");
6578 pic14_emitcode("rrc","a");
6579 } else if(shCount == 2){
6580 pic14_emitcode("mov","c,acc.7");
6581 pic14_emitcode("rrc","a");
6582 pic14_emitcode("mov","c,acc.7");
6583 pic14_emitcode("rrc","a");
6585 tlbl = newiTempLabel(NULL);
6586 /* rotate right accumulator */
6587 AccRol(8 - shCount);
6588 /* and kill the higher order bits */
6589 pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6590 pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6591 pic14_emitcode("orl","a,#0x%02x",
6592 (unsigned char)~SRMask[shCount]);
6593 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6598 /*-----------------------------------------------------------------*/
6599 /* shiftR1Left2Result - shift right one byte from left to result */
6600 /*-----------------------------------------------------------------*/
6601 static void shiftR1Left2ResultSigned (operand *left, int offl,
6602 operand *result, int offr,
6608 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6610 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6614 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6616 emitpcode(POC_RRF, popGet(AOP(result),offr));
6618 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6619 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6625 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6627 emitpcode(POC_RRF, popGet(AOP(result),offr));
6629 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6630 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6632 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6633 emitpcode(POC_RRF, popGet(AOP(result),offr));
6639 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6641 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6642 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6645 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6646 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6647 emitpcode(POC_ANDLW, popGetLit(0x1f));
6649 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6650 emitpcode(POC_IORLW, popGetLit(0xe0));
6652 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6656 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6657 emitpcode(POC_ANDLW, popGetLit(0x0f));
6658 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6659 emitpcode(POC_IORLW, popGetLit(0xf0));
6660 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6664 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6666 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6667 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6669 emitpcode(POC_RRFW, popGet(AOP(result),offr));
6670 emitpcode(POC_ANDLW, popGetLit(0x07));
6671 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6672 emitpcode(POC_IORLW, popGetLit(0xf8));
6673 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6678 emitpcode(POC_MOVLW, popGetLit(0x00));
6679 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6680 emitpcode(POC_MOVLW, popGetLit(0xfe));
6681 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6682 emitpcode(POC_IORLW, popGetLit(0x01));
6683 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6685 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6686 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6687 emitpcode(POC_DECF, popGet(AOP(result),offr));
6688 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6689 emitpcode(POC_BCF, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6695 emitpcode(POC_MOVLW, popGetLit(0x00));
6696 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6697 emitpcode(POC_MOVLW, popGetLit(0xff));
6698 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6700 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6701 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6702 emitpcode(POC_DECF, popGet(AOP(result),offr));
6710 /*-----------------------------------------------------------------*/
6711 /* shiftR1Left2Result - shift right one byte from left to result */
6712 /*-----------------------------------------------------------------*/
6713 static void shiftR1Left2Result (operand *left, int offl,
6714 operand *result, int offr,
6715 int shCount, int sign)
6720 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6722 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6724 /* Copy the msb into the carry if signed. */
6726 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6736 emitpcode(POC_RRF, popGet(AOP(result),offr));
6738 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6739 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6745 emitpcode(POC_RRF, popGet(AOP(result),offr));
6747 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6748 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6751 emitpcode(POC_RRF, popGet(AOP(result),offr));
6756 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6758 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6759 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6762 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6763 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6764 emitpcode(POC_ANDLW, popGetLit(0x1f));
6765 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6769 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6770 emitpcode(POC_ANDLW, popGetLit(0x0f));
6771 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6775 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6776 emitpcode(POC_ANDLW, popGetLit(0x0f));
6777 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6779 emitpcode(POC_RRF, popGet(AOP(result),offr));
6784 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6785 emitpcode(POC_ANDLW, popGetLit(0x80));
6786 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6787 emitpcode(POC_RLF, popGet(AOP(result),offr));
6788 emitpcode(POC_RLF, popGet(AOP(result),offr));
6793 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6794 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6795 emitpcode(POC_RLF, popGet(AOP(result),offr));
6804 /*-----------------------------------------------------------------*/
6805 /* shiftL1Left2Result - shift left one byte from left to result */
6806 /*-----------------------------------------------------------------*/
6807 static void shiftL1Left2Result (operand *left, int offl,
6808 operand *result, int offr, int shCount)
6814 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6816 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6817 DEBUGpic14_emitcode ("; ***","same = %d",same);
6818 // l = aopGet(AOP(left),offl,FALSE,FALSE);
6820 /* shift left accumulator */
6821 //AccLsh(shCount); // don't comment out just yet...
6822 // aopPut(AOP(result),"a",offr);
6826 /* Shift left 1 bit position */
6827 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6829 emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6831 emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6832 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6836 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6837 emitpcode(POC_ANDLW,popGetLit(0x7e));
6838 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6839 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6842 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6843 emitpcode(POC_ANDLW,popGetLit(0x3e));
6844 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6845 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6846 emitpcode(POC_RLF, popGet(AOP(result),offr));
6849 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6850 emitpcode(POC_ANDLW, popGetLit(0xf0));
6851 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6854 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6855 emitpcode(POC_ANDLW, popGetLit(0xf0));
6856 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6857 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6860 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6861 emitpcode(POC_ANDLW, popGetLit(0x30));
6862 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6863 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6864 emitpcode(POC_RLF, popGet(AOP(result),offr));
6867 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6868 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6869 emitpcode(POC_RRF, popGet(AOP(result),offr));
6873 DEBUGpic14_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6879 /*-----------------------------------------------------------------*/
6880 /* movLeft2Result - move byte from left to result */
6881 /*-----------------------------------------------------------------*/
6882 static void movLeft2Result (operand *left, int offl,
6883 operand *result, int offr)
6887 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6888 if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6889 l = aopGet(AOP(left),offl,FALSE,FALSE);
6891 if (*l == '@' && (IS_AOP_PREG(result))) {
6892 pic14_emitcode("mov","a,%s",l);
6893 aopPut(AOP(result),"a",offr);
6895 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6896 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6901 /*-----------------------------------------------------------------*/
6902 /* shiftLeft_Left2ResultLit - shift left by known count */
6903 /*-----------------------------------------------------------------*/
6905 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6907 int size, same, offr, i;
6909 size = AOP_SIZE(left);
6910 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6912 same = pic14_sameRegs (AOP(left), AOP(result));
6915 shCount = shCount & 0x07;
6921 case 0: /* takes 0 or 2N cycles (for offr==0) */
6922 if (!same || offr) {
6923 for (i=size-1; i >= 0; i--)
6924 movLeft2Result (left, i, result, offr + i);
6928 case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6930 shiftLeft_Left2ResultLit (left, result, 8 * offr);
6931 shiftLeft_Left2ResultLit (result, result, shCount);
6932 return; /* prevent clearing result again */
6935 for (i=0; i < size; i++) {
6936 if (same && !offr) {
6937 emitpcode (POC_RLF, popGet (AOP(left), i));
6939 emitpcode (POC_RLFW, popGet (AOP(left), i));
6940 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6946 case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
6947 /* works in-place/with offr as well */
6948 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
6949 emitpcode (POC_ANDLW, popGetLit (0xF0));
6950 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
6952 for (i = size - 2; i >= 0; i--)
6954 emitpcode (POC_SWAPFW, popGet (AOP(left), i));
6955 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6956 emitpcode (POC_ANDLW, popGetLit (0x0F));
6957 emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
6958 emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
6962 case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
6963 /* works in-place/with offr as well */
6964 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
6965 for (i = size-2; i >= 0; i--) {
6966 emitpcode (POC_RRFW, popGet (AOP(left), i));
6967 emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
6969 emitpcode (POC_CLRF, popGet (AOP(result), offr));
6970 emitpcode (POC_RRF, popGet (AOP(result), offr));
6974 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
6975 shiftLeft_Left2ResultLit (result, result, 1);
6976 return; /* prevent clearing result again */
6982 emitpcode (POC_CLRF, popGet (AOP(result), offr));
6986 /*-----------------------------------------------------------------*/
6987 /* shiftRight_Left2ResultLit - shift right by known count */
6988 /*-----------------------------------------------------------------*/
6990 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
6992 int size, same, offr, i;
6994 size = AOP_SIZE(left);
6995 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6997 same = pic14_sameRegs (AOP(left), AOP(result));
7000 shCount = shCount & 0x07;
7008 case 0: /* takes 0 or 2N cycles (for offr==0) */
7009 if (!same || offr) {
7010 for (i=0; i < size; i++)
7011 movLeft2Result (left, i + offr, result, i);
7015 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7016 emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7018 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7019 shiftRight_Left2ResultLit (result, result, shCount, sign);
7020 return; /* prevent sign-extending result again */
7024 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7027 for (i = size-1; i >= 0; i--) {
7028 if (same && !offr) {
7029 emitpcode (POC_RRF, popGet (AOP(left), i));
7031 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7032 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7038 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7039 /* works in-place/with offr as well */
7040 emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7041 emitpcode (POC_ANDLW, popGetLit (0x0F));
7042 emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7044 for (i = 1; i < size; i++)
7046 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7047 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7048 emitpcode (POC_ANDLW, popGetLit (0xF0));
7049 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7050 emitpcode (POC_XORWF, popGet (AOP(result), i));
7055 emitpcode (POC_MOVLW, popGetLit (0xF0));
7056 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7057 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7061 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7062 /* works in-place/with offr as well */
7063 emitpcode (POC_RLFW, popGet (AOP(left), offr));
7064 for (i = 0; i < size-1; i++) {
7065 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7066 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7068 emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7070 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7073 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7078 shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7079 shiftRight_Left2ResultLit (result, result, 1, sign);
7080 return; /* prevent sign extending result again */
7085 addSign (result, size, sign);
7089 /*-----------------------------------------------------------------*/
7090 /* shiftL2Left2Result - shift left two bytes from left to result */
7091 /*-----------------------------------------------------------------*/
7092 static void shiftL2Left2Result (operand *left, int offl,
7093 operand *result, int offr, int shCount)
7097 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7099 if(pic14_sameRegs(AOP(result), AOP(left))) {
7107 emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7108 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7109 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7113 emitpcode(POC_RLF, popGet(AOP(result),offr));
7114 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7120 emitpcode(POC_MOVLW, popGetLit(0x0f));
7121 emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7122 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7123 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7124 emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7125 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7126 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7128 emitpcode(POC_RLF, popGet(AOP(result),offr));
7129 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7133 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7134 emitpcode(POC_RRF, popGet(AOP(result),offr));
7135 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7136 emitpcode(POC_RRF, popGet(AOP(result),offr));
7137 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7138 emitpcode(POC_ANDLW,popGetLit(0xc0));
7139 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7140 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7141 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7142 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7145 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7146 emitpcode(POC_RRFW, popGet(AOP(result),offr));
7147 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7148 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7149 emitpcode(POC_RRF, popGet(AOP(result),offr));
7159 /* note, use a mov/add for the shift since the mov has a
7160 chance of getting optimized out */
7161 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7162 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7163 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7164 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7165 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7169 emitpcode(POC_RLF, popGet(AOP(result),offr));
7170 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7176 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7177 emitpcode(POC_ANDLW, popGetLit(0xF0));
7178 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7179 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7180 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7181 emitpcode(POC_ANDLW, popGetLit(0xF0));
7182 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7183 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7187 emitpcode(POC_RLF, popGet(AOP(result),offr));
7188 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7192 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7193 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7194 emitpcode(POC_RRFW, popGet(AOP(result),offl));
7195 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7197 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7198 emitpcode(POC_RRF, popGet(AOP(result),offr));
7199 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7200 emitpcode(POC_ANDLW,popGetLit(0xc0));
7201 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7202 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7203 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7204 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7207 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7208 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7209 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7210 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7211 emitpcode(POC_RRF, popGet(AOP(result),offr));
7217 /*-----------------------------------------------------------------*/
7218 /* shiftR2Left2Result - shift right two bytes from left to result */
7219 /*-----------------------------------------------------------------*/
7220 static void shiftR2Left2Result (operand *left, int offl,
7221 operand *result, int offr,
7222 int shCount, int sign)
7227 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7228 same = pic14_sameRegs(AOP(result), AOP(left));
7230 if(same && ((offl + MSB16) == offr)){
7232 /* don't crash result[offr] */
7233 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7234 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7237 movLeft2Result(left,offl, result, offr);
7238 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7241 /* a:x >> shCount (x = lsb(result))*/
7244 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7246 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7255 emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7260 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7261 emitpcode(POC_RRF,popGet(AOP(result),offr));
7263 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7264 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7265 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7266 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7271 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7274 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7275 emitpcode(POC_RRF,popGet(AOP(result),offr));
7282 emitpcode(POC_MOVLW, popGetLit(0xf0));
7283 emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7284 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7286 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7287 emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7288 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7289 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7291 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7292 emitpcode(POC_ANDLW, popGetLit(0x0f));
7293 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7295 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7296 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7297 emitpcode(POC_ANDLW, popGetLit(0xf0));
7298 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7299 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7303 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7304 emitpcode(POC_RRF, popGet(AOP(result),offr));
7308 emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7309 emitpcode(POC_BTFSC,
7310 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7311 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7319 emitpcode(POC_RLF, popGet(AOP(result),offr));
7320 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7322 emitpcode(POC_RLF, popGet(AOP(result),offr));
7323 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7324 emitpcode(POC_RLFW, popGet(AOP(result),offr));
7325 emitpcode(POC_ANDLW,popGetLit(0x03));
7327 emitpcode(POC_BTFSC,
7328 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7329 emitpcode(POC_IORLW,popGetLit(0xfc));
7331 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7332 emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7333 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7334 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7336 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7337 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7338 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7339 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7340 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7341 emitpcode(POC_RLF, popGet(AOP(result),offr));
7342 emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7343 emitpcode(POC_ANDLW,popGetLit(0x03));
7345 emitpcode(POC_BTFSC,
7346 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7347 emitpcode(POC_IORLW,popGetLit(0xfc));
7349 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7350 //emitpcode(POC_RLF, popGet(AOP(result),offr));
7357 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7358 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7359 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7360 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7363 emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7365 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7369 /*-----------------------------------------------------------------*/
7370 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7371 /*-----------------------------------------------------------------*/
7372 static void shiftLLeftOrResult (operand *left, int offl,
7373 operand *result, int offr, int shCount)
7376 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7378 /* shift left accumulator */
7379 AccLsh(left,offl,shCount);
7380 /* or with result */
7381 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7382 assert ( !"broken (modifies left, fails for left==result))" );
7385 /*-----------------------------------------------------------------*/
7386 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7387 /*-----------------------------------------------------------------*/
7388 static void shiftRLeftOrResult (operand *left, int offl,
7389 operand *result, int offr, int shCount)
7392 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7394 /* shift right accumulator */
7395 AccRsh(left,offl,shCount);
7396 /* or with result */
7397 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7398 assert ( !"broken (modifies left, fails for left==result))" );
7401 /*-----------------------------------------------------------------*/
7402 /* genlshOne - left shift a one byte quantity by known count */
7403 /*-----------------------------------------------------------------*/
7404 static void genlshOne (operand *result, operand *left, int shCount)
7407 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7408 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7411 /*-----------------------------------------------------------------*/
7412 /* genlshTwo - left shift two bytes by known amount != 0 */
7413 /*-----------------------------------------------------------------*/
7414 static void genlshTwo (operand *result,operand *left, int shCount)
7419 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7420 size = pic14_getDataSize(result);
7422 /* if shCount >= 8 */
7428 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7430 movLeft2Result(left, LSB, result, MSB16);
7432 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7435 /* 1 <= shCount <= 7 */
7438 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7440 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7444 /*-----------------------------------------------------------------*/
7445 /* shiftLLong - shift left one long from left to result */
7446 /* offl = LSB or MSB16 */
7447 /*-----------------------------------------------------------------*/
7448 static void shiftLLong (operand *left, operand *result, int offr )
7451 int size = AOP_SIZE(result);
7454 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7455 if(size >= LSB+offr){
7456 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7458 pic14_emitcode("add","a,acc");
7459 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7460 size >= MSB16+offr && offr != LSB )
7461 pic14_emitcode("xch","a,%s",
7462 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7464 aopPut(AOP(result),"a",LSB+offr);
7467 if(size >= MSB16+offr){
7468 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7469 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7472 pic14_emitcode("rlc","a");
7473 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7474 size >= MSB24+offr && offr != LSB)
7475 pic14_emitcode("xch","a,%s",
7476 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7478 aopPut(AOP(result),"a",MSB16+offr);
7481 if(size >= MSB24+offr){
7482 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7483 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7486 pic14_emitcode("rlc","a");
7487 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7488 size >= MSB32+offr && offr != LSB )
7489 pic14_emitcode("xch","a,%s",
7490 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7492 aopPut(AOP(result),"a",MSB24+offr);
7495 if(size > MSB32+offr){
7496 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7497 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7500 pic14_emitcode("rlc","a");
7501 aopPut(AOP(result),"a",MSB32+offr);
7504 aopPut(AOP(result),zero,LSB);
7507 /*-----------------------------------------------------------------*/
7508 /* genlshFour - shift four byte by a known amount != 0 */
7509 /*-----------------------------------------------------------------*/
7510 static void genlshFour (operand *result, operand *left, int shCount)
7515 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7516 size = AOP_SIZE(result);
7518 /* if shifting more that 3 bytes */
7519 if (shCount >= 24 ) {
7522 /* lowest order of left goes to the highest
7523 order of the destination */
7524 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7526 movLeft2Result(left, LSB, result, MSB32);
7527 aopPut(AOP(result),zero,LSB);
7528 aopPut(AOP(result),zero,MSB16);
7529 aopPut(AOP(result),zero,MSB32);
7533 /* more than two bytes */
7534 else if ( shCount >= 16 ) {
7535 /* lower order two bytes goes to higher order two bytes */
7537 /* if some more remaining */
7539 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7541 movLeft2Result(left, MSB16, result, MSB32);
7542 movLeft2Result(left, LSB, result, MSB24);
7544 aopPut(AOP(result),zero,MSB16);
7545 aopPut(AOP(result),zero,LSB);
7549 /* if more than 1 byte */
7550 else if ( shCount >= 8 ) {
7551 /* lower order three bytes goes to higher order three bytes */
7555 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7557 movLeft2Result(left, LSB, result, MSB16);
7559 else{ /* size = 4 */
7561 movLeft2Result(left, MSB24, result, MSB32);
7562 movLeft2Result(left, MSB16, result, MSB24);
7563 movLeft2Result(left, LSB, result, MSB16);
7564 aopPut(AOP(result),zero,LSB);
7566 else if(shCount == 1)
7567 shiftLLong(left, result, MSB16);
7569 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7570 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7571 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7572 aopPut(AOP(result),zero,LSB);
7577 /* 1 <= shCount <= 7 */
7578 else if(shCount <= 2){
7579 shiftLLong(left, result, LSB);
7581 shiftLLong(result, result, LSB);
7583 /* 3 <= shCount <= 7, optimize */
7585 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7586 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7587 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7593 /*-----------------------------------------------------------------*/
7594 /* genLeftShiftLiteral - left shifting by known count */
7595 /*-----------------------------------------------------------------*/
7596 static void genLeftShiftLiteral (operand *left,
7601 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7605 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7606 freeAsmop(right,NULL,ic,TRUE);
7608 aopOp(left,ic,FALSE);
7609 aopOp(result,ic,FALSE);
7611 size = getSize(operandType(result));
7614 pic14_emitcode("; shift left ","result %d, left %d",size,
7618 /* I suppose that the left size >= result size */
7621 movLeft2Result(left, size, result, size);
7625 else if(shCount >= (size * 8))
7627 aopPut(AOP(result),zero,size);
7631 genlshOne (result,left,shCount);
7636 genlshTwo (result,left,shCount);
7640 genlshFour (result,left,shCount);
7644 freeAsmop(left,NULL,ic,TRUE);
7645 freeAsmop(result,NULL,ic,TRUE);
7649 /*-----------------------------------------------------------------*
7650 * genMultiAsm - repeat assembly instruction for size of register.
7651 * if endian == 1, then the high byte (i.e base address + size of
7652 * register) is used first else the low byte is used first;
7653 *-----------------------------------------------------------------*/
7654 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7660 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7673 emitpcode(poc, popGet(AOP(reg),offset));
7680 /*-----------------------------------------------------------------*/
7681 /* genLeftShift - generates code for left shifting */
7682 /*-----------------------------------------------------------------*/
7683 static void genLeftShift (iCode *ic)
7685 operand *left,*right, *result;
7687 unsigned long lit = 0L;
7689 symbol *tlbl , *tlbl1;
7693 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7695 right = IC_RIGHT(ic);
7697 result = IC_RESULT(ic);
7699 aopOp(right,ic,FALSE);
7700 aopOp(left,ic,FALSE);
7701 aopOp(result,ic,FALSE);
7704 /* if the shift count is known then do it
7705 as efficiently as possible */
7706 if (AOP_TYPE(right) == AOP_LIT) {
7707 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7711 /* shift count is unknown then we have to form
7712 a loop get the loop count in B : Note: we take
7713 only the lower order byte since shifting
7714 more that 32 bits make no sense anyway, ( the
7715 largest size of an object can be only 32 bits ) */
7717 /* this code fails for RIGHT == RESULT */
7718 assert (!pic14_sameRegs (AOP(right), AOP(result)));
7720 /* now move the left to the result if they are not the
7722 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
7723 AOP_SIZE(result) > 1) {
7725 size = AOP_SIZE(result);
7728 l = aopGet(AOP(left),offset,FALSE,TRUE);
7729 if (*l == '@' && (IS_AOP_PREG(result))) {
7731 pic14_emitcode("mov","a,%s",l);
7732 aopPut(AOP(result),"a",offset);
7734 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
7735 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7736 //aopPut(AOP(result),l,offset);
7742 if(AOP_TYPE(left) == AOP_LIT)
7743 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7745 size = AOP_SIZE(result);
7747 /* if it is only one byte then */
7749 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7750 emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7751 emitpcode(POC_ANDLW, popGetLit(0xf0));
7752 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7753 emitpcode(POC_MOVFW, popGet(AOP(left),0));
7754 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7755 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7756 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7757 emitpcode(POC_RLFW, popGet(AOP(result),0));
7758 emitpcode(POC_ANDLW, popGetLit(0xfe));
7759 emitpcode(POC_ADDFW, popGet(AOP(result),0));
7760 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7761 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7764 tlbl = newiTempLabel(NULL);
7765 if (!pic14_sameRegs(AOP(left),AOP(result))) {
7766 mov2w (AOP(left), 0);
7767 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7770 emitpcode(POC_COMFW, popGet(AOP(right),0));
7771 emitpcode(POC_RRF, popGet(AOP(result),0));
7772 emitpLabel(tlbl->key);
7773 emitpcode(POC_RLF, popGet(AOP(result),0));
7774 emitpcode(POC_ADDLW, popGetLit(1));
7776 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7781 if (pic14_sameRegs(AOP(left),AOP(result))) {
7783 tlbl = newiTempLabel(NULL);
7784 emitpcode(POC_COMFW, popGet(AOP(right),0));
7785 genMultiAsm(POC_RRF, result, size,1);
7786 emitpLabel(tlbl->key);
7787 genMultiAsm(POC_RLF, result, size,0);
7788 emitpcode(POC_ADDLW, popGetLit(1));
7790 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7794 //tlbl = newiTempLabel(NULL);
7796 //tlbl1 = newiTempLabel(NULL);
7798 //reAdjustPreg(AOP(result));
7800 //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7801 //pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7802 //l = aopGet(AOP(result),offset,FALSE,FALSE);
7804 //pic14_emitcode("add","a,acc");
7805 //aopPut(AOP(result),"a",offset++);
7807 // l = aopGet(AOP(result),offset,FALSE,FALSE);
7809 // pic14_emitcode("rlc","a");
7810 // aopPut(AOP(result),"a",offset++);
7812 //reAdjustPreg(AOP(result));
7814 //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7815 //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7818 tlbl = newiTempLabel(NULL);
7819 tlbl1= newiTempLabel(NULL);
7821 size = AOP_SIZE(result);
7824 pctemp = popGetTempReg(); /* grab a temporary working register. */
7826 emitpcode(POC_MOVFW, popGet(AOP(right),0));
7828 /* offset should be 0, 1 or 3 */
7829 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7831 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
7833 emitpcode(POC_MOVWF, pctemp);
7836 emitpLabel(tlbl->key);
7839 emitpcode(POC_RLF, popGet(AOP(result),0));
7841 emitpcode(POC_RLF, popGet(AOP(result),offset++));
7843 emitpcode(POC_DECFSZ, pctemp);
7844 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7845 emitpLabel(tlbl1->key);
7847 popReleaseTempReg(pctemp);
7851 freeAsmop (right,NULL,ic,TRUE);
7852 freeAsmop(left,NULL,ic,TRUE);
7853 freeAsmop(result,NULL,ic,TRUE);
7858 /*-----------------------------------------------------------------*/
7859 /* genrshOne - right shift a one byte quantity by known count */
7860 /*-----------------------------------------------------------------*/
7861 static void genrshOne (operand *result, operand *left,
7862 int shCount, int sign)
7865 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7866 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7869 /*-----------------------------------------------------------------*/
7870 /* genrshTwo - right shift two bytes by known amount != 0 */
7871 /*-----------------------------------------------------------------*/
7872 static void genrshTwo (operand *result,operand *left,
7873 int shCount, int sign)
7876 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7877 /* if shCount >= 8 */
7881 shiftR1Left2Result(left, MSB16, result, LSB,
7884 movLeft2Result(left, MSB16, result, LSB);
7886 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7889 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7890 emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7894 /* 1 <= shCount <= 7 */
7896 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
7899 /*-----------------------------------------------------------------*/
7900 /* shiftRLong - shift right one long from left to result */
7901 /* offl = LSB or MSB16 */
7902 /*-----------------------------------------------------------------*/
7903 static void shiftRLong (operand *left, int offl,
7904 operand *result, int sign)
7909 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7911 size = AOP_SIZE(left);
7912 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7915 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7919 assert (offl >= 0 && offl < size);
7921 same = pic14_sameRegs (AOP(left), AOP(result));
7923 /* perform the shift */
7926 if (same && !offl) {
7927 emitpcode (POC_RRF, popGet (AOP(result), size));
7929 emitpcode (POC_RRFW, popGet (AOP(left), size));
7930 emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7934 addSign (result, AOP_SIZE(left) - offl, sign);
7937 /*-----------------------------------------------------------------*/
7938 /* genrshFour - shift four byte by a known amount != 0 */
7939 /*-----------------------------------------------------------------*/
7940 static void genrshFour (operand *result, operand *left,
7941 int shCount, int sign)
7944 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7945 /* if shifting more that 3 bytes */
7946 if(shCount >= 24 ) {
7949 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7951 movLeft2Result(left, MSB32, result, LSB);
7953 addSign(result, MSB16, sign);
7955 else if(shCount >= 16){
7958 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7960 movLeft2Result(left, MSB24, result, LSB);
7961 movLeft2Result(left, MSB32, result, MSB16);
7963 addSign(result, MSB24, sign);
7965 else if(shCount >= 8){
7968 shiftRLong(left, MSB16, result, sign);
7969 else if(shCount == 0){
7970 movLeft2Result(left, MSB16, result, LSB);
7971 movLeft2Result(left, MSB24, result, MSB16);
7972 movLeft2Result(left, MSB32, result, MSB24);
7973 addSign(result, MSB32, sign);
7976 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7977 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7978 /* the last shift is signed */
7979 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7980 addSign(result, MSB32, sign);
7983 else{ /* 1 <= shCount <= 7 */
7985 shiftRLong(left, LSB, result, sign);
7987 shiftRLong(result, LSB, result, sign);
7990 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7991 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7992 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7997 /*-----------------------------------------------------------------*/
7998 /* genRightShiftLiteral - right shifting by known count */
7999 /*-----------------------------------------------------------------*/
8000 static void genRightShiftLiteral (operand *left,
8006 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8010 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8011 freeAsmop(right,NULL,ic,TRUE);
8013 aopOp(left,ic,FALSE);
8014 aopOp(result,ic,FALSE);
8017 pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8021 lsize = pic14_getDataSize(left);
8022 res_size = pic14_getDataSize(result);
8023 /* test the LEFT size !!! */
8025 /* I suppose that the left size >= result size */
8028 movLeft2Result(left, res_size, result, res_size);
8031 else if(shCount >= (lsize * 8)){
8034 emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8036 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8037 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8042 emitpcode(POC_MOVLW, popGetLit(0));
8043 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8044 emitpcode(POC_MOVLW, popGetLit(0xff));
8046 emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8051 emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8058 genrshOne (result,left,shCount,sign);
8062 genrshTwo (result,left,shCount,sign);
8066 genrshFour (result,left,shCount,sign);
8074 freeAsmop(left,NULL,ic,TRUE);
8075 freeAsmop(result,NULL,ic,TRUE);
8080 /*-----------------------------------------------------------------*/
8081 /* genSignedRightShift - right shift of signed number */
8082 /*-----------------------------------------------------------------*/
8083 static void genSignedRightShift (iCode *ic)
8085 operand *right, *left, *result;
8088 symbol *tlbl, *tlbl1 ;
8091 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8093 /* we do it the hard way put the shift count in b
8094 and loop thru preserving the sign */
8096 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8098 right = IC_RIGHT(ic);
8100 result = IC_RESULT(ic);
8102 aopOp(right,ic,FALSE);
8103 aopOp(left,ic,FALSE);
8104 aopOp(result,ic,FALSE);
8107 if ( AOP_TYPE(right) == AOP_LIT) {
8108 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8109 //genRightShiftLiteral (left,right,result,ic,1);
8112 /* shift count is unknown then we have to form
8113 a loop get the loop count in B : Note: we take
8114 only the lower order byte since shifting
8115 more that 32 bits make no sense anyway, ( the
8116 largest size of an object can be only 32 bits ) */
8118 //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8119 //pic14_emitcode("inc","b");
8120 //freeAsmop (right,NULL,ic,TRUE);
8121 //aopOp(left,ic,FALSE);
8122 //aopOp(result,ic,FALSE);
8124 /* now move the left to the result if they are not the
8126 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
8127 AOP_SIZE(result) > 1) {
8129 size = AOP_SIZE(result);
8133 l = aopGet(AOP(left),offset,FALSE,TRUE);
8134 if (*l == '@' && IS_AOP_PREG(result)) {
8135 pic14_emitcode("mov","a,%s",l);
8136 aopPut(AOP(result),"a",offset);
8138 aopPut(AOP(result),l,offset);
8140 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8141 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8147 /* mov the highest order bit to OVR */
8148 tlbl = newiTempLabel(NULL);
8149 tlbl1= newiTempLabel(NULL);
8151 size = AOP_SIZE(result);
8154 pctemp = popGetTempReg(); /* grab a temporary working register. */
8156 emitpcode(POC_MOVFW, popGet(AOP(right),0));
8158 /* offset should be 0, 1 or 3 */
8159 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8161 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8163 emitpcode(POC_MOVWF, pctemp);
8166 emitpLabel(tlbl->key);
8168 emitpcode(POC_RLFW, popGet(AOP(result),offset));
8169 emitpcode(POC_RRF, popGet(AOP(result),offset));
8172 emitpcode(POC_RRF, popGet(AOP(result),--offset));
8175 emitpcode(POC_DECFSZ, pctemp);
8176 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8177 emitpLabel(tlbl1->key);
8179 popReleaseTempReg(pctemp);
8181 size = AOP_SIZE(result);
8183 pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8184 pic14_emitcode("rlc","a");
8185 pic14_emitcode("mov","ov,c");
8186 /* if it is only one byte then */
8188 l = aopGet(AOP(left),0,FALSE,FALSE);
8190 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8191 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8192 pic14_emitcode("mov","c,ov");
8193 pic14_emitcode("rrc","a");
8194 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8195 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8196 aopPut(AOP(result),"a",0);
8200 reAdjustPreg(AOP(result));
8201 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8202 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8203 pic14_emitcode("mov","c,ov");
8205 l = aopGet(AOP(result),offset,FALSE,FALSE);
8207 pic14_emitcode("rrc","a");
8208 aopPut(AOP(result),"a",offset--);
8210 reAdjustPreg(AOP(result));
8211 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8212 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8217 freeAsmop(left,NULL,ic,TRUE);
8218 freeAsmop(result,NULL,ic,TRUE);
8219 freeAsmop(right,NULL,ic,TRUE);
8223 /*-----------------------------------------------------------------*/
8224 /* loadSignToC - load the operand's sign bit into CARRY */
8225 /*-----------------------------------------------------------------*/
8227 static void loadSignToC (operand *op)
8230 assert (op && AOP(op) && AOP_SIZE(op));
8233 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8237 /*-----------------------------------------------------------------*/
8238 /* genRightShift - generate code for right shifting */
8239 /*-----------------------------------------------------------------*/
8240 static void genGenericShift (iCode *ic, int shiftRight)
8242 operand *right, *left, *result;
8245 symbol *tlbl, *tlbl1, *inverselbl;
8248 /* if signed then we do it the hard way preserve the
8249 sign bit moving it inwards */
8250 retype = getSpec(operandType(IC_RESULT(ic)));
8251 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8253 /* signed & unsigned types are treated the same : i.e. the
8254 signed is NOT propagated inwards : quoting from the
8255 ANSI - standard : "for E1 >> E2, is equivalent to division
8256 by 2**E2 if unsigned or if it has a non-negative value,
8257 otherwise the result is implementation defined ", MY definition
8258 is that the sign does not get propagated */
8260 right = IC_RIGHT(ic);
8262 result = IC_RESULT(ic);
8264 aopOp(right,ic,FALSE);
8265 aopOp(left,ic,FALSE);
8266 aopOp(result,ic,FALSE);
8268 /* if the shift count is known then do it
8269 as efficiently as possible */
8270 if (AOP_TYPE(right) == AOP_LIT) {
8271 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8275 shiftRight = !shiftRight;
8279 shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8281 shiftLeft_Left2ResultLit (left, result, lit);
8282 //genRightShiftLiteral (left,right,result,ic, 0);
8286 /* shift count is unknown then we have to form
8287 a loop get the loop count in B : Note: we take
8288 only the lower order byte since shifting
8289 more that 32 bits make no sense anyway, ( the
8290 largest size of an object can be only 32 bits ) */
8292 /* we must not overwrite the shift counter */
8293 assert (!pic14_sameRegs(AOP(right),AOP(result)));
8295 /* now move the left to the result if they are not the
8297 if (!pic14_sameRegs(AOP(left),AOP(result)))
8299 size = min(AOP_SIZE(result), AOP_SIZE(left));
8301 mov2w(AOP(left), size);
8302 movwf(AOP(result), size);
8304 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8307 tlbl = newiTempLabel(NULL);
8308 tlbl1= newiTempLabel(NULL);
8310 size = AOP_SIZE(result);
8312 mov2w(AOP(right),0);
8313 if (!SPEC_USIGN(operandType(right)))
8315 inverselbl = newiTempLabel(NULL);
8316 /* signed shift count -- invert shift direction for c<0 */
8317 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8318 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8320 emitpcode(POC_SUBLW, popGetLit(0)); /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8321 /* check for `a = b >> c' with `-c == 0' */
8323 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8324 emitpLabel(tlbl->key);
8325 /* propagate the sign bit inwards for SIGNED result */
8326 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8327 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8328 emitpcode(POC_ADDLW, popGetLit(1)); /* clears CARRY (unless W==0 afterwards) */
8330 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8332 if (!SPEC_USIGN(operandType(right)))
8334 symbol *inv_loop = newiTempLabel(NULL);
8336 shiftRight = !shiftRight; /* invert shift direction */
8338 /* we came here from the code above -- we are done */
8339 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8341 /* emit code for shifting N<0 steps, count is already in W */
8342 emitpLabel(inverselbl->key);
8343 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8344 emitpLabel(inv_loop->key);
8345 /* propagate the sign bit inwards for SIGNED result */
8346 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8347 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8348 emitpcode(POC_ADDLW, popGetLit(1));
8350 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8353 emitpLabel(tlbl1->key);
8355 freeAsmop(left,NULL,ic,TRUE);
8356 freeAsmop (right,NULL,ic,TRUE);
8357 freeAsmop(result,NULL,ic,TRUE);
8360 static void genRightShift (iCode *ic)
8362 genGenericShift(ic, 1);
8365 static void genLeftShift (iCode *ic)
8367 genGenericShift(ic, 0);
8370 /*-----------------------------------------------------------------*/
8371 /* SetIrp - Set IRP bit */
8372 /*-----------------------------------------------------------------*/
8373 void SetIrp(operand *result) {
8375 if (AOP_TYPE(result) == AOP_LIT) {
8376 unsigned lit = (unsigned)operandLitValue(result);
8382 if (PCOP(AOP(result))->type == PO_LITERAL) {
8383 int addrs = PCOL(AOP(result))->lit;
8389 emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8390 if(AOP_SIZE(result) > 1) {
8391 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8399 setup_fsr (operand *ptr)
8402 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8404 /* also setup-up IRP */
8408 /*-----------------------------------------------------------------*/
8409 /* emitPtrByteGet - emits code to get a byte into WREG from an */
8410 /* arbitrary pointer (__code, __data, generic) */
8411 /*-----------------------------------------------------------------*/
8413 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8420 if (!alreadyAddressed) setup_fsr (src);
8421 emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8425 assert( AOP_SIZE(src) == 2 );
8427 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8429 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8430 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
8431 call_libraryfunc ("__gptrget1");
8435 assert( AOP_SIZE(src) == 3 );
8437 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8439 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8441 call_libraryfunc ("__gptrget1");
8445 assert( !"unhandled pointer type" );
8450 /*-----------------------------------------------------------------*/
8451 /* emitPtrByteSet - emits code to set a byte from src through a */
8452 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR). */
8453 /*-----------------------------------------------------------------*/
8455 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8462 if (!alreadyAddressed) setup_fsr (dst);
8463 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8467 assert( !"trying to assign to __code pointer" );
8471 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8473 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8475 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8477 call_libraryfunc ("__gptrput1");
8481 assert( !"unhandled pointer type" );
8486 /*-----------------------------------------------------------------*/
8487 /* genUnpackBits - generates code for unpacking bits */
8488 /*-----------------------------------------------------------------*/
8489 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8491 int rsize; /* result size */
8492 sym_link *etype; /* bitfield type information */
8493 int blen; /* bitfield length */
8494 int bstr; /* bitfield starting bit within byte */
8497 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8498 etype = getSpec(operandType(result));
8499 rsize = getSize (operandType (result));
8500 blen = SPEC_BLEN (etype);
8501 bstr = SPEC_BSTR (etype);
8503 /* single bit field case */
8505 if (ifx) { /* that is for an if statement */
8508 resolveIfx(&rIfx,ifx);
8509 if (ptype == -1) /* direct */
8510 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8512 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8513 emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8514 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8518 assert (!pic14_sameRegs (AOP(result), AOP(left)));
8519 for (i=0; i < AOP_SIZE(result); i++)
8520 emitpcode (POC_CLRF, popGet (AOP(result), i));
8525 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8526 /* adjust result below */
8533 emitPtrByteGet (left, ptype, FALSE);
8534 emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8536 /* adjust result below */
8540 assert( !"unhandled pointer type" );
8543 /* move sign-/zero extended bit to result */
8544 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8545 emitpcode (POC_INCF, popGet (AOP(result), 0));
8547 emitpcode (POC_DECF, popGet (AOP(result), 0));
8549 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8553 else if (blen <= 8 && ((blen + bstr) <= 8))
8558 for (i=0; i < AOP_SIZE(result); i++)
8559 emitpcode (POC_CLRF, popGet (AOP(result), i));
8564 mov2w(AOP(left), 0);
8571 emitPtrByteGet (left, ptype, FALSE);
8575 assert( !"unhandled pointer type" );
8579 emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8580 movwf(AOP(result), 0);
8581 AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8583 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8585 /* signed bitfield */
8586 assert (bstr + blen > 0);
8587 emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8588 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8589 emitpcode(POC_IORWF, popGet(AOP(result),0));
8591 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8595 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8599 /*-----------------------------------------------------------------*/
8600 /* genDataPointerGet - generates code when ptr offset is known */
8601 /*-----------------------------------------------------------------*/
8602 static void genDataPointerGet (operand *left,
8606 int size , offset = 0;
8609 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8612 /* optimization - most of the time, left and result are the same
8613 * address, but different types. for the pic code, we could omit
8616 aopOp(result,ic,TRUE);
8618 if (pic14_sameRegs (AOP(left), AOP(result)))
8621 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8623 //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8625 size = AOP_SIZE(result);
8626 if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8630 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8631 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8635 freeAsmop(left,NULL,ic,TRUE);
8636 freeAsmop(result,NULL,ic,TRUE);
8640 /*-----------------------------------------------------------------*/
8641 /* genNearPointerGet - pic14_emitcode for near pointer fetch */
8642 /*-----------------------------------------------------------------*/
8643 static void genNearPointerGet (operand *left,
8648 sym_link *ltype = operandType(left);
8649 sym_link *rtype = operandType(result);
8650 sym_link *retype= getSpec(rtype); /* bitfield type information */
8654 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8657 aopOp(left,ic,FALSE);
8659 /* if left is rematerialisable and
8660 result is not bit variable type and
8661 the left is pointer to data space i.e
8662 lower 128 bytes of space */
8663 if (AOP_TYPE(left) == AOP_PCODE && //AOP_TYPE(left) == AOP_IMMD &&
8664 !IS_BITVAR(retype) &&
8665 PIC_IS_DATA_PTR(ltype)) {
8666 genDataPointerGet (left,result,ic);
8670 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8671 aopOp (result,ic,FALSE);
8673 /* Check if can access directly instead of via a pointer */
8674 if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8675 && AOP_SIZE(result) == 1)
8680 if (IS_BITFIELD(getSpec(operandType(result))))
8682 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8686 /* If the pointer value is not in a the FSR then need to put it in */
8687 /* Must set/reset IRP bit for use with FSR. */
8692 /* if bitfield then unpack the bits */
8694 /* we have can just get the values */
8695 int size = AOP_SIZE(result);
8698 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8702 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8704 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8705 if (AOP_TYPE(result) == AOP_LIT) {
8706 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8708 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8710 if (size && !direct)
8711 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8716 /* now some housekeeping stuff */
8718 /* we had to allocate for this iCode */
8719 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8720 freeAsmop(NULL,aop,ic,TRUE);
8722 /* we did not allocate which means left
8723 already in a pointer register, then
8724 if size > 0 && this could be used again
8725 we have to point it back to where it
8727 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8728 if (AOP_SIZE(result) > 1 &&
8729 !OP_SYMBOL(left)->remat &&
8730 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8732 int size = AOP_SIZE(result) - 1;
8734 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8740 freeAsmop(left,NULL,ic,TRUE);
8741 freeAsmop(result,NULL,ic,TRUE);
8746 /*-----------------------------------------------------------------*/
8747 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch */
8748 /*-----------------------------------------------------------------*/
8749 static void genPagedPointerGet (operand *left,
8756 sym_link *rtype, *retype;
8759 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8761 rtype = operandType(result);
8762 retype= getSpec(rtype);
8764 aopOp(left,ic,FALSE);
8766 /* if the value is already in a pointer register
8767 then don't need anything more */
8768 if (!AOP_INPREG(AOP(left))) {
8769 /* otherwise get a free pointer register */
8771 preg = getFreePtr(ic,&aop,FALSE);
8772 pic14_emitcode("mov","%s,%s",
8774 aopGet(AOP(left),0,FALSE,TRUE));
8775 rname = preg->name ;
8777 rname = aopGet(AOP(left),0,FALSE,FALSE);
8779 freeAsmop(left,NULL,ic,TRUE);
8780 aopOp (result,ic,FALSE);
8782 /* if bitfield then unpack the bits */
8783 if (IS_BITFIELD(retype))
8784 genUnpackBits (result,left,rname,PPOINTER,0);
8786 /* we have can just get the values */
8787 int size = AOP_SIZE(result);
8792 pic14_emitcode("movx","a,@%s",rname);
8793 aopPut(AOP(result),"a",offset);
8798 pic14_emitcode("inc","%s",rname);
8802 /* now some housekeeping stuff */
8804 /* we had to allocate for this iCode */
8805 freeAsmop(NULL,aop,ic,TRUE);
8807 /* we did not allocate which means left
8808 already in a pointer register, then
8809 if size > 0 && this could be used again
8810 we have to point it back to where it
8812 if (AOP_SIZE(result) > 1 &&
8813 !OP_SYMBOL(left)->remat &&
8814 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8816 int size = AOP_SIZE(result) - 1;
8818 pic14_emitcode("dec","%s",rname);
8823 freeAsmop(result,NULL,ic,TRUE);
8828 /*-----------------------------------------------------------------*/
8829 /* genFarPointerGet - gget value from far space */
8830 /*-----------------------------------------------------------------*/
8831 static void genFarPointerGet (operand *left,
8832 operand *result, iCode *ic)
8835 sym_link *retype = getSpec(operandType(result));
8838 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8840 aopOp(left,ic,FALSE);
8842 /* if the operand is already in dptr
8843 then we do nothing else we move the value to dptr */
8844 if (AOP_TYPE(left) != AOP_STR) {
8845 /* if this is remateriazable */
8846 if (AOP_TYPE(left) == AOP_IMMD)
8847 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8848 else { /* we need to get it byte by byte */
8849 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8850 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8851 if (options.model == MODEL_FLAT24)
8853 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8857 /* so dptr know contains the address */
8858 freeAsmop(left,NULL,ic,TRUE);
8859 aopOp(result,ic,FALSE);
8861 /* if bit then unpack */
8862 if (IS_BITFIELD(retype))
8863 genUnpackBits(result,left,"dptr",FPOINTER,0);
8865 size = AOP_SIZE(result);
8869 pic14_emitcode("movx","a,@dptr");
8870 aopPut(AOP(result),"a",offset++);
8872 pic14_emitcode("inc","dptr");
8876 freeAsmop(result,NULL,ic,TRUE);
8881 /*-----------------------------------------------------------------*/
8882 /* genCodePointerGet - get value from code space */
8883 /*-----------------------------------------------------------------*/
8884 static void genCodePointerGet (operand *left,
8885 operand *result, iCode *ic)
8888 sym_link *retype = getSpec(operandType(result));
8890 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8892 aopOp(left,ic,FALSE);
8894 /* if the operand is already in dptr
8895 then we do nothing else we move the value to dptr */
8896 if (AOP_TYPE(left) != AOP_STR) {
8897 /* if this is remateriazable */
8898 if (AOP_TYPE(left) == AOP_IMMD)
8899 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8900 else { /* we need to get it byte by byte */
8901 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8902 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8903 if (options.model == MODEL_FLAT24)
8905 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8909 /* so dptr know contains the address */
8910 freeAsmop(left,NULL,ic,TRUE);
8911 aopOp(result,ic,FALSE);
8913 /* if bit then unpack */
8914 if (IS_BITFIELD(retype))
8915 genUnpackBits(result,left,"dptr",CPOINTER,0);
8917 size = AOP_SIZE(result);
8921 pic14_emitcode("clr","a");
8922 pic14_emitcode("movc","a,@a+dptr");
8923 aopPut(AOP(result),"a",offset++);
8925 pic14_emitcode("inc","dptr");
8929 freeAsmop(result,NULL,ic,TRUE);
8932 /*-----------------------------------------------------------------*/
8933 /* genGenPointerGet - gget value from generic pointer space */
8934 /*-----------------------------------------------------------------*/
8935 static void genGenPointerGet (operand *left,
8936 operand *result, iCode *ic)
8939 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8940 aopOp(left,ic,FALSE);
8941 aopOp(result,ic,FALSE);
8944 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8946 if (IS_BITFIELD(getSpec(operandType(result))))
8948 genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
8953 /* emit call to __gptrget */
8954 char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
8955 int size = AOP_SIZE(result);
8958 assert (size > 0 && size <= 4);
8960 /* pass arguments */
8961 assert (AOP_SIZE(left) == 3);
8962 mov2w(AOP(left), 0);
8963 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8964 mov2w(AOP(left), 1);
8965 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8966 mov2w(AOP(left), 2);
8967 call_libraryfunc (func[size]);
8970 movwf (AOP(result), --size);
8972 emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
8973 movwf (AOP(result), size);
8977 freeAsmop(left,NULL,ic,TRUE);
8978 freeAsmop(result,NULL,ic,TRUE);
8982 /*-----------------------------------------------------------------*/
8983 /* genConstPointerGet - get value from const generic pointer space */
8984 /*-----------------------------------------------------------------*/
8985 static void genConstPointerGet (operand *left,
8986 operand *result, iCode *ic)
8988 //sym_link *retype = getSpec(operandType(result));
8990 symbol *albl, *blbl;//, *clbl;
8997 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8998 aopOp(left,ic,FALSE);
8999 aopOp(result,ic,FALSE);
9001 size = AOP_SIZE(result);
9003 DEBUGpic14_AopType(__LINE__,left,NULL,result);
9005 DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
9007 lit = op_isLitLike (left);
9008 poc = lit ? POC_MOVLW : POC_MOVFW;
9010 if (IS_BITFIELD(getSpec(operandType(result))))
9012 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
9017 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
9018 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
9019 assert (size > 0 && size <= 4);
9022 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9024 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9025 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
9026 call_libraryfunc (func[size]);
9028 movwf(AOP(result),size-1);
9029 for (i = 1; i < size; i++)
9031 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
9032 movwf(AOP(result),size - 1 - i);
9037 freeAsmop(left,NULL,ic,TRUE);
9038 freeAsmop(result,NULL,ic,TRUE);
9041 /*-----------------------------------------------------------------*/
9042 /* genPointerGet - generate code for pointer get */
9043 /*-----------------------------------------------------------------*/
9044 static void genPointerGet (iCode *ic)
9046 operand *left, *result ;
9047 sym_link *type, *etype;
9051 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9054 result = IC_RESULT(ic) ;
9056 /* depending on the type of pointer we need to
9057 move it to the correct pointer register */
9058 type = operandType(left);
9059 etype = getSpec(type);
9061 if (IS_PTR_CONST(type))
9062 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9064 /* if left is of type of pointer then it is simple */
9065 if (IS_PTR(type) && !IS_FUNC(type->next))
9066 p_type = DCL_TYPE(type);
9068 /* we have to go by the storage class */
9069 p_type = PTR_TYPE(SPEC_OCLS(etype));
9071 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9073 if (SPEC_OCLS(etype)->codesp ) {
9074 DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9075 //p_type = CPOINTER ;
9078 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9079 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9080 /*p_type = FPOINTER ;*/
9082 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9083 DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9084 /* p_type = PPOINTER; */
9086 if (SPEC_OCLS(etype) == idata )
9087 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9088 /* p_type = IPOINTER; */
9090 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9091 /* p_type = POINTER ; */
9094 /* now that we have the pointer type we assign
9095 the pointer values */
9101 genNearPointerGet (left,result,ic);
9105 genPagedPointerGet(left,result,ic);
9109 genFarPointerGet (left,result,ic);
9113 genConstPointerGet (left,result,ic);
9117 genGenPointerGet (left,result,ic);
9120 assert ( !"unhandled pointer type" );
9126 /*-----------------------------------------------------------------*/
9127 /* genPackBits - generates code for packed bit storage */
9128 /*-----------------------------------------------------------------*/
9129 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9131 int blen; /* bitfield length */
9132 int bstr; /* bitfield starting bit within byte */
9133 int litval; /* source literal value (if AOP_LIT) */
9134 unsigned char mask; /* bitmask within current byte */
9137 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9139 blen = SPEC_BLEN (etype);
9140 bstr = SPEC_BSTR (etype);
9142 /* If the bitfield length is less than a byte and does not cross byte boundaries */
9143 if ((blen <= 8) && ((bstr + blen) <= 8))
9145 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9146 (unsigned char) (0xFF >> (8 - bstr)));
9148 if (AOP_TYPE (right) == AOP_LIT)
9150 /* Case with a bitfield length <8 and literal source */
9151 int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9158 if (AOP(result)->type == AOP_PCODE)
9159 pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9161 pcop = popGet(AOP(result),0);
9162 emitpcode(lit?POC_BSF:POC_BCF,pcop);
9168 emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9172 assert( !"trying to assign to bitfield via pointer to __code space" );
9176 emitPtrByteGet(result, p_type, FALSE);
9178 emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9180 emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9182 emitPtrByteSet(result, p_type, TRUE);
9186 assert( !"unhandled pointer type" );
9188 } // switch (p_type)
9191 litval = lit << bstr;
9192 litval &= (~mask) & 0x00ff;
9197 mov2w (AOP(result), 0);
9198 if ((litval|mask) != 0x00ff)
9199 emitpcode(POC_ANDLW, popGetLit (mask));
9201 emitpcode(POC_IORLW, popGetLit (litval));
9202 movwf (AOP(result), 0);
9208 emitPtrByteGet(result, p_type, FALSE);
9209 if ((litval|mask) != 0x00ff)
9210 emitpcode(POC_ANDLW, popGetLit (mask));
9212 emitpcode(POC_IORLW, popGetLit (litval));
9213 emitPtrByteSet(result, p_type, TRUE);
9217 assert( !"trying to assign to bitfield via pointer to __code space" );
9221 assert( !"unhandled pointer type" );
9228 /* right is no literal */
9233 /* Note more efficient code, of pre clearing bit then only setting it if required,
9234 * can only be done if it is known that the result is not a SFR */
9235 emitpcode(POC_RRFW,popGet(AOP(right),0));
9237 emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9239 emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9245 emitPtrByteGet (result, p_type, FALSE);
9246 emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9247 emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9248 emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9249 emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9250 emitPtrByteSet (result, p_type, TRUE);
9254 assert( !"trying to assign to bitfield via pointer to __code space" );
9258 assert( !"unhandled pointer type" );
9263 /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9264 pCodeOp *temp = popGetTempReg ();
9266 mov2w (AOP(right), 0);
9268 emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9270 emitpcode(POC_MOVWF, temp);
9272 AccLsh (temp, bstr);
9278 mov2w (AOP(result), 0);
9279 emitpcode(POC_ANDLW, popGetLit (mask));
9280 emitpcode(POC_IORFW, temp);
9281 movwf (AOP(result), 0);
9287 emitPtrByteGet (result, p_type, FALSE);
9288 emitpcode(POC_ANDLW, popGetLit (mask));
9289 emitpcode(POC_IORFW, temp);
9290 emitPtrByteSet (result, p_type, TRUE);
9294 assert( !"trying to assign to bitfield via pointer to __code space" );
9298 assert( !"unhandled pointer type" );
9302 popReleaseTempReg (temp);
9304 } // if (AOP(right)->type != AOP_LIT)
9306 } // if (blen <= 8 && ((blen + bstr) <= 8))
9308 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9311 /*-----------------------------------------------------------------*/
9312 /* genDataPointerSet - remat pointer to data space */
9313 /*-----------------------------------------------------------------*/
9314 static void genDataPointerSet(operand *right,
9318 int size, offset = 0 ;
9322 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9323 aopOp(right,ic,FALSE);
9324 aopOp(result,ic,FALSE);
9326 assert (IS_SYMOP(result));
9327 assert (IS_PTR(OP_SYM_TYPE(result)));
9329 if (AOP_TYPE(right) == AOP_LIT)
9332 size = AOP_SIZE(right);
9333 ressize = getSize(OP_SYM_ETYPE(result));
9334 if (size > ressize) size = ressize;
9335 //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9337 //assert( !"what's going on here?" );
9340 if ( AOP_TYPE(result) == AOP_PCODE) {
9341 fprintf(stderr,"genDataPointerSet %s, %d\n",
9342 AOP(result)->aopu.pcop->name,
9343 PCOI(AOP(result)->aopu.pcop)->offset);
9347 // tsd, was l+1 - the underline `_' prefix was being stripped
9349 emitpComment ("%s:%u: size=%d/%d, offset=%d, AOP_TYPE(res)=%d", __FILE__,__LINE__, size, ressize, offset, AOP_TYPE(result));
9351 if (AOP_TYPE(right) == AOP_LIT) {
9352 unsigned int lit = pic14aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
9353 //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9355 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9356 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9358 emitpcode(POC_CLRF, popGet(AOP(result), offset));
9361 //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9362 emitpcode(POC_MOVFW, popGet(AOP(right), offset));
9363 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9369 freeAsmop(right,NULL,ic,TRUE);
9370 freeAsmop(result,NULL,ic,TRUE);
9373 /*-----------------------------------------------------------------*/
9374 /* genNearPointerSet - pic14_emitcode for near pointer put */
9375 /*-----------------------------------------------------------------*/
9376 static void genNearPointerSet (operand *right,
9381 sym_link *ptype = operandType(result);
9382 sym_link *retype = getSpec(operandType(right));
9383 sym_link *letype = getSpec(ptype);
9388 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9389 aopOp(result,ic,FALSE);
9392 /* if the result is rematerializable &
9393 in data space & not a bit variable */
9394 //if (AOP_TYPE(result) == AOP_IMMD &&
9395 if (AOP_TYPE(result) == AOP_PCODE &&
9396 PIC_IS_DATA_PTR(ptype) &&
9397 !IS_BITVAR (retype) &&
9398 !IS_BITVAR (letype)) {
9399 genDataPointerSet (right,result,ic);
9400 freeAsmop(result,NULL,ic,TRUE);
9405 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9406 aopOp(right,ic,FALSE);
9407 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9409 /* Check if can access directly instead of via a pointer */
9410 if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9414 if (IS_BITFIELD (letype))
9416 genPackBits (letype, result, right, direct?-1:POINTER);
9420 /* If the pointer value is not in a the FSR then need to put it in */
9421 /* Must set/reset IRP bit for use with FSR. */
9422 /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9427 /* we have can just get the values */
9428 int size = AOP_SIZE(right);
9431 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9433 char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9435 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9437 if (AOP_TYPE(right) == AOP_LIT) {
9438 emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9440 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9443 emitpcode(POC_MOVWF,popGet(AOP(result),0));
9445 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9447 if (size && !direct)
9448 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9453 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9454 /* now some housekeeping stuff */
9456 /* we had to allocate for this iCode */
9457 freeAsmop(NULL,aop,ic,TRUE);
9459 /* we did not allocate which means left
9460 already in a pointer register, then
9461 if size > 0 && this could be used again
9462 we have to point it back to where it
9464 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9465 if (AOP_SIZE(right) > 1 &&
9466 !OP_SYMBOL(result)->remat &&
9467 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9469 int size = AOP_SIZE(right) - 1;
9471 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9475 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9478 freeAsmop(right,NULL,ic,TRUE);
9479 freeAsmop(result,NULL,ic,TRUE);
9483 /*-----------------------------------------------------------------*/
9484 /* genPagedPointerSet - pic14_emitcode for Paged pointer put */
9485 /*-----------------------------------------------------------------*/
9486 static void genPagedPointerSet (operand *right,
9496 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9498 retype= getSpec(operandType(right));
9500 aopOp(result,ic,FALSE);
9502 /* if the value is already in a pointer register
9503 then don't need anything more */
9504 if (!AOP_INPREG(AOP(result))) {
9505 /* otherwise get a free pointer register */
9507 preg = getFreePtr(ic,&aop,FALSE);
9508 pic14_emitcode("mov","%s,%s",
9510 aopGet(AOP(result),0,FALSE,TRUE));
9511 rname = preg->name ;
9513 rname = aopGet(AOP(result),0,FALSE,FALSE);
9515 freeAsmop(result,NULL,ic,TRUE);
9516 aopOp (right,ic,FALSE);
9518 /* if bitfield then unpack the bits */
9519 if (IS_BITFIELD(retype))
9520 genPackBits (retype,result,right,rname,PPOINTER);
9522 /* we have can just get the values */
9523 int size = AOP_SIZE(right);
9527 l = aopGet(AOP(right),offset,FALSE,TRUE);
9530 pic14_emitcode("movx","@%s,a",rname);
9533 pic14_emitcode("inc","%s",rname);
9539 /* now some housekeeping stuff */
9541 /* we had to allocate for this iCode */
9542 freeAsmop(NULL,aop,ic,TRUE);
9544 /* we did not allocate which means left
9545 already in a pointer register, then
9546 if size > 0 && this could be used again
9547 we have to point it back to where it
9549 if (AOP_SIZE(right) > 1 &&
9550 !OP_SYMBOL(result)->remat &&
9551 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9553 int size = AOP_SIZE(right) - 1;
9555 pic14_emitcode("dec","%s",rname);
9560 freeAsmop(right,NULL,ic,TRUE);
9565 /*-----------------------------------------------------------------*/
9566 /* genFarPointerSet - set value from far space */
9567 /*-----------------------------------------------------------------*/
9568 static void genFarPointerSet (operand *right,
9569 operand *result, iCode *ic)
9572 sym_link *retype = getSpec(operandType(right));
9575 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9576 aopOp(result,ic,FALSE);
9578 /* if the operand is already in dptr
9579 then we do nothing else we move the value to dptr */
9580 if (AOP_TYPE(result) != AOP_STR) {
9581 /* if this is remateriazable */
9582 if (AOP_TYPE(result) == AOP_IMMD)
9583 pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9584 else { /* we need to get it byte by byte */
9585 pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9586 pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9587 if (options.model == MODEL_FLAT24)
9589 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9593 /* so dptr know contains the address */
9594 freeAsmop(result,NULL,ic,TRUE);
9595 aopOp(right,ic,FALSE);
9597 /* if bit then unpack */
9598 if (IS_BITFIELD(retype))
9599 genPackBits(retype,result,right,"dptr",FPOINTER);
9601 size = AOP_SIZE(right);
9605 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9607 pic14_emitcode("movx","@dptr,a");
9609 pic14_emitcode("inc","dptr");
9613 freeAsmop(right,NULL,ic,TRUE);
9617 /*-----------------------------------------------------------------*/
9618 /* genGenPointerSet - set value from generic pointer space */
9619 /*-----------------------------------------------------------------*/
9620 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9622 sym_link *retype = getSpec(operandType(result));
9625 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9626 aopOp(right,ic,FALSE);
9627 aopOp(result,ic,FALSE);
9630 DEBUGpic14_AopType(__LINE__,right,NULL,result);
9632 if (IS_BITFIELD(retype))
9634 genPackBits (retype, result, right, GPOINTER);
9639 /* emit call to __gptrput */
9640 char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9641 int size = AOP_SIZE(right);
9644 assert (size == getSize(OP_SYM_ETYPE(result)));
9645 assert (size > 0 && size <= 4);
9647 /* pass arguments */
9648 /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9654 mov2w_op (right, off);
9655 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9660 assert (AOP_SIZE(result) == 3);
9661 mov2w(AOP(result), 0);
9662 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9663 mov2w(AOP(result), 1);
9664 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9665 mov2w(AOP(result), 2);
9666 call_libraryfunc (func[size]);
9669 freeAsmop(right,NULL,ic,TRUE);
9670 freeAsmop(result,NULL,ic,TRUE);
9673 /*-----------------------------------------------------------------*/
9674 /* genPointerSet - stores the value into a pointer location */
9675 /*-----------------------------------------------------------------*/
9676 static void genPointerSet (iCode *ic)
9678 operand *right, *result ;
9679 sym_link *type, *etype;
9683 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9685 right = IC_RIGHT(ic);
9686 result = IC_RESULT(ic) ;
9688 /* depending on the type of pointer we need to
9689 move it to the correct pointer register */
9690 type = operandType(result);
9691 etype = getSpec(type);
9692 /* if left is of type of pointer then it is simple */
9693 if (IS_PTR(type) && !IS_FUNC(type->next)) {
9694 p_type = DCL_TYPE(type);
9697 /* we have to go by the storage class */
9698 p_type = PTR_TYPE(SPEC_OCLS(etype));
9700 /* if (SPEC_OCLS(etype)->codesp ) { */
9701 /* p_type = CPOINTER ; */
9704 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9705 /* p_type = FPOINTER ; */
9707 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9708 /* p_type = PPOINTER ; */
9710 /* if (SPEC_OCLS(etype) == idata ) */
9711 /* p_type = IPOINTER ; */
9713 /* p_type = POINTER ; */
9716 /* now that we have the pointer type we assign
9717 the pointer values */
9723 genNearPointerSet (right,result,ic);
9727 genPagedPointerSet (right,result,ic);
9731 genFarPointerSet (right,result,ic);
9735 genGenPointerSet (right,result,ic);
9739 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9740 "genPointerSet: illegal pointer type");
9744 /*-----------------------------------------------------------------*/
9745 /* genIfx - generate code for Ifx statement */
9746 /*-----------------------------------------------------------------*/
9747 static void genIfx (iCode *ic, iCode *popIc)
9749 operand *cond = IC_COND(ic);
9753 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9755 aopOp(cond,ic,FALSE);
9757 /* get the value into acc */
9758 if (AOP_TYPE(cond) != AOP_CRY)
9759 pic14_toBoolean(cond);
9763 /* if there was something to be popped then do it */
9769 /* This assumes that CARRY is set iff cond is true */
9772 assert (!IC_FALSE(ic));
9773 emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
9775 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9777 assert (IC_FALSE(ic));
9778 emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
9780 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9784 static int hasWarned = 0;
9787 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
9794 /* now Z is set iff !cond */
9797 assert (!IC_FALSE(ic));
9799 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9802 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9808 /* the result is now in the accumulator */
9809 freeAsmop(cond,NULL,ic,TRUE);
9812 /*-----------------------------------------------------------------*/
9813 /* genAddrOf - generates code for address of */
9814 /*-----------------------------------------------------------------*/
9815 static void genAddrOf (iCode *ic)
9817 operand *right, *result, *left;
9821 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9824 //aopOp(IC_RESULT(ic),ic,FALSE);
9826 aopOp((left=IC_LEFT(ic)),ic,FALSE);
9827 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9828 aopOp((result=IC_RESULT(ic)),ic,TRUE);
9830 DEBUGpic14_AopType(__LINE__,left,right,result);
9831 assert (IS_SYMOP (left));
9833 /* sanity check: generic pointers to code space are not yet supported,
9834 * pionters to codespace must not be assigned addresses of __data values. */
9836 fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9837 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)));
9838 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)));
9839 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)));
9840 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)));
9843 if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9844 fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9845 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9846 OP_SYMBOL(left)->name);
9847 } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9848 fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9849 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9850 OP_SYMBOL(left)->name);
9853 size = AOP_SIZE(IC_RESULT(ic));
9854 if (IS_GENPTR(OP_SYM_TYPE(result))) {
9856 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9861 /* fixing bug #863624, reported from (errolv) */
9862 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9863 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9866 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9867 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9872 if (IS_GENPTR(OP_SYM_TYPE(result)))
9874 /* provide correct tag */
9875 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9876 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9877 movwf (AOP(result), 2);
9880 freeAsmop(left,NULL,ic,FALSE);
9881 freeAsmop(result,NULL,ic,TRUE);
9886 /*-----------------------------------------------------------------*/
9887 /* genFarFarAssign - assignment when both are in far space */
9888 /*-----------------------------------------------------------------*/
9889 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9891 int size = AOP_SIZE(right);
9894 /* first push the right side on to the stack */
9896 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9898 pic14_emitcode ("push","acc");
9901 freeAsmop(right,NULL,ic,FALSE);
9902 /* now assign DPTR to result */
9903 aopOp(result,ic,FALSE);
9904 size = AOP_SIZE(result);
9906 pic14_emitcode ("pop","acc");
9907 aopPut(AOP(result),"a",--offset);
9909 freeAsmop(result,NULL,ic,FALSE);
9914 /*-----------------------------------------------------------------*/
9915 /* genAssign - generate code for assignment */
9916 /*-----------------------------------------------------------------*/
9917 static void genAssign (iCode *ic)
9919 operand *result, *right;
9920 int size, offset,know_W;
9921 unsigned long lit = 0L;
9923 result = IC_RESULT(ic);
9924 right = IC_RIGHT(ic) ;
9927 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9929 /* if they are the same */
9930 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9933 aopOp(right,ic,FALSE);
9934 aopOp(result,ic,TRUE);
9936 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9938 /* if they are the same registers */
9939 if (pic14_sameRegs(AOP(right),AOP(result)))
9942 /* special case: assign from __code */
9943 if (!IS_ITEMP(right) /* --> iTemps never reside in __code */
9944 && IS_SYMOP (right) /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
9945 && !IS_FUNC(OP_SYM_TYPE(right)) /* --> we would want its address instead of the first instruction */
9946 && !IS_CODEPTR(OP_SYM_TYPE(right)) /* --> get symbols address instread */
9947 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
9949 emitpComment ("genAssign from CODESPACE");
9950 genConstPointerGet (right, result, ic);
9954 /* just for symmetry reasons... */
9955 if (!IS_ITEMP(result)
9956 && IS_SYMOP (result)
9957 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
9959 assert ( !"cannot write to CODESPACE" );
9962 /* if the result is a bit */
9963 if (AOP_TYPE(result) == AOP_CRY) {
9965 /* if the right size is a literal then
9966 we know what the value is */
9967 if (AOP_TYPE(right) == AOP_LIT) {
9969 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9970 popGet(AOP(result),0));
9972 if (((int) operandLitValue(right)))
9973 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9974 AOP(result)->aopu.aop_dir,
9975 AOP(result)->aopu.aop_dir);
9977 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9978 AOP(result)->aopu.aop_dir,
9979 AOP(result)->aopu.aop_dir);
9983 /* the right is also a bit variable */
9984 if (AOP_TYPE(right) == AOP_CRY) {
9985 emitpcode(POC_BCF, popGet(AOP(result),0));
9986 emitpcode(POC_BTFSC, popGet(AOP(right),0));
9987 emitpcode(POC_BSF, popGet(AOP(result),0));
9989 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9990 AOP(result)->aopu.aop_dir,
9991 AOP(result)->aopu.aop_dir);
9992 pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
9993 AOP(right)->aopu.aop_dir,
9994 AOP(right)->aopu.aop_dir);
9995 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9996 AOP(result)->aopu.aop_dir,
9997 AOP(result)->aopu.aop_dir);
10001 /* we need to or */
10002 emitpcode(POC_BCF, popGet(AOP(result),0));
10003 pic14_toBoolean(right);
10005 emitpcode(POC_BSF, popGet(AOP(result),0));
10006 //aopPut(AOP(result),"a",0);
10010 /* bit variables done */
10012 size = AOP_SIZE(result);
10014 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
10015 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10016 if(aopIdx(AOP(result),0) == 4) {
10017 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10018 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10019 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10022 DEBUGpic14_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
10028 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10029 if(AOP_TYPE(right) == AOP_LIT) {
10030 lit = (unsigned long)pic14aopLiteral(AOP(right)->aopu.aop_lit, offset) & 0x0ff;
10032 if(know_W != (int)(lit&0xff))
10033 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10035 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10037 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10039 } else if (AOP_TYPE(right) == AOP_CRY) {
10040 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10042 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10043 emitpcode(POC_INCF, popGet(AOP(result),0));
10046 mov2w_op (right, offset);
10047 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10055 freeAsmop (right,NULL,ic,FALSE);
10056 freeAsmop (result,NULL,ic,TRUE);
10059 /*-----------------------------------------------------------------*/
10060 /* genJumpTab - genrates code for jump table */
10061 /*-----------------------------------------------------------------*/
10062 static void genJumpTab (iCode *ic)
10068 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10070 aopOp(IC_JTCOND(ic),ic,FALSE);
10071 /* get the condition into accumulator */
10072 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10074 /* multiply by three */
10075 pic14_emitcode("add","a,acc");
10076 pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10078 jtab = newiTempLabel(NULL);
10079 pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10080 pic14_emitcode("jmp","@a+dptr");
10081 pic14_emitcode("","%05d_DS_:",jtab->key+100);
10083 emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10084 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10085 emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10086 emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10088 emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10089 emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10090 emitpLabel(jtab->key);
10092 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10094 /* now generate the jump labels */
10095 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10096 jtab = setNextItem(IC_JTLABELS(ic))) {
10097 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10098 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10104 /*-----------------------------------------------------------------*/
10105 /* genMixedOperation - gen code for operators between mixed types */
10106 /*-----------------------------------------------------------------*/
10108 TSD - Written for the PIC port - but this unfortunately is buggy.
10109 This routine is good in that it is able to efficiently promote
10110 types to different (larger) sizes. Unfortunately, the temporary
10111 variables that are optimized out by this routine are sometimes
10112 used in other places. So until I know how to really parse the
10113 iCode tree, I'm going to not be using this routine :(.
10115 static int genMixedOperation (iCode *ic)
10119 operand *result = IC_RESULT(ic);
10120 sym_link *ctype = operandType(IC_LEFT(ic));
10121 operand *right = IC_RIGHT(ic);
10127 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10129 pic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10135 nextright = IC_RIGHT(nextic);
10136 nextleft = IC_LEFT(nextic);
10137 nextresult = IC_RESULT(nextic);
10139 aopOp(right,ic,FALSE);
10140 aopOp(result,ic,FALSE);
10141 aopOp(nextright, nextic, FALSE);
10142 aopOp(nextleft, nextic, FALSE);
10143 aopOp(nextresult, nextic, FALSE);
10145 if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10147 operand *t = right;
10151 pic14_emitcode(";remove right +","");
10153 } else if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10155 operand *t = right;
10159 pic14_emitcode(";remove left +","");
10163 big = AOP_SIZE(nextleft);
10164 small = AOP_SIZE(nextright);
10166 switch(nextic->op) {
10169 pic14_emitcode(";optimize a +","");
10170 /* if unsigned or not an integral type */
10171 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10172 pic14_emitcode(";add a bit to something","");
10175 pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10177 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10178 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10179 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10181 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10189 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10190 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10191 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10194 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10196 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10197 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10198 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10199 pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10200 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10203 pic14_emitcode("rlf","known_zero,w");
10210 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10211 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10212 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10214 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10224 freeAsmop(right,NULL,ic,TRUE);
10225 freeAsmop(result,NULL,ic,TRUE);
10226 freeAsmop(nextright,NULL,ic,TRUE);
10227 freeAsmop(nextleft,NULL,ic,TRUE);
10229 nextic->generated = 1;
10236 /*-----------------------------------------------------------------*/
10237 /* genCast - gen code for casting */
10238 /*-----------------------------------------------------------------*/
10239 static void genCast (iCode *ic)
10241 operand *result = IC_RESULT(ic);
10242 sym_link *restype = operandType(result);
10243 sym_link *rtype = operandType(IC_RIGHT(ic));
10244 operand *right = IC_RIGHT(ic);
10248 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10249 /* if they are equivalent then do nothing */
10250 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10253 aopOp(right,ic,FALSE) ;
10254 aopOp(result,ic,FALSE);
10256 DEBUGpic14_AopType(__LINE__,NULL,right,result);
10258 /* if the result is a bit */
10259 if (AOP_TYPE(result) == AOP_CRY) {
10260 assert(!"assigning to bit variables is not supported");
10263 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10265 size = AOP_SIZE(result);
10267 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10269 emitpcode(POC_CLRF, popGet(AOP(result),0));
10270 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10271 emitpcode(POC_INCF, popGet(AOP(result),0));
10274 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
10279 if (IS_PTR(restype))
10281 operand *result = IC_RESULT(ic);
10282 //operand *left = IC_LEFT(ic);
10283 operand *right = IC_RIGHT(ic);
10286 /* copy common part */
10287 int max, size = AOP_SIZE(result);
10288 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10289 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10291 /* warn if we discard generic opinter tag */
10292 if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10294 //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10300 mov2w_op (right, size);
10301 movwf (AOP(result), size);
10304 /* upcast into generic pointer type? */
10305 if (IS_GENPTR(restype)
10306 && (size < AOP_SIZE(result))
10307 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10309 //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10312 switch (DCL_TYPE(rtype))
10314 case POINTER: /* __data */
10315 case FPOINTER: /* __data */
10316 assert (AOP_SIZE(right) == 2);
10317 tag = GPTRTAG_DATA;
10320 case CPOINTER: /* __code */
10321 assert (AOP_SIZE(right) == 2);
10322 tag = GPTRTAG_CODE;
10325 case GPOINTER: /* unknown destination, __data or __code */
10326 /* assume __data space (address of immediate) */
10327 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10328 if (AOP(right)->code)
10329 tag = GPTRTAG_CODE;
10331 tag = GPTRTAG_DATA;
10335 assert (!"unhandled pointer type");
10338 /* convert other values into pointers to __data space */
10339 tag = GPTRTAG_DATA;
10342 assert (AOP_SIZE(result) == 3);
10344 emitpcode(POC_CLRF, popGet(AOP(result), 2));
10346 emitpcode(POC_MOVLW, popGetLit(tag));
10347 movwf(AOP(result), 2);
10350 addSign(result, max, 0);
10355 /* if they are the same size : or less */
10356 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10358 /* if they are in the same place */
10359 if (pic14_sameRegs(AOP(right),AOP(result)))
10362 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10363 if (IS_PTR_CONST(rtype))
10364 DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10365 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10366 DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10368 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10369 emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10370 emitpcode(POC_MOVWF, popGet(AOP(result),0));
10371 emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10372 emitpcode(POC_MOVWF, popGet(AOP(result),1));
10373 if(AOP_SIZE(result) <2)
10374 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10378 /* if they in different places then copy */
10379 size = AOP_SIZE(result);
10382 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10383 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10385 //aopPut(AOP(result),
10386 // aopGet(AOP(right),offset,FALSE,FALSE),
10395 /* so we now know that the size of destination is greater
10396 than the size of the source.
10397 Now, if the next iCode is an operator then we might be
10398 able to optimize the operation without performing a cast.
10400 if(0 && genMixedOperation(ic)) {
10401 /* XXX: cannot optimize: must copy regs! */
10405 /* we move to result for the size of source */
10406 size = AOP_SIZE(right);
10409 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10410 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10414 addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10417 freeAsmop(right,NULL,ic,TRUE);
10418 freeAsmop(result,NULL,ic,TRUE);
10422 /*-----------------------------------------------------------------*/
10423 /* genDjnz - generate decrement & jump if not zero instrucion */
10424 /*-----------------------------------------------------------------*/
10425 static int genDjnz (iCode *ic, iCode *ifx)
10427 symbol *lbl, *lbl1;
10429 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10434 /* if the if condition has a false label
10435 then we cannot save */
10439 /* if the minus is not of the form
10441 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10442 !IS_OP_LITERAL(IC_RIGHT(ic)))
10445 if (operandLitValue(IC_RIGHT(ic)) != 1)
10448 /* if the size of this greater than one then no
10450 if (getSize(operandType(IC_RESULT(ic))) > 1)
10453 /* otherwise we can save BIG */
10454 lbl = newiTempLabel(NULL);
10455 lbl1= newiTempLabel(NULL);
10457 aopOp(IC_RESULT(ic),ic,FALSE);
10459 if (IS_AOP_PREG(IC_RESULT(ic))) {
10460 pic14_emitcode("dec","%s",
10461 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10462 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10463 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10467 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10468 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10470 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10471 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10474 /* pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10475 /* pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10476 /* pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10477 /* pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10480 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10481 ifx->generated = 1;
10485 /*-----------------------------------------------------------------*/
10486 /* genReceive - generate code for a receive iCode */
10487 /*-----------------------------------------------------------------*/
10488 static void genReceive (iCode *ic)
10491 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10493 if (isOperandInFarSpace(IC_RESULT(ic)) &&
10494 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10495 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10497 int size = getSize(operandType(IC_RESULT(ic)));
10498 int offset = fReturnSizePic - size;
10500 pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10501 fReturn[fReturnSizePic - offset - 1] : "acc"));
10504 aopOp(IC_RESULT(ic),ic,FALSE);
10505 size = AOP_SIZE(IC_RESULT(ic));
10508 pic14_emitcode ("pop","acc");
10509 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10514 aopOp(IC_RESULT(ic),ic,FALSE);
10516 GpsuedoStkPtr = ic->parmBytes; // address used arg on stack
10517 assignResultValue(IC_RESULT(ic));
10520 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10523 /*-----------------------------------------------------------------*/
10524 /* genDummyRead - generate code for dummy read of volatiles */
10525 /*-----------------------------------------------------------------*/
10527 genDummyRead (iCode * ic)
10530 pic14_emitcode ("; genDummyRead","");
10531 pic14_emitcode ("; not implemented","");
10536 /*-----------------------------------------------------------------*/
10537 /* genpic14Code - generate code for pic14 based controllers */
10538 /*-----------------------------------------------------------------*/
10540 * At this point, ralloc.c has gone through the iCode and attempted
10541 * to optimize in a way suitable for a PIC. Now we've got to generate
10542 * PIC instructions that correspond to the iCode.
10544 * Once the instructions are generated, we'll pass through both the
10545 * peep hole optimizer and the pCode optimizer.
10546 *-----------------------------------------------------------------*/
10548 void genpic14Code (iCode *lic)
10555 lineHead = lineCurr = NULL;
10557 pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10560 /* if debug information required */
10561 if (options.debug && currFunc) {
10563 debugFile->writeFunction (currFunc, lic);
10568 for (ic = lic ; ic ; ic = ic->next ) {
10570 //DEBUGpic14_emitcode(";ic","");
10571 //fprintf (stderr, "in ic loop\n");
10572 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10573 //ic->lineno, printCLine(ic->filename, ic->lineno));
10575 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10577 //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10578 cline = printCLine (ic->filename, ic->lineno);
10579 if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10580 addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10581 //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10584 if (options.iCodeInAsm) {
10585 char *iLine = printILine(ic);
10586 emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10589 /* if the result is marked as
10590 spilt and rematerializable or code for
10591 this has already been generated then
10593 if (resultRemat(ic) || ic->generated )
10596 /* depending on the operation */
10615 /* IPOP happens only when trying to restore a
10616 spilt live range, if there is an ifx statement
10617 following this pop then the if statement might
10618 be using some of the registers being popped which
10619 would destory the contents of the register so
10620 we need to check for this condition and handle it */
10622 ic->next->op == IFX &&
10623 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10624 genIfx (ic->next,ic);
10642 genEndFunction (ic);
10662 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10679 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
10683 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10690 /* note these two are xlated by algebraic equivalence
10691 during parsing SDCC.y */
10692 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10693 "got '>=' or '<=' shouldn't have come here");
10697 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10709 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10713 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10717 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10741 genRightShift (ic);
10744 case GET_VALUE_AT_ADDRESS:
10749 if (POINTER_SET(ic))
10776 addSet(&_G.sendSet,ic);
10779 case DUMMY_READ_VOLATILE:
10784 fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10791 /* now we are ready to call the
10792 peep hole optimizer */
10793 if (!options.nopeep) {
10794 peepHole (&lineHead);
10796 /* now do the actual printing */
10797 printLine (lineHead,codeOutBuf);
10800 DFPRINTF((stderr,"printing pBlock\n\n"));
10801 printpBlock(stdout,pb);
10807 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10808 * (meaning: representing its own address) or not (referencing its contents).
10809 * This can only be decided based on the operand's type. */
10811 aop_isLitLike (asmop *aop)
10814 if (aop->type == AOP_LIT) return 1;
10815 if (aop->type == AOP_IMMD) return 1;
10816 if ((aop->type == AOP_PCODE) &&
10817 ((aop->aopu.pcop->type == PO_LITERAL)))
10819 /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10820 * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10827 op_isLitLike (operand *op)
10830 if (aop_isLitLike (AOP(op))) return 1;
10831 if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10832 if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;