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 && debugFile && currFunc) {
3119 debugFile->writeEndFunction (currFunc, ic, 1);
3122 pic14_emitcode ("reti","");
3123 emitpcode(POC_MOVFW, popCopyReg(&pc_psave));
3124 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
3125 emitpcode(POC_CLRF, popCopyReg(&pc_status));
3126 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3127 emitpcode(POC_MOVWF, popCopyReg(&pc_status));
3128 emitpcode(POC_SWAPF, popCopyReg(&pc_wsave));
3129 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3130 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3131 emitpcodeNULLop(POC_RETFIE);
3134 if (IFFUNC_ISCRITICAL(sym->type))
3135 pic14_emitcode("setb","ea");
3137 if (IFFUNC_CALLEESAVES(sym->type)) {
3140 /* if any registers used */
3141 if (sym->regsUsed) {
3142 /* save the registers used */
3143 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3144 if (bitVectBitValue(sym->regsUsed,i) ||
3145 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3146 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3152 /* if debug then send end of function */
3153 if (options.debug && debugFile && currFunc) {
3154 debugFile->writeEndFunction (currFunc, ic, 1);
3157 pic14_emitcode ("return","");
3158 emitpcodeNULLop(POC_RETURN);
3160 /* Mark the end of a function */
3161 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3166 /*-----------------------------------------------------------------*/
3167 /* genRet - generate code for return statement */
3168 /*-----------------------------------------------------------------*/
3169 static void genRet (iCode *ic)
3171 int size,offset = 0;
3175 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3176 /* if we have no return value then
3177 just generate the "ret" */
3181 /* we have something to return then
3182 move the return value into place */
3183 aopOp(IC_LEFT(ic),ic,FALSE);
3184 size = AOP_SIZE(IC_LEFT(ic));
3186 for (offset = 0; offset < size; offset++)
3188 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
3191 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3194 /* generate a jump to the return label
3195 if the next is not the return statement */
3196 if (!(ic->next && ic->next->op == LABEL &&
3197 IC_LABEL(ic->next) == returnLabel)) {
3199 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3204 /*-----------------------------------------------------------------*/
3205 /* genLabel - generates a label */
3206 /*-----------------------------------------------------------------*/
3207 static void genLabel (iCode *ic)
3211 /* special case never generate */
3212 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3213 if (IC_LABEL(ic) == entryLabel)
3216 emitpLabel(IC_LABEL(ic)->key);
3217 pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3220 /*-----------------------------------------------------------------*/
3221 /* genGoto - generates a goto */
3222 /*-----------------------------------------------------------------*/
3224 static void genGoto (iCode *ic)
3228 emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3229 pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3233 /*-----------------------------------------------------------------*/
3234 /* genMultbits :- multiplication of bits */
3235 /*-----------------------------------------------------------------*/
3236 static void genMultbits (operand *left,
3241 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3243 if(!pic14_sameRegs(AOP(result),AOP(right)))
3244 emitpcode(POC_BSF, popGet(AOP(result),0));
3246 emitpcode(POC_BTFSC,popGet(AOP(right),0));
3247 emitpcode(POC_BTFSS,popGet(AOP(left),0));
3248 emitpcode(POC_BCF, popGet(AOP(result),0));
3253 /*-----------------------------------------------------------------*/
3254 /* genMultOneByte : 8 bit multiplication & division */
3255 /*-----------------------------------------------------------------*/
3256 static void genMultOneByte (operand *left,
3260 char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
3268 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3269 DEBUGpic14_AopType(__LINE__,left,right,result);
3270 DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3272 /* (if two literals, the value is computed before) */
3273 /* if one literal, literal on the right */
3274 if (AOP_TYPE(left) == AOP_LIT){
3280 assert (AOP_SIZE(left) == AOP_SIZE(right));
3282 size = min(AOP_SIZE(result),AOP_SIZE(left));
3283 offset = Gstack_base_addr - (2*size - 1);
3285 /* pass right operand as argument */
3286 for (i=0; i < size; i++)
3288 mov2w (AOP(right), i);
3289 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3292 /* pass left operand as argument */
3293 for (i=0; i < size; i++)
3295 mov2w (AOP(left), i);
3296 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3298 assert (offset == Gstack_base_addr);
3300 /* call library routine */
3301 assert (size > 0 && size <= 4);
3302 call_libraryfunc (func[size]);
3305 movwf (AOP(result), size-1);
3306 for (i=0; i < size - 1; i++)
3308 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
3309 movwf (AOP(result), size - 2 - i);
3312 /* now (zero-/sign) extend the result to its size */
3313 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
3316 /*-----------------------------------------------------------------*/
3317 /* genMult - generates code for multiplication */
3318 /*-----------------------------------------------------------------*/
3319 static void genMult (iCode *ic)
3321 operand *left = IC_LEFT(ic);
3322 operand *right = IC_RIGHT(ic);
3323 operand *result= IC_RESULT(ic);
3327 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3328 /* assign the amsops */
3329 aopOp (left,ic,FALSE);
3330 aopOp (right,ic,FALSE);
3331 aopOp (result,ic,TRUE);
3333 DEBUGpic14_AopType(__LINE__,left,right,result);
3335 /* special cases first */
3337 if (AOP_TYPE(left) == AOP_CRY &&
3338 AOP_TYPE(right)== AOP_CRY) {
3339 genMultbits(left,right,result);
3343 /* if both are of size == 1 */
3344 if (AOP_SIZE(left) == 1 &&
3345 AOP_SIZE(right) == 1 ) {
3346 genMultOneByte(left,right,result);
3350 /* should have been converted to function call */
3354 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3355 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3356 freeAsmop(result,NULL,ic,TRUE);
3359 /*-----------------------------------------------------------------*/
3360 /* genDivbits :- division of bits */
3361 /*-----------------------------------------------------------------*/
3362 static void genDivbits (operand *left,
3371 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3372 /* the result must be bit */
3373 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3374 l = aopGet(AOP(left),0,FALSE,FALSE);
3378 pic14_emitcode("div","ab");
3379 pic14_emitcode("rrc","a");
3380 aopPut(AOP(result),"c",0);
3383 /*-----------------------------------------------------------------*/
3384 /* genDivOneByte : 8 bit division */
3385 /*-----------------------------------------------------------------*/
3386 static void genDivOneByte (operand *left,
3394 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3396 assert (AOP_SIZE(right) == 1);
3397 assert (AOP_SIZE(left) == 1);
3399 size = min(AOP_SIZE(result),AOP_SIZE(left));
3400 sign = !(SPEC_USIGN(operandType(left))
3401 && SPEC_USIGN(operandType(right)));
3403 if (AOP_TYPE(right) == AOP_LIT)
3405 /* XXX: might add specialized code */
3410 /* unsigned division */
3412 mov2w(AOP(right),0);
3413 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3415 call_libraryfunc("__divuchar");
3416 movwf(AOP(result),0);
3421 temp = popGetTempReg();
3422 lbl = newiTempLabel(NULL);
3424 /* XXX: improve this naive approach:
3425 [result] = [a] / [b]
3426 ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
3430 movwf temp // temp <-- left
3431 movf right,W // W <-- right
3435 subwf temp,F // temp <-- temp - W
3436 skipNC // subwf clears CARRY (i.e. sets BORROW) if temp < W
3438 decf result // we just subtract once too often
3441 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3442 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
3445 emitpcode(POC_MOVWF, temp);
3446 mov2w(AOP(right),0);
3447 emitpcode(POC_CLRF, popGet(AOP(result),0));
3449 emitpLabel(lbl->key);
3450 emitpcode(POC_INCF, popGet(AOP(result),0));
3451 emitpcode(POC_SUBWF, temp);
3453 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3454 emitpcode(POC_DECF, popGet(AOP(result),0));
3459 /* signed division */
3460 mov2w(AOP(right),0);
3461 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3463 call_libraryfunc("__divschar");
3464 movwf(AOP(result),0);
3467 /* now performed the signed/unsigned division -- extend result */
3468 addSign(result, 1, sign);
3471 /*-----------------------------------------------------------------*/
3472 /* genDiv - generates code for division */
3473 /*-----------------------------------------------------------------*/
3474 static void genDiv (iCode *ic)
3476 operand *left = IC_LEFT(ic);
3477 operand *right = IC_RIGHT(ic);
3478 operand *result= IC_RESULT(ic);
3481 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3482 /* assign the amsops */
3483 aopOp (left,ic,FALSE);
3484 aopOp (right,ic,FALSE);
3485 aopOp (result,ic,TRUE);
3487 /* special cases first */
3489 if (AOP_TYPE(left) == AOP_CRY &&
3490 AOP_TYPE(right)== AOP_CRY) {
3491 genDivbits(left,right,result);
3495 /* if both are of size == 1 */
3496 if (AOP_SIZE(left) == 1 &&
3497 AOP_SIZE(right) == 1 ) {
3498 genDivOneByte(left,right,result);
3502 /* should have been converted to function call */
3505 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3506 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3507 freeAsmop(result,NULL,ic,TRUE);
3510 /*-----------------------------------------------------------------*/
3511 /* genModOneByte : 8 bit modulus */
3512 /*-----------------------------------------------------------------*/
3513 static void genModOneByte (operand *left,
3521 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3523 assert (AOP_SIZE(right) == 1);
3524 assert (AOP_SIZE(left) == 1);
3526 size = min(AOP_SIZE(result),AOP_SIZE(left));
3527 sign = !(SPEC_USIGN(operandType(left))
3528 && SPEC_USIGN(operandType(right)));
3530 if (AOP_TYPE(right) == AOP_LIT)
3532 /* XXX: might add specialized code */
3537 /* unsigned division */
3539 mov2w(AOP(right),0);
3540 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3542 call_libraryfunc("__moduchar");
3543 movwf(AOP(result),0);
3548 lbl = newiTempLabel(NULL);
3550 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3552 /* XXX: improve this naive approach:
3553 [result] = [a] % [b]
3554 ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3558 movwf result // result <-- left
3559 movf right,W // W <-- right
3561 subwf result,F // result <-- result - W
3562 skipNC // subwf clears CARRY (i.e. sets BORROW) if result < W
3564 addwf result, F // we just subtract once too often
3567 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3568 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3570 if (!pic14_sameRegs(AOP(left), AOP(result)))
3573 emitpcode(POC_MOVWF, popGet(AOP(result),0));
3575 mov2w(AOP(right),0);
3577 emitpLabel(lbl->key);
3578 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3580 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3581 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3586 /* signed division */
3587 mov2w(AOP(right),0);
3588 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3590 call_libraryfunc("__modschar");
3591 movwf(AOP(result),0);
3594 /* now we performed the signed/unsigned modulus -- extend result */
3595 addSign(result, 1, sign);
3598 /*-----------------------------------------------------------------*/
3599 /* genMod - generates code for division */
3600 /*-----------------------------------------------------------------*/
3601 static void genMod (iCode *ic)
3603 operand *left = IC_LEFT(ic);
3604 operand *right = IC_RIGHT(ic);
3605 operand *result= IC_RESULT(ic);
3608 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3609 /* assign the amsops */
3610 aopOp (left,ic,FALSE);
3611 aopOp (right,ic,FALSE);
3612 aopOp (result,ic,TRUE);
3614 /* if both are of size == 1 */
3615 if (AOP_SIZE(left) == 1 &&
3616 AOP_SIZE(right) == 1 ) {
3617 genModOneByte(left,right,result);
3621 /* should have been converted to function call */
3625 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3626 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3627 freeAsmop(result,NULL,ic,TRUE);
3630 /*-----------------------------------------------------------------*/
3631 /* genIfxJump :- will create a jump depending on the ifx */
3632 /*-----------------------------------------------------------------*/
3634 note: May need to add parameter to indicate when a variable is in bit space.
3636 static void genIfxJump (iCode *ic, char *jval)
3640 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3641 /* if true label then we jump if condition
3643 if ( IC_TRUE(ic) ) {
3645 if(strcmp(jval,"a") == 0)
3647 else if (strcmp(jval,"c") == 0)
3650 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3651 emitpcode(POC_BTFSC, newpCodeOpBit(jval,-1,1));
3654 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3655 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3659 /* false label is present */
3660 if(strcmp(jval,"a") == 0)
3662 else if (strcmp(jval,"c") == 0)
3665 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3666 emitpcode(POC_BTFSS, newpCodeOpBit(jval,-1,1));
3669 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3670 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3675 /* mark the icode as generated */
3680 /*-----------------------------------------------------------------*/
3682 /*-----------------------------------------------------------------*/
3683 static void genSkip(iCode *ifx,int status_bit)
3689 if ( IC_TRUE(ifx) ) {
3690 switch(status_bit) {
3705 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3706 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3710 switch(status_bit) {
3724 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3725 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3732 /*-----------------------------------------------------------------*/
3734 /*-----------------------------------------------------------------*/
3735 static void genSkipc(resolvedIfx *rifx)
3746 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3747 emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3748 rifx->generated = 1;
3752 /*-----------------------------------------------------------------*/
3754 /*-----------------------------------------------------------------*/
3755 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3761 if( (rifx->condition ^ invert_condition) & 1)
3766 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3767 rifx->generated = 1;
3772 /*-----------------------------------------------------------------*/
3774 /*-----------------------------------------------------------------*/
3775 static void genSkipz(iCode *ifx, int condition)
3778 assert (ifx != NULL);
3786 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3788 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3791 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3793 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3799 /*-----------------------------------------------------------------*/
3801 /*-----------------------------------------------------------------*/
3802 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3809 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3811 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3814 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3815 rifx->generated = 1;
3820 /*-----------------------------------------------------------------*/
3821 /* genChkZeroes :- greater or less than comparison */
3822 /* For each byte in a literal that is zero, inclusive or the */
3823 /* the corresponding byte in the operand with W */
3824 /* returns true if any of the bytes are zero */
3825 /*-----------------------------------------------------------------*/
3826 static int genChkZeroes(operand *op, int lit, int size)
3833 i = (lit >> (size*8)) & 0xff;
3837 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3839 emitpcode(POC_IORFW, popGet(AOP(op),size));
3849 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3850 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
3851 #define DEBUGpc emitpComment
3853 /*-----------------------------------------------------------------*/
3854 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
3855 /* aop (if it's NOT a literal) or from lit (if */
3856 /* aop is a literal) */
3857 /*-----------------------------------------------------------------*/
3858 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3859 if (aop->type == AOP_LIT) {
3860 emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3862 emitpcode (POC_MOVFW, popGet (aop, offset));
3866 /* genCmp performs a left < right comparison, stores
3867 * the outcome in result (if != NULL) and generates
3868 * control flow code for the ifx (if != NULL).
3870 * This version leaves in sequences like
3871 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3872 * which should be optmized by the peephole
3873 * optimizer - RN 2005-01-01 */
3874 static void genCmp (operand *left,operand *right,
3875 operand *result, iCode *ifx, int sign)
3885 int invert_result = 0;
3889 assert (AOP_SIZE(left) == AOP_SIZE(right));
3890 assert (left && right);
3892 size = AOP_SIZE(right) - 1;
3893 mask = (0x100UL << (size*8)) - 1;
3894 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3899 resolveIfx (&rIfx, ifx);
3901 /**********************************************************************
3902 * handle bits - bit compares are promoted to int compares seemingly! *
3903 **********************************************************************/
3905 // THIS IS COMPLETELY UNTESTED!
3906 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3907 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3908 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3909 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3912 // 1 < {0,1} is false --> clear C by skipping the next instruction
3913 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3914 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3915 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3916 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3917 emitCLRC; // only skipped for left=0 && right=1
3919 goto correct_result_in_carry;
3923 /*************************************************
3924 * make sure that left is register (or the like) *
3925 *************************************************/
3926 if (!isAOP_REGlike(left)) {
3927 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
3928 assert (isAOP_LIT(left));
3929 assert (isAOP_REGlike(right));
3930 // swap left and right
3931 // left < right <==> right > left <==> (right >= left + 1)
3932 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3934 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
3935 // MAXVALUE < right? always false
3936 if (performedLt) emitCLRC; else emitSETC;
3937 goto correct_result_in_carry;
3940 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
3941 // that's why we handled it above.
3948 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
3949 } else if (isAOP_LIT(right)) {
3950 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3953 assert (isAOP_REGlike(left)); // left must be register or the like
3954 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
3956 /*************************************************
3957 * special cases go here *
3958 *************************************************/
3960 if (isAOP_LIT(right)) {
3962 // unsigned comparison to a literal
3963 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
3965 // unsigned left < 0? always false
3966 if (performedLt) emitCLRC; else emitSETC;
3967 goto correct_result_in_carry;
3970 // signed comparison to a literal
3971 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
3972 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
3973 // signed left < 0x80000000? always false
3974 if (performedLt) emitCLRC; else emitSETC;
3975 goto correct_result_in_carry;
3976 } else if (lit == 0) {
3977 // compare left < 0; set CARRY if SIGNBIT(left) is set
3978 if (performedLt) emitSETC; else emitCLRC;
3979 emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
3980 if (performedLt) emitCLRC; else emitSETC;
3981 goto correct_result_in_carry;
3984 } // right is literal
3986 /*************************************************
3987 * perform a general case comparison *
3988 * make sure we get CARRY==1 <==> left >= right *
3989 *************************************************/
3990 // compare most significant bytes
3991 //DEBUGpc ("comparing bytes at offset %d", size);
3993 // unsigned comparison
3994 pic14_mov2w_regOrLit (AOP(right), lit, size);
3995 emitpcode (POC_SUBFW, popGet (AOP(left), size));
3997 // signed comparison
3998 // (add 2^n to both operands then perform an unsigned comparison)
3999 if (isAOP_LIT(right)) {
4000 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4001 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4003 if (litbyte == 0x80) {
4004 // left >= 0x80 -- always true, but more bytes to come
4005 mov2w (AOP(left), size);
4006 emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
4009 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4010 mov2w (AOP(left), size);
4011 emitpcode (POC_ADDLW, popGetLit (0x80));
4012 emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4015 pCodeOp *pctemp = popGetTempReg();
4016 mov2w (AOP(left), size);
4017 emitpcode (POC_ADDLW, popGetLit (0x80));
4018 emitpcode (POC_MOVWF, pctemp);
4019 mov2w (AOP(right), size);
4020 emitpcode (POC_ADDLW, popGetLit (0x80));
4021 emitpcode (POC_SUBFW, pctemp);
4022 popReleaseTempReg(pctemp);
4026 // compare remaining bytes (treat as unsigned case from above)
4027 templbl = newiTempLabel ( NULL );
4030 //DEBUGpc ("comparing bytes at offset %d", offs);
4032 emitpcode (POC_GOTO, popGetLabel (templbl->key));
4033 pic14_mov2w_regOrLit (AOP(right), lit, offs);
4034 emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4036 emitpLabel (templbl->key);
4037 goto result_in_carry;
4041 /****************************************************
4042 * now CARRY contains the result of the comparison: *
4043 * SUBWF sets CARRY iff *
4044 * F-W >= 0 <==> F >= W <==> !(F < W) *
4045 * (F=left, W=right) *
4046 ****************************************************/
4050 // value will be used in the following genSkipc()
4051 rIfx.condition ^= 1;
4054 correct_result_in_carry:
4056 // assign result to variable (if neccessary)
4057 if (result && AOP_TYPE(result) != AOP_CRY) {
4058 //DEBUGpc ("assign result");
4059 size = AOP_SIZE(result);
4061 emitpcode (POC_CLRF, popGet (AOP(result), size));
4063 if (invert_result) {
4065 emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4067 emitpcode (POC_RLF, popGet (AOP(result), 0));
4071 // perform conditional jump
4073 //DEBUGpc ("generate control flow");
4081 /* OLD VERSION -- BUGGY, DO NOT USE */
4083 /*-----------------------------------------------------------------*/
4084 /* genCmp :- greater or less than comparison */
4085 /*-----------------------------------------------------------------*/
4086 static void genCmp (operand *left,operand *right,
4087 operand *result, iCode *ifx, int sign)
4089 int size; //, offset = 0 ;
4090 unsigned long lit = 0L,i = 0;
4091 resolvedIfx rFalseIfx;
4092 // resolvedIfx rTrueIfx;
4096 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4099 DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4100 DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4104 resolveIfx(&rFalseIfx,ifx);
4105 truelbl = newiTempLabel(NULL);
4106 size = max(AOP_SIZE(left),AOP_SIZE(right));
4108 DEBUGpic14_AopType(__LINE__,left,right,result);
4112 /* if literal is on the right then swap with left */
4113 if ((AOP_TYPE(right) == AOP_LIT)) {
4114 operand *tmp = right ;
4115 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4116 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4119 lit = (lit - 1) & mask;
4122 rFalseIfx.condition ^= 1;
4125 } else if ((AOP_TYPE(left) == AOP_LIT)) {
4126 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4130 //if(IC_TRUE(ifx) == NULL)
4131 /* if left & right are bit variables */
4132 if (AOP_TYPE(left) == AOP_CRY &&
4133 AOP_TYPE(right) == AOP_CRY ) {
4134 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4135 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4137 /* subtract right from left if at the
4138 end the carry flag is set then we know that
4139 left is greater than right */
4141 symbol *lbl = newiTempLabel(NULL);
4144 if(AOP_TYPE(right) == AOP_LIT) {
4146 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4148 DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4155 genSkipCond(&rFalseIfx,left,size-1,7);
4157 /* no need to compare to 0...*/
4158 /* NOTE: this is a de-generate compare that most certainly
4159 * creates some dead code. */
4160 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4162 if(ifx) ifx->generated = 1;
4169 //i = (lit >> (size*8)) & 0xff;
4170 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4172 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4174 i = ((0-lit) & 0xff);
4177 /* lit is 0x7f, all signed chars are less than
4178 * this except for 0x7f itself */
4179 emitpcode(POC_XORLW, popGetLit(0x7f));
4180 genSkipz2(&rFalseIfx,0);
4182 emitpcode(POC_ADDLW, popGetLit(0x80));
4183 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4184 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4189 genSkipz2(&rFalseIfx,1);
4191 emitpcode(POC_ADDLW, popGetLit(i));
4192 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4196 if(ifx) ifx->generated = 1;
4200 /* chars are out of the way. now do ints and longs */
4203 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4210 genSkipCond(&rFalseIfx,left,size,7);
4211 if(ifx) ifx->generated = 1;
4216 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4218 //rFalseIfx.condition ^= 1;
4219 //genSkipCond(&rFalseIfx,left,size,7);
4220 //rFalseIfx.condition ^= 1;
4222 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4223 if(rFalseIfx.condition)
4224 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4226 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4228 emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4229 emitpcode(POC_ADDFW, popGet(AOP(left),0));
4230 emitpcode(POC_MOVFW, popGet(AOP(left),1));
4233 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4235 if(rFalseIfx.condition) {
4237 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4243 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4244 emitpLabel(truelbl->key);
4245 if(ifx) ifx->generated = 1;
4252 if( (lit & 0xff) == 0) {
4253 /* lower byte is zero */
4254 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4255 i = ((lit >> 8) & 0xff) ^0x80;
4256 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4257 emitpcode(POC_ADDLW, popGetLit( 0x80));
4258 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4259 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4262 if(ifx) ifx->generated = 1;
4267 /* Special cases for signed longs */
4268 if( (lit & 0xffffff) == 0) {
4269 /* lower byte is zero */
4270 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4271 i = ((lit >> 8*3) & 0xff) ^0x80;
4272 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4273 emitpcode(POC_ADDLW, popGetLit( 0x80));
4274 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4275 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4278 if(ifx) ifx->generated = 1;
4286 if(lit & (0x80 << (size*8))) {
4287 /* lit is negative */
4288 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4290 //genSkipCond(&rFalseIfx,left,size,7);
4292 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4294 if(rFalseIfx.condition)
4295 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4297 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4301 /* lit is positive */
4302 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4303 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4304 if(rFalseIfx.condition)
4305 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4307 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4311 /* There are no more special cases, so perform a general compare */
4313 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4314 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4318 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4320 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4322 //rFalseIfx.condition ^= 1;
4323 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4325 emitpLabel(truelbl->key);
4327 if(ifx) ifx->generated = 1;
4334 /* sign is out of the way. So now do an unsigned compare */
4335 DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4338 /* General case - compare to an unsigned literal on the right.*/
4340 i = (lit >> (size*8)) & 0xff;
4341 emitpcode(POC_MOVLW, popGetLit(i));
4342 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4344 i = (lit >> (size*8)) & 0xff;
4347 emitpcode(POC_MOVLW, popGetLit(i));
4349 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4351 /* this byte of the lit is zero,
4352 *if it's not the last then OR in the variable */
4354 emitpcode(POC_IORFW, popGet(AOP(left),size));
4359 emitpLabel(lbl->key);
4360 //if(emitFinalCheck)
4361 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4363 emitpLabel(truelbl->key);
4365 if(ifx) ifx->generated = 1;
4372 if(AOP_TYPE(left) == AOP_LIT) {
4373 //symbol *lbl = newiTempLabel(NULL);
4375 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4378 DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4381 if((lit == 0) && (sign == 0)){
4384 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4386 emitpcode(POC_IORFW, popGet(AOP(right),--size));
4388 genSkipz2(&rFalseIfx,0);
4389 if(ifx) ifx->generated = 1;
4396 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4397 /* degenerate compare can never be true */
4398 if(rFalseIfx.condition == 0)
4399 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4401 if(ifx) ifx->generated = 1;
4406 /* signed comparisons to a literal byte */
4408 int lp1 = (lit+1) & 0xff;
4410 DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4413 rFalseIfx.condition ^= 1;
4414 genSkipCond(&rFalseIfx,right,0,7);
4417 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4418 emitpcode(POC_XORLW, popGetLit(0x7f));
4419 genSkipz2(&rFalseIfx,1);
4422 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4423 emitpcode(POC_ADDLW, popGetLit(0x80));
4424 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4425 rFalseIfx.condition ^= 1;
4426 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4429 if(ifx) ifx->generated = 1;
4431 /* unsigned comparisons to a literal byte */
4433 switch(lit & 0xff ) {
4435 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4436 genSkipz2(&rFalseIfx,0);
4437 if(ifx) ifx->generated = 1;
4440 genSkipCond(&rFalseIfx,right,0,7);
4441 if(ifx) ifx->generated = 1;
4445 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4446 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4447 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4448 rFalseIfx.condition ^= 1;
4449 if (AOP_TYPE(result) == AOP_CRY) {
4450 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4451 if(ifx) ifx->generated = 1;
4453 DEBUGpic14_emitcode ("; ***","%s %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4454 emitpcode(POC_CLRF, popGet(AOP(result),0));
4455 emitpcode(POC_RLF, popGet(AOP(result),0));
4456 emitpcode(POC_MOVLW, popGetLit(0x01));
4457 emitpcode(POC_XORWF, popGet(AOP(result),0));
4468 /* Size is greater than 1 */
4476 /* this means lit = 0xffffffff, or -1 */
4479 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4480 rFalseIfx.condition ^= 1;
4481 genSkipCond(&rFalseIfx,right,size,7);
4482 if(ifx) ifx->generated = 1;
4489 if(rFalseIfx.condition) {
4490 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4491 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4494 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4496 emitpcode(POC_IORFW, popGet(AOP(right),size));
4500 if(rFalseIfx.condition) {
4501 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4502 emitpLabel(truelbl->key);
4504 rFalseIfx.condition ^= 1;
4505 genSkipCond(&rFalseIfx,right,s,7);
4508 if(ifx) ifx->generated = 1;
4512 if((size == 1) && (0 == (lp1&0xff))) {
4513 /* lower byte of signed word is zero */
4514 DEBUGpic14_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
4515 i = ((lp1 >> 8) & 0xff) ^0x80;
4516 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4517 emitpcode(POC_ADDLW, popGetLit( 0x80));
4518 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4519 rFalseIfx.condition ^= 1;
4520 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4523 if(ifx) ifx->generated = 1;
4527 if(lit & (0x80 << (size*8))) {
4528 /* Lit is less than zero */
4529 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
4530 //rFalseIfx.condition ^= 1;
4531 //genSkipCond(&rFalseIfx,left,size,7);
4532 //rFalseIfx.condition ^= 1;
4533 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4534 //emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4536 if(rFalseIfx.condition)
4537 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4539 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4543 /* Lit is greater than or equal to zero */
4544 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
4545 //rFalseIfx.condition ^= 1;
4546 //genSkipCond(&rFalseIfx,right,size,7);
4547 //rFalseIfx.condition ^= 1;
4549 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4550 //emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4552 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4553 if(rFalseIfx.condition)
4554 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4556 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4561 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4562 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4566 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4568 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4570 rFalseIfx.condition ^= 1;
4571 //rFalseIfx.condition = 1;
4572 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4574 emitpLabel(truelbl->key);
4576 if(ifx) ifx->generated = 1;
4581 /* compare word or long to an unsigned literal on the right.*/
4586 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4589 break; /* handled above */
4592 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4594 emitpcode(POC_IORFW, popGet(AOP(right),size));
4595 genSkipz2(&rFalseIfx,0);
4599 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4601 emitpcode(POC_IORFW, popGet(AOP(right),size));
4604 if(rFalseIfx.condition)
4605 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4607 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4610 emitpcode(POC_MOVLW, popGetLit(lit+1));
4611 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4613 rFalseIfx.condition ^= 1;
4614 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4617 emitpLabel(truelbl->key);
4619 if(ifx) ifx->generated = 1;
4625 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4626 i = (lit >> (size*8)) & 0xff;
4628 emitpcode(POC_MOVLW, popGetLit(i));
4629 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4632 i = (lit >> (size*8)) & 0xff;
4635 emitpcode(POC_MOVLW, popGetLit(i));
4637 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4639 /* this byte of the lit is zero,
4640 *if it's not the last then OR in the variable */
4642 emitpcode(POC_IORFW, popGet(AOP(right),size));
4647 emitpLabel(lbl->key);
4649 rFalseIfx.condition ^= 1;
4650 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4654 emitpLabel(truelbl->key);
4655 if(ifx) ifx->generated = 1;
4659 /* Compare two variables */
4661 DEBUGpic14_emitcode(";sign","%d",sign);
4665 /* Sigh. thus sucks... */
4667 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4668 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4669 emitpcode(POC_MOVLW, popGetLit(0x80));
4670 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4671 emitpcode(POC_XORFW, popGet(AOP(right),size));
4672 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4674 /* Signed char comparison */
4675 /* Special thanks to Nikolai Golovchenko for this snippet */
4676 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4677 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4678 emitpcode(POC_RRFW, popGet(AOP(left),0)); /* could be any register */
4679 emitpcode(POC_XORFW, popGet(AOP(left),0));
4680 emitpcode(POC_XORFW, popGet(AOP(right),0));
4681 emitpcode(POC_ADDLW, popGetLit(0x80));
4683 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4684 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4686 if(ifx) ifx->generated = 1;
4692 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4693 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4697 /* The rest of the bytes of a multi-byte compare */
4701 emitpcode(POC_GOTO, popGetLabel(lbl->key));
4704 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4705 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4710 emitpLabel(lbl->key);
4712 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4713 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
4714 (AOP_TYPE(result) == AOP_REG)) {
4715 emitpcode(POC_CLRF, popGet(AOP(result),0));
4716 emitpcode(POC_RLF, popGet(AOP(result),0));
4718 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4720 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4721 if(ifx) ifx->generated = 1;
4728 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4729 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4730 pic14_outBitC(result);
4732 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4733 /* if the result is used in the next
4734 ifx conditional branch then generate
4735 code a little differently */
4737 genIfxJump (ifx,"c");
4739 pic14_outBitC(result);
4740 /* leave the result in acc */
4746 /*-----------------------------------------------------------------*/
4747 /* genCmpGt :- greater than comparison */
4748 /*-----------------------------------------------------------------*/
4749 static void genCmpGt (iCode *ic, iCode *ifx)
4751 operand *left, *right, *result;
4752 sym_link *letype , *retype;
4756 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4758 right= IC_RIGHT(ic);
4759 result = IC_RESULT(ic);
4761 letype = getSpec(operandType(left));
4762 retype =getSpec(operandType(right));
4763 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4764 /* assign the amsops */
4765 aopOp (left,ic,FALSE);
4766 aopOp (right,ic,FALSE);
4767 aopOp (result,ic,TRUE);
4769 genCmp(right, left, result, ifx, sign);
4771 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4772 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4773 freeAsmop(result,NULL,ic,TRUE);
4776 /*-----------------------------------------------------------------*/
4777 /* genCmpLt - less than comparisons */
4778 /*-----------------------------------------------------------------*/
4779 static void genCmpLt (iCode *ic, iCode *ifx)
4781 operand *left, *right, *result;
4782 sym_link *letype , *retype;
4786 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4788 right= IC_RIGHT(ic);
4789 result = IC_RESULT(ic);
4791 letype = getSpec(operandType(left));
4792 retype =getSpec(operandType(right));
4793 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4795 /* assign the amsops */
4796 aopOp (left,ic,FALSE);
4797 aopOp (right,ic,FALSE);
4798 aopOp (result,ic,TRUE);
4800 genCmp(left, right, result, ifx, sign);
4802 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4803 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4804 freeAsmop(result,NULL,ic,TRUE);
4808 /*-----------------------------------------------------------------*/
4809 /* genc16bit2lit - compare a 16 bit value to a literal */
4810 /*-----------------------------------------------------------------*/
4811 static void genc16bit2lit(operand *op, int lit, int offset)
4816 DEBUGpic14_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
4817 if( (lit&0xff) == 0)
4822 switch( BYTEofLONG(lit,i)) {
4824 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4827 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4830 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4833 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4834 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4839 switch( BYTEofLONG(lit,i)) {
4841 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4845 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4849 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4852 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4854 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4862 /*-----------------------------------------------------------------*/
4863 /* gencjneshort - compare and jump if not equal */
4864 /*-----------------------------------------------------------------*/
4865 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4867 int size = min(AOP_SIZE(left),AOP_SIZE(right));
4872 //unsigned long lit = 0L;
4874 if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4875 emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4878 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4879 DEBUGpic14_AopType(__LINE__,left,right,result);
4881 assert (!pic14_sameRegs (AOP(left), AOP(result)));
4882 assert (!pic14_sameRegs (AOP(right), AOP(result)));
4883 if (AOP_SIZE(result)) {
4884 for (offset = 0; offset < AOP_SIZE(result); offset++)
4885 emitpcode (POC_CLRF, popGet (AOP(result), offset));
4888 assert (AOP_SIZE(left) == AOP_SIZE(right));
4889 //resolveIfx(&rIfx,ifx);
4890 lbl = newiTempLabel (NULL);
4893 mov2w (AOP(right),size);
4894 emitpcode (POC_XORFW, popGet (AOP(left), size));
4898 emitpcode (POC_GOTO, popGetLabel (lbl->key));
4901 emitpLabel (lbl->key);
4902 if (AOP_SIZE(result)) {
4904 emitpcode (POC_INCF, popGet (AOP(result), 0));
4907 genSkipz (ifx, NULL != IC_TRUE(ifx));
4914 DEBUGpic14_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
4915 assert (!pic14_sameRegs (AOP(result), AOP(left)));
4916 assert (!pic14_sameRegs (AOP(result), AOP(right)));
4917 for (offset=0; offset < AOP_SIZE(result); offset++)
4919 emitpcode (POC_CLRF, popGet (AOP(result), offset));
4924 /* if the left side is a literal or
4925 if the right is in a pointer register and left
4927 if ((AOP_TYPE(left) == AOP_LIT) ||
4928 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4933 if(AOP_TYPE(right) == AOP_LIT)
4934 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4936 /* if the right side is a literal then anything goes */
4937 if (AOP_TYPE(right) == AOP_LIT &&
4938 AOP_TYPE(left) != AOP_DIR ) {
4941 genc16bit2lit(left, lit, 0);
4943 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4949 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4950 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4952 emitpcode(POC_MOVF,popGet(AOP(left),offset));
4956 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4964 /* if the right side is in a register or in direct space or
4965 if the left is a pointer register & right is not */
4966 else if (AOP_TYPE(right) == AOP_REG ||
4967 AOP_TYPE(right) == AOP_DIR ||
4968 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4969 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4970 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4971 int lbl_key = lbl->key;
4974 DEBUGpic14_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
4975 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
4976 __FUNCTION__,__LINE__);
4980 /* switch(size) { */
4982 /* genc16bit2lit(left, lit, 0); */
4984 /* emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
4990 if((AOP_TYPE(left) == AOP_DIR) &&
4991 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4993 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4994 emitpcode(POC_XORFW,popGet(AOP(right),offset));
4996 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4998 switch (lit & 0xff) {
5000 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5003 emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
5004 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5005 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5009 emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5010 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5011 //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5012 emitpcode(POC_GOTO,popGetLabel(lbl_key));
5016 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5017 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5022 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5025 if(AOP_TYPE(result) == AOP_CRY) {
5026 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5031 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5033 /* fix me. probably need to check result size too */
5034 //emitpcode(POC_CLRF,popGet(AOP(result),0));
5039 emitpcode(POC_GOTO,popGetLabel(lbl_key));
5049 } else if(AOP_TYPE(right) == AOP_REG &&
5050 AOP_TYPE(left) != AOP_DIR){
5054 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5055 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5056 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5061 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5066 /* right is a pointer reg need both a & b */
5069 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5071 pic14_emitcode("mov","b,%s",l);
5072 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5073 pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
5078 emitpcode(POC_INCF,popGet(AOP(result),0));
5080 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5082 emitpLabel(lbl->key);
5084 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5093 /*-----------------------------------------------------------------*/
5094 /* gencjne - compare and jump if not equal */
5095 /*-----------------------------------------------------------------*/
5096 static void gencjne(operand *left, operand *right, iCode *ifx)
5098 symbol *tlbl = newiTempLabel(NULL);
5100 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5101 gencjneshort(left, right, lbl);
5103 pic14_emitcode("mov","a,%s",one);
5104 pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5105 pic14_emitcode("","%05d_DS_:",lbl->key+100);
5106 pic14_emitcode("clr","a");
5107 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5109 emitpLabel(lbl->key);
5110 emitpLabel(tlbl->key);
5115 /*-----------------------------------------------------------------*/
5116 /* genCmpEq - generates code for equal to */
5117 /*-----------------------------------------------------------------*/
5118 static void genCmpEq (iCode *ic, iCode *ifx)
5120 operand *left, *right, *result;
5122 symbol *false_label;
5125 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5128 DEBUGpic14_emitcode ("; ifx is non-null","");
5130 DEBUGpic14_emitcode ("; ifx is null","");
5132 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5133 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5134 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5136 DEBUGpic14_AopType(__LINE__,left,right,result);
5138 /* if literal, move literal to right */
5139 if (op_isLitLike (IC_LEFT(ic))) {
5140 operand *tmp = right ;
5146 if (ifx && !IC_TRUE(ifx))
5148 assert (IC_FALSE(ifx));
5149 false_label = IC_FALSE(ifx);
5152 size = min(AOP_SIZE(left),AOP_SIZE(right));
5153 assert(!pic14_sameRegs(AOP(result),AOP(left)));
5154 assert(!pic14_sameRegs(AOP(result),AOP(right)));
5156 /* assume left != right */
5159 for (i=0; i < AOP_SIZE(result); i++)
5161 emitpcode(POC_CLRF, popGet(AOP(result),i));
5165 if (AOP_TYPE(right) == AOP_LIT)
5167 unsigned long lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
5169 size = AOP_SIZE(left);
5170 assert(!op_isLitLike(left));
5175 mov2w(AOP(left), 0);
5176 for (i=1; i < size; i++)
5177 emitpcode(POC_IORFW,popGet(AOP(left),i));
5178 /* now Z is set iff `left == right' */
5180 if (!false_label) false_label = newiTempLabel(NULL);
5181 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5185 for (i=0; i < size; i++)
5188 emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
5189 /* now Z is cleared if `left != right' */
5191 if (!false_label) false_label = newiTempLabel(NULL);
5192 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5199 /* right is no literal */
5202 for (i=0; i < size; i++)
5204 mov2w(AOP(right),i);
5205 emitpcode(POC_XORFW,popGet(AOP(left),i));
5206 /* now Z is cleared if `left != right' */
5208 if (!false_label) false_label = newiTempLabel(NULL);
5209 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5213 /* if we reach here, left == right */
5215 if (AOP_SIZE(result) > 0)
5217 emitpcode(POC_INCF, popGet(AOP(result),0));
5220 if (ifx && IC_TRUE(ifx))
5222 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5225 if (false_label && (!ifx || IC_TRUE(ifx)))
5226 emitpLabel(false_label->key);
5228 if (ifx) ifx->generated = 1;
5230 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5231 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5232 freeAsmop(result,NULL,ic,TRUE);
5235 /*-----------------------------------------------------------------*/
5236 /* ifxForOp - returns the icode containing the ifx for operand */
5237 /*-----------------------------------------------------------------*/
5238 static iCode *ifxForOp ( operand *op, iCode *ic )
5241 /* if true symbol then needs to be assigned */
5242 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5243 if (IS_TRUE_SYMOP(op))
5246 /* if this has register type condition and
5247 the next instruction is ifx with the same operand
5248 and live to of the operand is upto the ifx only then */
5250 ic->next->op == IFX &&
5251 IC_COND(ic->next)->key == op->key &&
5252 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5256 ic->next->op == IFX &&
5257 IC_COND(ic->next)->key == op->key) {
5258 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5262 DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5264 ic->next->op == IFX)
5265 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5268 ic->next->op == IFX &&
5269 IC_COND(ic->next)->key == op->key) {
5270 DEBUGpic14_emitcode ("; "," key is okay");
5271 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5272 OP_SYMBOL(op)->liveTo,
5279 /*-----------------------------------------------------------------*/
5280 /* genAndOp - for && operation */
5281 /*-----------------------------------------------------------------*/
5282 static void genAndOp (iCode *ic)
5284 operand *left,*right, *result;
5288 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5289 /* note here that && operations that are in an
5290 if statement are taken away by backPatchLabels
5291 only those used in arthmetic operations remain */
5292 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5293 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5294 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5296 DEBUGpic14_AopType(__LINE__,left,right,result);
5298 emitpcode(POC_MOVFW,popGet(AOP(left),0));
5299 emitpcode(POC_ANDFW,popGet(AOP(right),0));
5300 emitpcode(POC_MOVWF,popGet(AOP(result),0));
5302 /* if both are bit variables */
5303 /* if (AOP_TYPE(left) == AOP_CRY && */
5304 /* AOP_TYPE(right) == AOP_CRY ) { */
5305 /* pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5306 /* pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5307 /* pic14_outBitC(result); */
5309 /* tlbl = newiTempLabel(NULL); */
5310 /* pic14_toBoolean(left); */
5311 /* pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5312 /* pic14_toBoolean(right); */
5313 /* pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5314 /* pic14_outBitAcc(result); */
5317 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5318 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5319 freeAsmop(result,NULL,ic,TRUE);
5323 /*-----------------------------------------------------------------*/
5324 /* genOrOp - for || operation */
5325 /*-----------------------------------------------------------------*/
5328 modified this code, but it doesn't appear to ever get called
5331 static void genOrOp (iCode *ic)
5333 operand *left,*right, *result;
5337 /* note here that || operations that are in an
5338 if statement are taken away by backPatchLabels
5339 only those used in arthmetic operations remain */
5341 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5342 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5343 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5344 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5346 DEBUGpic14_AopType(__LINE__,left,right,result);
5348 for (i=0; i < AOP_SIZE(result); i++)
5350 emitpcode(POC_CLRF, popGet(AOP(result), i));
5353 tlbl = newiTempLabel(NULL);
5354 pic14_toBoolean(left);
5356 emitpcode(POC_GOTO, popGetLabel(tlbl->key));
5357 pic14_toBoolean(right);
5358 emitpLabel(tlbl->key);
5359 /* here Z is clear IFF `left || right' */
5361 emitpcode(POC_INCF, popGet(AOP(result), 0));
5363 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5364 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5365 freeAsmop(result,NULL,ic,TRUE);
5368 /*-----------------------------------------------------------------*/
5369 /* isLiteralBit - test if lit == 2^n */
5370 /*-----------------------------------------------------------------*/
5371 static int isLiteralBit(unsigned long lit)
5373 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5374 0x100L,0x200L,0x400L,0x800L,
5375 0x1000L,0x2000L,0x4000L,0x8000L,
5376 0x10000L,0x20000L,0x40000L,0x80000L,
5377 0x100000L,0x200000L,0x400000L,0x800000L,
5378 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5379 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5383 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5384 for(idx = 0; idx < 32; idx++)
5390 /*-----------------------------------------------------------------*/
5391 /* continueIfTrue - */
5392 /*-----------------------------------------------------------------*/
5393 static void continueIfTrue (iCode *ic)
5396 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5400 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
5401 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5406 /*-----------------------------------------------------------------*/
5408 /*-----------------------------------------------------------------*/
5409 static void jumpIfTrue (iCode *ic)
5412 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5416 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
5417 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5422 /*-----------------------------------------------------------------*/
5423 /* jmpTrueOrFalse - */
5424 /*-----------------------------------------------------------------*/
5425 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5428 // ugly but optimized by peephole
5429 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5431 symbol *nlbl = newiTempLabel(NULL);
5432 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5433 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5434 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5435 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5438 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5439 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5444 /*-----------------------------------------------------------------*/
5445 /* genAnd - code for and */
5446 /*-----------------------------------------------------------------*/
5447 static void genAnd (iCode *ic, iCode *ifx)
5449 operand *left, *right, *result;
5451 unsigned long lit = 0L;
5456 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5457 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5458 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5459 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5461 resolveIfx(&rIfx,ifx);
5463 /* if left is a literal & right is not then exchange them */
5464 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5465 AOP_NEEDSACC(left)) {
5466 operand *tmp = right ;
5471 /* if result = right then exchange them */
5472 if(pic14_sameRegs(AOP(result),AOP(right))){
5473 operand *tmp = right ;
5478 /* if right is bit then exchange them */
5479 if (AOP_TYPE(right) == AOP_CRY &&
5480 AOP_TYPE(left) != AOP_CRY){
5481 operand *tmp = right ;
5485 if(AOP_TYPE(right) == AOP_LIT)
5486 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5488 size = AOP_SIZE(result);
5490 DEBUGpic14_AopType(__LINE__,left,right,result);
5493 // result = bit & yy;
5494 if (AOP_TYPE(left) == AOP_CRY){
5495 // c = bit & literal;
5496 if(AOP_TYPE(right) == AOP_LIT){
5498 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5501 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5504 if(size && (AOP_TYPE(result) == AOP_CRY)){
5505 pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5508 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5512 pic14_emitcode("clr","c");
5515 if (AOP_TYPE(right) == AOP_CRY){
5517 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5518 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5521 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5523 pic14_emitcode("rrc","a");
5524 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5530 pic14_outBitC(result);
5532 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5533 genIfxJump(ifx, "c");
5537 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5538 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5539 if((AOP_TYPE(right) == AOP_LIT) &&
5540 (AOP_TYPE(result) == AOP_CRY) &&
5541 (AOP_TYPE(left) != AOP_CRY)){
5542 int posbit = isLiteralBit(lit);
5546 //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5549 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5554 while (posbit > 7) {
5558 emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5559 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5560 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5567 symbol *tlbl = newiTempLabel(NULL);
5568 int sizel = AOP_SIZE(left);
5570 pic14_emitcode("setb","c");
5572 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5573 mov2w( AOP(left), offset);
5575 if((posbit = isLiteralBit(bytelit)) != 0) {
5576 emitpcode(rIfx.condition ? POC_BTFSC : POC_BTFSS, // XXX: or the other way round?
5577 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit - 1, 0));
5578 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5581 emitpcode(POC_ANDLW, newpCodeOpLit(bytelit & 0x0ff));
5582 if (rIfx.condition) emitSKPZ;
5585 if(bytelit != 0x0FFL)
5587 pic14_emitcode("anl","a,%s",
5588 aopGet(AOP(right),offset,FALSE,TRUE));
5590 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5593 emitpcode(POC_GOTO, popGetLabel(rIfx.lbl->key));
5599 // bit = left & literal
5601 pic14_emitcode("clr","c");
5602 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5604 // if(left & literal)
5607 jmpTrueOrFalse(ifx, tlbl);
5611 pic14_outBitC(result);
5615 /* if left is same as result */
5616 if(pic14_sameRegs(AOP(result),AOP(left))){
5618 for(;size--; offset++,lit>>=8) {
5619 if(AOP_TYPE(right) == AOP_LIT){
5620 switch(lit & 0xff) {
5622 /* and'ing with 0 has clears the result */
5623 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5626 /* and'ing with 0xff is a nop when the result and left are the same */
5631 int p = my_powof2( (~lit) & 0xff );
5633 /* only one bit is set in the literal, so use a bcf instruction */
5634 emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5637 if(know_W != (int)(lit&0xff))
5638 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5640 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5645 if (AOP_TYPE(left) == AOP_ACC) {
5646 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5648 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5649 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5656 // left & result in different registers
5657 if(AOP_TYPE(result) == AOP_CRY){
5659 // if(size), result in bit
5660 // if(!size && ifx), conditional oper: if(left & right)
5661 symbol *tlbl = newiTempLabel(NULL);
5662 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5664 pic14_emitcode("setb","c");
5666 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5667 pic14_emitcode("anl","a,%s",
5668 aopGet(AOP(left),offset,FALSE,FALSE));
5669 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5674 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5675 pic14_outBitC(result);
5677 jmpTrueOrFalse(ifx, tlbl);
5679 for(;(size--);offset++) {
5681 // result = left & right
5682 if(AOP_TYPE(right) == AOP_LIT){
5683 int t = (lit >> (offset*8)) & 0x0FFL;
5686 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5689 if(AOP_TYPE(left) != AOP_ACC) {
5690 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5692 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5695 if(AOP_TYPE(left) == AOP_ACC) {
5696 emitpcode(POC_ANDLW, popGetLit(t));
5698 emitpcode(POC_MOVLW, popGetLit(t));
5699 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5701 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5706 if (AOP_TYPE(left) == AOP_ACC) {
5707 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5709 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5710 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5712 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5718 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5719 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5720 freeAsmop(result,NULL,ic,TRUE);
5723 /*-----------------------------------------------------------------*/
5724 /* genOr - code for or */
5725 /*-----------------------------------------------------------------*/
5726 static void genOr (iCode *ic, iCode *ifx)
5728 operand *left, *right, *result;
5730 unsigned long lit = 0L;
5733 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5735 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5736 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5737 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5739 DEBUGpic14_AopType(__LINE__,left,right,result);
5741 /* if left is a literal & right is not then exchange them */
5742 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5743 AOP_NEEDSACC(left)) {
5744 operand *tmp = right ;
5749 /* if result = right then exchange them */
5750 if(pic14_sameRegs(AOP(result),AOP(right))){
5751 operand *tmp = right ;
5756 /* if right is bit then exchange them */
5757 if (AOP_TYPE(right) == AOP_CRY &&
5758 AOP_TYPE(left) != AOP_CRY){
5759 operand *tmp = right ;
5764 DEBUGpic14_AopType(__LINE__,left,right,result);
5766 if(AOP_TYPE(right) == AOP_LIT)
5767 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5769 size = AOP_SIZE(result);
5773 if (AOP_TYPE(left) == AOP_CRY){
5774 if(AOP_TYPE(right) == AOP_LIT){
5775 // c = bit & literal;
5777 // lit != 0 => result = 1
5778 if(AOP_TYPE(result) == AOP_CRY){
5780 emitpcode(POC_BSF, popGet(AOP(result),0));
5781 //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5782 // AOP(result)->aopu.aop_dir,
5783 // AOP(result)->aopu.aop_dir);
5785 continueIfTrue(ifx);
5789 // lit == 0 => result = left
5790 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5792 pic14_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5795 if (AOP_TYPE(right) == AOP_CRY){
5796 if(pic14_sameRegs(AOP(result),AOP(left))){
5798 emitpcode(POC_BCF, popGet(AOP(result),0));
5799 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5800 emitpcode(POC_BSF, popGet(AOP(result),0));
5802 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5803 AOP(result)->aopu.aop_dir,
5804 AOP(result)->aopu.aop_dir);
5805 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5806 AOP(right)->aopu.aop_dir,
5807 AOP(right)->aopu.aop_dir);
5808 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5809 AOP(result)->aopu.aop_dir,
5810 AOP(result)->aopu.aop_dir);
5812 if( AOP_TYPE(result) == AOP_ACC) {
5813 emitpcode(POC_MOVLW, popGetLit(0));
5814 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5815 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5816 emitpcode(POC_MOVLW, popGetLit(1));
5820 emitpcode(POC_BCF, popGet(AOP(result),0));
5821 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5822 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5823 emitpcode(POC_BSF, popGet(AOP(result),0));
5825 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5826 AOP(result)->aopu.aop_dir,
5827 AOP(result)->aopu.aop_dir);
5828 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5829 AOP(right)->aopu.aop_dir,
5830 AOP(right)->aopu.aop_dir);
5831 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5832 AOP(left)->aopu.aop_dir,
5833 AOP(left)->aopu.aop_dir);
5834 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5835 AOP(result)->aopu.aop_dir,
5836 AOP(result)->aopu.aop_dir);
5841 symbol *tlbl = newiTempLabel(NULL);
5842 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5845 emitpcode(POC_BCF, popGet(AOP(result),0));
5846 if( AOP_TYPE(right) == AOP_ACC) {
5847 emitpcode(POC_IORLW, popGetLit(0));
5849 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5850 emitpcode(POC_BSF, popGet(AOP(result),0));
5855 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5856 pic14_emitcode(";XXX setb","c");
5857 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5858 AOP(left)->aopu.aop_dir,tlbl->key+100);
5859 pic14_toBoolean(right);
5860 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5861 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5862 jmpTrueOrFalse(ifx, tlbl);
5866 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5873 pic14_outBitC(result);
5875 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5876 genIfxJump(ifx, "c");
5880 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5881 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5882 if((AOP_TYPE(right) == AOP_LIT) &&
5883 (AOP_TYPE(result) == AOP_CRY) &&
5884 (AOP_TYPE(left) != AOP_CRY)){
5886 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5889 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5891 continueIfTrue(ifx);
5894 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5895 // lit = 0, result = boolean(left)
5897 pic14_emitcode(";XXX setb","c");
5898 pic14_toBoolean(right);
5900 symbol *tlbl = newiTempLabel(NULL);
5901 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5903 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5905 genIfxJump (ifx,"a");
5909 pic14_outBitC(result);
5913 /* if left is same as result */
5914 if(pic14_sameRegs(AOP(result),AOP(left))){
5916 for(;size--; offset++,lit>>=8) {
5917 if(AOP_TYPE(right) == AOP_LIT){
5918 if((lit & 0xff) == 0)
5919 /* or'ing with 0 has no effect */
5922 int p = my_powof2(lit & 0xff);
5924 /* only one bit is set in the literal, so use a bsf instruction */
5926 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5928 if(know_W != (int)(lit & 0xff))
5929 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5930 know_W = lit & 0xff;
5931 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5936 if (AOP_TYPE(left) == AOP_ACC) {
5937 emitpcode(POC_IORFW, popGet(AOP(right),offset));
5938 pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5940 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
5941 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5943 pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5944 pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5950 // left & result in different registers
5951 if(AOP_TYPE(result) == AOP_CRY){
5953 // if(size), result in bit
5954 // if(!size && ifx), conditional oper: if(left | right)
5955 symbol *tlbl = newiTempLabel(NULL);
5956 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5957 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5961 pic14_emitcode(";XXX setb","c");
5963 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5964 pic14_emitcode(";XXX orl","a,%s",
5965 aopGet(AOP(left),offset,FALSE,FALSE));
5966 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5971 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5972 pic14_outBitC(result);
5974 jmpTrueOrFalse(ifx, tlbl);
5975 } else for(;(size--);offset++){
5977 // result = left | right
5978 if(AOP_TYPE(right) == AOP_LIT){
5979 int t = (lit >> (offset*8)) & 0x0FFL;
5982 if (AOP_TYPE(left) != AOP_ACC) {
5983 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
5985 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5989 if (AOP_TYPE(left) == AOP_ACC) {
5990 emitpcode(POC_IORLW, popGetLit(t));
5992 emitpcode(POC_MOVLW, popGetLit(t));
5993 emitpcode(POC_IORFW, popGet(AOP(left),offset));
5995 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6000 // faster than result <- left, anl result,right
6001 // and better if result is SFR
6002 if (AOP_TYPE(left) == AOP_ACC) {
6003 emitpcode(POC_IORFW,popGet(AOP(right),offset));
6005 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6006 emitpcode(POC_IORFW,popGet(AOP(left),offset));
6008 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6013 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6014 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6015 freeAsmop(result,NULL,ic,TRUE);
6018 /*-----------------------------------------------------------------*/
6019 /* genXor - code for xclusive or */
6020 /*-----------------------------------------------------------------*/
6021 static void genXor (iCode *ic, iCode *ifx)
6023 operand *left, *right, *result;
6025 unsigned long lit = 0L;
6028 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6030 aopOp((left = IC_LEFT(ic)),ic,FALSE);
6031 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6032 aopOp((result=IC_RESULT(ic)),ic,TRUE);
6034 /* if left is a literal & right is not ||
6035 if left needs acc & right does not */
6036 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6037 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6038 operand *tmp = right ;
6043 /* if result = right then exchange them */
6044 if(pic14_sameRegs(AOP(result),AOP(right))){
6045 operand *tmp = right ;
6050 /* if right is bit then exchange them */
6051 if (AOP_TYPE(right) == AOP_CRY &&
6052 AOP_TYPE(left) != AOP_CRY){
6053 operand *tmp = right ;
6057 if(AOP_TYPE(right) == AOP_LIT)
6058 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6060 size = AOP_SIZE(result);
6064 if (AOP_TYPE(left) == AOP_CRY){
6065 if(AOP_TYPE(right) == AOP_LIT){
6066 // c = bit & literal;
6068 // lit>>1 != 0 => result = 1
6069 if(AOP_TYPE(result) == AOP_CRY){
6071 {emitpcode(POC_BSF, popGet(AOP(result),offset));
6072 pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6074 continueIfTrue(ifx);
6077 pic14_emitcode("setb","c");
6081 // lit == 0, result = left
6082 if(size && pic14_sameRegs(AOP(result),AOP(left)))
6084 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6086 // lit == 1, result = not(left)
6087 if(size && pic14_sameRegs(AOP(result),AOP(left))){
6088 emitpcode(POC_MOVLW, popGet(AOP(result),offset));
6089 emitpcode(POC_XORWF, popGet(AOP(result),offset));
6090 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6093 assert ( !"incomplete genXor" );
6094 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6095 pic14_emitcode("cpl","c");
6102 symbol *tlbl = newiTempLabel(NULL);
6103 if (AOP_TYPE(right) == AOP_CRY){
6105 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6108 int sizer = AOP_SIZE(right);
6110 // if val>>1 != 0, result = 1
6111 pic14_emitcode("setb","c");
6113 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6115 // test the msb of the lsb
6116 pic14_emitcode("anl","a,#0xfe");
6117 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6121 pic14_emitcode("rrc","a");
6123 pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6124 pic14_emitcode("cpl","c");
6125 pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6130 pic14_outBitC(result);
6132 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6133 genIfxJump(ifx, "c");
6137 if(pic14_sameRegs(AOP(result),AOP(left))){
6138 /* if left is same as result */
6139 for(;size--; offset++) {
6140 if(AOP_TYPE(right) == AOP_LIT){
6141 int t = (lit >> (offset*8)) & 0x0FFL;
6145 if (IS_AOP_PREG(left)) {
6146 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6147 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6148 aopPut(AOP(result),"a",offset);
6150 emitpcode(POC_MOVLW, popGetLit(t));
6151 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6152 pic14_emitcode("xrl","%s,%s",
6153 aopGet(AOP(left),offset,FALSE,TRUE),
6154 aopGet(AOP(right),offset,FALSE,FALSE));
6157 if (AOP_TYPE(left) == AOP_ACC)
6158 pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6160 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6161 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6163 if (IS_AOP_PREG(left)) {
6164 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6165 aopPut(AOP(result),"a",offset);
6167 pic14_emitcode("xrl","%s,a",
6168 aopGet(AOP(left),offset,FALSE,TRUE));
6174 // left & result in different registers
6175 if(AOP_TYPE(result) == AOP_CRY){
6177 // if(size), result in bit
6178 // if(!size && ifx), conditional oper: if(left ^ right)
6179 symbol *tlbl = newiTempLabel(NULL);
6180 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6182 pic14_emitcode("setb","c");
6184 if((AOP_TYPE(right) == AOP_LIT) &&
6185 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6186 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6188 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6189 pic14_emitcode("xrl","a,%s",
6190 aopGet(AOP(left),offset,FALSE,FALSE));
6192 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6197 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6198 pic14_outBitC(result);
6200 jmpTrueOrFalse(ifx, tlbl);
6201 } else for(;(size--);offset++){
6203 // result = left & right
6204 if(AOP_TYPE(right) == AOP_LIT){
6205 int t = (lit >> (offset*8)) & 0x0FFL;
6208 if (AOP_TYPE(left) != AOP_ACC) {
6209 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6211 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6212 pic14_emitcode("movf","%s,w",
6213 aopGet(AOP(left),offset,FALSE,FALSE));
6214 pic14_emitcode("movwf","%s",
6215 aopGet(AOP(result),offset,FALSE,FALSE));
6218 if (AOP_TYPE(left) == AOP_ACC) {
6219 emitpcode(POC_XORLW, popGetLit(t));
6221 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6223 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6226 if (AOP_TYPE(left) == AOP_ACC) {
6227 emitpcode(POC_XORLW, popGetLit(t));
6229 emitpcode(POC_MOVLW, popGetLit(t));
6230 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6232 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6233 pic14_emitcode("movlw","0x%x",t);
6234 pic14_emitcode("xorwf","%s,w",
6235 aopGet(AOP(left),offset,FALSE,FALSE));
6236 pic14_emitcode("movwf","%s",
6237 aopGet(AOP(result),offset,FALSE,FALSE));
6243 // faster than result <- left, anl result,right
6244 // and better if result is SFR
6245 if (AOP_TYPE(left) == AOP_ACC) {
6246 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6248 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6249 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6251 if ( AOP_TYPE(result) != AOP_ACC){
6252 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6258 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6259 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6260 freeAsmop(result,NULL,ic,TRUE);
6263 /*-----------------------------------------------------------------*/
6264 /* genInline - write the inline code out */
6265 /*-----------------------------------------------------------------*/
6266 static void genInline (iCode *ic)
6268 char *buffer, *bp, *bp1;
6271 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6273 _G.inLine += (!options.asmpeep);
6275 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6276 strcpy(buffer,IC_INLINE(ic));
6278 /* emit each line as a code */
6284 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6292 /* print label, use this special format with NULL directive
6293 * to denote that the argument should not be indented with tab */
6294 addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6301 if ((bp1 != bp) && *bp1)
6302 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6306 _G.inLine -= (!options.asmpeep);
6309 /*-----------------------------------------------------------------*/
6310 /* genRRC - rotate right with carry */
6311 /*-----------------------------------------------------------------*/
6312 static void genRRC (iCode *ic)
6314 operand *left , *result ;
6315 int size, offset = 0, same;
6318 /* rotate right with carry */
6320 result=IC_RESULT(ic);
6321 aopOp (left,ic,FALSE);
6322 aopOp (result,ic,FALSE);
6324 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6326 same = pic14_sameRegs(AOP(result),AOP(left));
6328 size = AOP_SIZE(result);
6330 /* get the lsb and put it into the carry */
6331 emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6338 emitpcode(POC_RRF, popGet(AOP(left),offset));
6340 emitpcode(POC_RRFW, popGet(AOP(left),offset));
6341 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6347 freeAsmop(left,NULL,ic,TRUE);
6348 freeAsmop(result,NULL,ic,TRUE);
6351 /*-----------------------------------------------------------------*/
6352 /* genRLC - generate code for rotate left with carry */
6353 /*-----------------------------------------------------------------*/
6354 static void genRLC (iCode *ic)
6356 operand *left , *result ;
6357 int size, offset = 0;
6361 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6362 /* rotate right with carry */
6364 result=IC_RESULT(ic);
6365 aopOp (left,ic,FALSE);
6366 aopOp (result,ic,FALSE);
6368 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6370 same = pic14_sameRegs(AOP(result),AOP(left));
6372 /* move it to the result */
6373 size = AOP_SIZE(result);
6375 /* get the msb and put it into the carry */
6376 emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6383 emitpcode(POC_RLF, popGet(AOP(left),offset));
6385 emitpcode(POC_RLFW, popGet(AOP(left),offset));
6386 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6393 freeAsmop(left,NULL,ic,TRUE);
6394 freeAsmop(result,NULL,ic,TRUE);
6397 /*-----------------------------------------------------------------*/
6398 /* genGetHbit - generates code get highest order bit */
6399 /*-----------------------------------------------------------------*/
6400 static void genGetHbit (iCode *ic)
6402 operand *left, *result;
6404 result=IC_RESULT(ic);
6405 aopOp (left,ic,FALSE);
6406 aopOp (result,ic,FALSE);
6409 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6410 /* get the highest order byte into a */
6411 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6412 if(AOP_TYPE(result) == AOP_CRY){
6413 pic14_emitcode("rlc","a");
6414 pic14_outBitC(result);
6417 pic14_emitcode("rl","a");
6418 pic14_emitcode("anl","a,#0x01");
6419 pic14_outAcc(result);
6423 freeAsmop(left,NULL,ic,TRUE);
6424 freeAsmop(result,NULL,ic,TRUE);
6427 /*-----------------------------------------------------------------*/
6428 /* AccLsh - shift left accumulator by known count */
6429 /* MARK: pic14 always rotates through CARRY! */
6430 /*-----------------------------------------------------------------*/
6431 static void AccLsh (pCodeOp *pcop,int shCount)
6434 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6435 shCount &= 0x0007; // shCount : 0..7
6442 emitpcode(POC_RLF,pcop);
6446 emitpcode(POC_RLF,pcop);
6447 emitpcode(POC_RLF,pcop);
6450 emitpcode(POC_RLF,pcop);
6451 emitpcode(POC_RLF,pcop);
6452 emitpcode(POC_RLF,pcop);
6455 emitpcode(POC_SWAPF,pcop);
6458 emitpcode(POC_SWAPF,pcop);
6459 emitpcode(POC_RLF,pcop);
6462 emitpcode(POC_SWAPF,pcop);
6463 emitpcode(POC_RLF,pcop);
6464 emitpcode(POC_RLF,pcop);
6467 emitpcode(POC_RRFW,pcop);
6468 emitpcode(POC_RRF,pcop);
6471 /* clear invalid bits */
6472 emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6473 emitpcode(POC_ANDWF, pcop);
6476 /*-----------------------------------------------------------------*/
6477 /* AccRsh - shift right accumulator by known count */
6478 /* MARK: pic14 always rotates through CARRY! */
6479 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6480 /* 1: mask out invalid bits (zero-extend) */
6481 /* 2: sign-extend result (pretty slow) */
6482 /*-----------------------------------------------------------------*/
6483 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6486 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6487 shCount &= 0x0007; // shCount : 0..7
6493 /* load sign if needed */
6494 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6495 else if (mask_mode == 1) emitCLRC;
6496 emitpcode(POC_RRF,pcop);
6500 /* load sign if needed */
6501 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6502 emitpcode(POC_RRF,pcop);
6503 /* load sign if needed */
6504 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6505 emitpcode(POC_RRF,pcop);
6506 if (mask_mode == 2) return;
6509 /* load sign if needed */
6510 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6511 emitpcode(POC_RRF,pcop);
6512 /* load sign if needed */
6513 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6514 emitpcode(POC_RRF,pcop);
6515 /* load sign if needed */
6516 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6517 emitpcode(POC_RRF,pcop);
6518 if (mask_mode == 2) return;
6521 emitpcode(POC_SWAPF,pcop);
6524 emitpcode(POC_SWAPF,pcop);
6525 emitpcode(POC_RRF,pcop);
6528 emitpcode(POC_SWAPF,pcop);
6529 emitpcode(POC_RRF,pcop);
6530 emitpcode(POC_RRF,pcop);
6536 emitpcode(POC_RLFW,pcop);
6537 emitpcode(POC_CLRF,pcop);
6539 emitpcode(POC_COMF,pcop);
6542 emitpcode(POC_RLFW,pcop);
6543 emitpcode(POC_RLF,pcop);
6550 /* leave invalid bits undefined */
6554 /* clear invalid bits -- zero-extend */
6555 emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6556 emitpcode(POC_ANDWF, pcop);
6558 if (mask_mode == 2) {
6560 emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6561 emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6562 emitpcode(POC_IORWF, pcop);
6567 /*-----------------------------------------------------------------*/
6568 /* AccSRsh - signed right shift accumulator by known count */
6569 /*-----------------------------------------------------------------*/
6570 static void AccSRsh (int shCount)
6573 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6576 pic14_emitcode("mov","c,acc.7");
6577 pic14_emitcode("rrc","a");
6578 } else if(shCount == 2){
6579 pic14_emitcode("mov","c,acc.7");
6580 pic14_emitcode("rrc","a");
6581 pic14_emitcode("mov","c,acc.7");
6582 pic14_emitcode("rrc","a");
6584 tlbl = newiTempLabel(NULL);
6585 /* rotate right accumulator */
6586 AccRol(8 - shCount);
6587 /* and kill the higher order bits */
6588 pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6589 pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6590 pic14_emitcode("orl","a,#0x%02x",
6591 (unsigned char)~SRMask[shCount]);
6592 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6597 /*-----------------------------------------------------------------*/
6598 /* shiftR1Left2Result - shift right one byte from left to result */
6599 /*-----------------------------------------------------------------*/
6600 static void shiftR1Left2ResultSigned (operand *left, int offl,
6601 operand *result, int offr,
6607 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6609 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6613 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6615 emitpcode(POC_RRF, popGet(AOP(result),offr));
6617 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6618 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6624 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6626 emitpcode(POC_RRF, popGet(AOP(result),offr));
6628 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6629 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6631 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6632 emitpcode(POC_RRF, popGet(AOP(result),offr));
6638 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6640 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6641 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6644 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6645 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6646 emitpcode(POC_ANDLW, popGetLit(0x1f));
6648 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6649 emitpcode(POC_IORLW, popGetLit(0xe0));
6651 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6655 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6656 emitpcode(POC_ANDLW, popGetLit(0x0f));
6657 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6658 emitpcode(POC_IORLW, popGetLit(0xf0));
6659 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6663 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6665 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6666 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6668 emitpcode(POC_RRFW, popGet(AOP(result),offr));
6669 emitpcode(POC_ANDLW, popGetLit(0x07));
6670 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6671 emitpcode(POC_IORLW, popGetLit(0xf8));
6672 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6677 emitpcode(POC_MOVLW, popGetLit(0x00));
6678 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6679 emitpcode(POC_MOVLW, popGetLit(0xfe));
6680 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6681 emitpcode(POC_IORLW, popGetLit(0x01));
6682 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6684 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6685 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6686 emitpcode(POC_DECF, popGet(AOP(result),offr));
6687 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6688 emitpcode(POC_BCF, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6694 emitpcode(POC_MOVLW, popGetLit(0x00));
6695 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6696 emitpcode(POC_MOVLW, popGetLit(0xff));
6697 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6699 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6700 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6701 emitpcode(POC_DECF, popGet(AOP(result),offr));
6709 /*-----------------------------------------------------------------*/
6710 /* shiftR1Left2Result - shift right one byte from left to result */
6711 /*-----------------------------------------------------------------*/
6712 static void shiftR1Left2Result (operand *left, int offl,
6713 operand *result, int offr,
6714 int shCount, int sign)
6719 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6721 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6723 /* Copy the msb into the carry if signed. */
6725 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6735 emitpcode(POC_RRF, popGet(AOP(result),offr));
6737 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6738 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6744 emitpcode(POC_RRF, popGet(AOP(result),offr));
6746 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6747 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6750 emitpcode(POC_RRF, popGet(AOP(result),offr));
6755 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6757 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6758 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6761 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6762 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6763 emitpcode(POC_ANDLW, popGetLit(0x1f));
6764 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6768 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6769 emitpcode(POC_ANDLW, popGetLit(0x0f));
6770 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6774 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6775 emitpcode(POC_ANDLW, popGetLit(0x0f));
6776 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6778 emitpcode(POC_RRF, popGet(AOP(result),offr));
6783 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6784 emitpcode(POC_ANDLW, popGetLit(0x80));
6785 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6786 emitpcode(POC_RLF, popGet(AOP(result),offr));
6787 emitpcode(POC_RLF, popGet(AOP(result),offr));
6792 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6793 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6794 emitpcode(POC_RLF, popGet(AOP(result),offr));
6803 /*-----------------------------------------------------------------*/
6804 /* shiftL1Left2Result - shift left one byte from left to result */
6805 /*-----------------------------------------------------------------*/
6806 static void shiftL1Left2Result (operand *left, int offl,
6807 operand *result, int offr, int shCount)
6813 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6815 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6816 DEBUGpic14_emitcode ("; ***","same = %d",same);
6817 // l = aopGet(AOP(left),offl,FALSE,FALSE);
6819 /* shift left accumulator */
6820 //AccLsh(shCount); // don't comment out just yet...
6821 // aopPut(AOP(result),"a",offr);
6825 /* Shift left 1 bit position */
6826 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6828 emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6830 emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6831 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6835 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6836 emitpcode(POC_ANDLW,popGetLit(0x7e));
6837 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6838 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6841 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6842 emitpcode(POC_ANDLW,popGetLit(0x3e));
6843 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6844 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6845 emitpcode(POC_RLF, popGet(AOP(result),offr));
6848 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6849 emitpcode(POC_ANDLW, popGetLit(0xf0));
6850 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6853 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6854 emitpcode(POC_ANDLW, popGetLit(0xf0));
6855 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6856 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6859 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6860 emitpcode(POC_ANDLW, popGetLit(0x30));
6861 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6862 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6863 emitpcode(POC_RLF, popGet(AOP(result),offr));
6866 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6867 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6868 emitpcode(POC_RRF, popGet(AOP(result),offr));
6872 DEBUGpic14_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6878 /*-----------------------------------------------------------------*/
6879 /* movLeft2Result - move byte from left to result */
6880 /*-----------------------------------------------------------------*/
6881 static void movLeft2Result (operand *left, int offl,
6882 operand *result, int offr)
6886 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6887 if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6888 l = aopGet(AOP(left),offl,FALSE,FALSE);
6890 if (*l == '@' && (IS_AOP_PREG(result))) {
6891 pic14_emitcode("mov","a,%s",l);
6892 aopPut(AOP(result),"a",offr);
6894 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6895 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6900 /*-----------------------------------------------------------------*/
6901 /* shiftLeft_Left2ResultLit - shift left by known count */
6902 /*-----------------------------------------------------------------*/
6904 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6906 int size, same, offr, i;
6908 size = AOP_SIZE(left);
6909 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6911 same = pic14_sameRegs (AOP(left), AOP(result));
6914 shCount = shCount & 0x07;
6920 case 0: /* takes 0 or 2N cycles (for offr==0) */
6921 if (!same || offr) {
6922 for (i=size-1; i >= 0; i--)
6923 movLeft2Result (left, i, result, offr + i);
6927 case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6929 shiftLeft_Left2ResultLit (left, result, 8 * offr);
6930 shiftLeft_Left2ResultLit (result, result, shCount);
6931 return; /* prevent clearing result again */
6934 for (i=0; i < size; i++) {
6935 if (same && !offr) {
6936 emitpcode (POC_RLF, popGet (AOP(left), i));
6938 emitpcode (POC_RLFW, popGet (AOP(left), i));
6939 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6945 case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
6946 /* works in-place/with offr as well */
6947 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
6948 emitpcode (POC_ANDLW, popGetLit (0xF0));
6949 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
6951 for (i = size - 2; i >= 0; i--)
6953 emitpcode (POC_SWAPFW, popGet (AOP(left), i));
6954 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6955 emitpcode (POC_ANDLW, popGetLit (0x0F));
6956 emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
6957 emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
6961 case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
6962 /* works in-place/with offr as well */
6963 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
6964 for (i = size-2; i >= 0; i--) {
6965 emitpcode (POC_RRFW, popGet (AOP(left), i));
6966 emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
6968 emitpcode (POC_CLRF, popGet (AOP(result), offr));
6969 emitpcode (POC_RRF, popGet (AOP(result), offr));
6973 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
6974 shiftLeft_Left2ResultLit (result, result, 1);
6975 return; /* prevent clearing result again */
6981 emitpcode (POC_CLRF, popGet (AOP(result), offr));
6985 /*-----------------------------------------------------------------*/
6986 /* shiftRight_Left2ResultLit - shift right by known count */
6987 /*-----------------------------------------------------------------*/
6989 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
6991 int size, same, offr, i;
6993 size = AOP_SIZE(left);
6994 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6996 same = pic14_sameRegs (AOP(left), AOP(result));
6999 shCount = shCount & 0x07;
7007 case 0: /* takes 0 or 2N cycles (for offr==0) */
7008 if (!same || offr) {
7009 for (i=0; i < size; i++)
7010 movLeft2Result (left, i + offr, result, i);
7014 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7015 emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7017 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7018 shiftRight_Left2ResultLit (result, result, shCount, sign);
7019 return; /* prevent sign-extending result again */
7023 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7026 for (i = size-1; i >= 0; i--) {
7027 if (same && !offr) {
7028 emitpcode (POC_RRF, popGet (AOP(left), i));
7030 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7031 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7037 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7038 /* works in-place/with offr as well */
7039 emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7040 emitpcode (POC_ANDLW, popGetLit (0x0F));
7041 emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7043 for (i = 1; i < size; i++)
7045 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7046 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7047 emitpcode (POC_ANDLW, popGetLit (0xF0));
7048 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7049 emitpcode (POC_XORWF, popGet (AOP(result), i));
7054 emitpcode (POC_MOVLW, popGetLit (0xF0));
7055 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7056 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7060 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7061 /* works in-place/with offr as well */
7062 emitpcode (POC_RLFW, popGet (AOP(left), offr));
7063 for (i = 0; i < size-1; i++) {
7064 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7065 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7067 emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7069 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7072 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7077 shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7078 shiftRight_Left2ResultLit (result, result, 1, sign);
7079 return; /* prevent sign extending result again */
7084 addSign (result, size, sign);
7088 /*-----------------------------------------------------------------*/
7089 /* shiftL2Left2Result - shift left two bytes from left to result */
7090 /*-----------------------------------------------------------------*/
7091 static void shiftL2Left2Result (operand *left, int offl,
7092 operand *result, int offr, int shCount)
7096 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7098 if(pic14_sameRegs(AOP(result), AOP(left))) {
7106 emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7107 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7108 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7112 emitpcode(POC_RLF, popGet(AOP(result),offr));
7113 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7119 emitpcode(POC_MOVLW, popGetLit(0x0f));
7120 emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7121 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7122 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7123 emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7124 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7125 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7127 emitpcode(POC_RLF, popGet(AOP(result),offr));
7128 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7132 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7133 emitpcode(POC_RRF, popGet(AOP(result),offr));
7134 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7135 emitpcode(POC_RRF, popGet(AOP(result),offr));
7136 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7137 emitpcode(POC_ANDLW,popGetLit(0xc0));
7138 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7139 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7140 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7141 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7144 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7145 emitpcode(POC_RRFW, popGet(AOP(result),offr));
7146 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7147 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7148 emitpcode(POC_RRF, popGet(AOP(result),offr));
7158 /* note, use a mov/add for the shift since the mov has a
7159 chance of getting optimized out */
7160 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7161 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7162 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7163 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7164 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7168 emitpcode(POC_RLF, popGet(AOP(result),offr));
7169 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7175 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7176 emitpcode(POC_ANDLW, popGetLit(0xF0));
7177 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7178 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7179 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7180 emitpcode(POC_ANDLW, popGetLit(0xF0));
7181 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7182 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7186 emitpcode(POC_RLF, popGet(AOP(result),offr));
7187 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7191 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7192 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7193 emitpcode(POC_RRFW, popGet(AOP(result),offl));
7194 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7196 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7197 emitpcode(POC_RRF, popGet(AOP(result),offr));
7198 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7199 emitpcode(POC_ANDLW,popGetLit(0xc0));
7200 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7201 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7202 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7203 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7206 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7207 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7208 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7209 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7210 emitpcode(POC_RRF, popGet(AOP(result),offr));
7216 /*-----------------------------------------------------------------*/
7217 /* shiftR2Left2Result - shift right two bytes from left to result */
7218 /*-----------------------------------------------------------------*/
7219 static void shiftR2Left2Result (operand *left, int offl,
7220 operand *result, int offr,
7221 int shCount, int sign)
7226 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7227 same = pic14_sameRegs(AOP(result), AOP(left));
7229 if(same && ((offl + MSB16) == offr)){
7231 /* don't crash result[offr] */
7232 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7233 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7236 movLeft2Result(left,offl, result, offr);
7237 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7240 /* a:x >> shCount (x = lsb(result))*/
7243 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7245 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7254 emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7259 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7260 emitpcode(POC_RRF,popGet(AOP(result),offr));
7262 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7263 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7264 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7265 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7270 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7273 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7274 emitpcode(POC_RRF,popGet(AOP(result),offr));
7281 emitpcode(POC_MOVLW, popGetLit(0xf0));
7282 emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7283 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7285 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7286 emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7287 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7288 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7290 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7291 emitpcode(POC_ANDLW, popGetLit(0x0f));
7292 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7294 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7295 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7296 emitpcode(POC_ANDLW, popGetLit(0xf0));
7297 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7298 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7302 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7303 emitpcode(POC_RRF, popGet(AOP(result),offr));
7307 emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7308 emitpcode(POC_BTFSC,
7309 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7310 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7318 emitpcode(POC_RLF, popGet(AOP(result),offr));
7319 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7321 emitpcode(POC_RLF, popGet(AOP(result),offr));
7322 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7323 emitpcode(POC_RLFW, popGet(AOP(result),offr));
7324 emitpcode(POC_ANDLW,popGetLit(0x03));
7326 emitpcode(POC_BTFSC,
7327 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7328 emitpcode(POC_IORLW,popGetLit(0xfc));
7330 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7331 emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7332 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7333 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7335 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7336 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7337 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7338 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7339 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7340 emitpcode(POC_RLF, popGet(AOP(result),offr));
7341 emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7342 emitpcode(POC_ANDLW,popGetLit(0x03));
7344 emitpcode(POC_BTFSC,
7345 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7346 emitpcode(POC_IORLW,popGetLit(0xfc));
7348 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7349 //emitpcode(POC_RLF, popGet(AOP(result),offr));
7356 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7357 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7358 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7359 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7362 emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7364 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7368 /*-----------------------------------------------------------------*/
7369 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7370 /*-----------------------------------------------------------------*/
7371 static void shiftLLeftOrResult (operand *left, int offl,
7372 operand *result, int offr, int shCount)
7375 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7377 /* shift left accumulator */
7378 AccLsh(left,offl,shCount);
7379 /* or with result */
7380 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7381 assert ( !"broken (modifies left, fails for left==result))" );
7384 /*-----------------------------------------------------------------*/
7385 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7386 /*-----------------------------------------------------------------*/
7387 static void shiftRLeftOrResult (operand *left, int offl,
7388 operand *result, int offr, int shCount)
7391 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7393 /* shift right accumulator */
7394 AccRsh(left,offl,shCount);
7395 /* or with result */
7396 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7397 assert ( !"broken (modifies left, fails for left==result))" );
7400 /*-----------------------------------------------------------------*/
7401 /* genlshOne - left shift a one byte quantity by known count */
7402 /*-----------------------------------------------------------------*/
7403 static void genlshOne (operand *result, operand *left, int shCount)
7406 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7407 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7410 /*-----------------------------------------------------------------*/
7411 /* genlshTwo - left shift two bytes by known amount != 0 */
7412 /*-----------------------------------------------------------------*/
7413 static void genlshTwo (operand *result,operand *left, int shCount)
7418 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7419 size = pic14_getDataSize(result);
7421 /* if shCount >= 8 */
7427 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7429 movLeft2Result(left, LSB, result, MSB16);
7431 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7434 /* 1 <= shCount <= 7 */
7437 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7439 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7443 /*-----------------------------------------------------------------*/
7444 /* shiftLLong - shift left one long from left to result */
7445 /* offl = LSB or MSB16 */
7446 /*-----------------------------------------------------------------*/
7447 static void shiftLLong (operand *left, operand *result, int offr )
7450 int size = AOP_SIZE(result);
7453 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7454 if(size >= LSB+offr){
7455 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7457 pic14_emitcode("add","a,acc");
7458 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7459 size >= MSB16+offr && offr != LSB )
7460 pic14_emitcode("xch","a,%s",
7461 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7463 aopPut(AOP(result),"a",LSB+offr);
7466 if(size >= MSB16+offr){
7467 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7468 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7471 pic14_emitcode("rlc","a");
7472 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7473 size >= MSB24+offr && offr != LSB)
7474 pic14_emitcode("xch","a,%s",
7475 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7477 aopPut(AOP(result),"a",MSB16+offr);
7480 if(size >= MSB24+offr){
7481 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7482 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7485 pic14_emitcode("rlc","a");
7486 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7487 size >= MSB32+offr && offr != LSB )
7488 pic14_emitcode("xch","a,%s",
7489 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7491 aopPut(AOP(result),"a",MSB24+offr);
7494 if(size > MSB32+offr){
7495 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7496 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7499 pic14_emitcode("rlc","a");
7500 aopPut(AOP(result),"a",MSB32+offr);
7503 aopPut(AOP(result),zero,LSB);
7506 /*-----------------------------------------------------------------*/
7507 /* genlshFour - shift four byte by a known amount != 0 */
7508 /*-----------------------------------------------------------------*/
7509 static void genlshFour (operand *result, operand *left, int shCount)
7514 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7515 size = AOP_SIZE(result);
7517 /* if shifting more that 3 bytes */
7518 if (shCount >= 24 ) {
7521 /* lowest order of left goes to the highest
7522 order of the destination */
7523 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7525 movLeft2Result(left, LSB, result, MSB32);
7526 aopPut(AOP(result),zero,LSB);
7527 aopPut(AOP(result),zero,MSB16);
7528 aopPut(AOP(result),zero,MSB32);
7532 /* more than two bytes */
7533 else if ( shCount >= 16 ) {
7534 /* lower order two bytes goes to higher order two bytes */
7536 /* if some more remaining */
7538 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7540 movLeft2Result(left, MSB16, result, MSB32);
7541 movLeft2Result(left, LSB, result, MSB24);
7543 aopPut(AOP(result),zero,MSB16);
7544 aopPut(AOP(result),zero,LSB);
7548 /* if more than 1 byte */
7549 else if ( shCount >= 8 ) {
7550 /* lower order three bytes goes to higher order three bytes */
7554 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7556 movLeft2Result(left, LSB, result, MSB16);
7558 else{ /* size = 4 */
7560 movLeft2Result(left, MSB24, result, MSB32);
7561 movLeft2Result(left, MSB16, result, MSB24);
7562 movLeft2Result(left, LSB, result, MSB16);
7563 aopPut(AOP(result),zero,LSB);
7565 else if(shCount == 1)
7566 shiftLLong(left, result, MSB16);
7568 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7569 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7570 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7571 aopPut(AOP(result),zero,LSB);
7576 /* 1 <= shCount <= 7 */
7577 else if(shCount <= 2){
7578 shiftLLong(left, result, LSB);
7580 shiftLLong(result, result, LSB);
7582 /* 3 <= shCount <= 7, optimize */
7584 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7585 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7586 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7592 /*-----------------------------------------------------------------*/
7593 /* genLeftShiftLiteral - left shifting by known count */
7594 /*-----------------------------------------------------------------*/
7595 static void genLeftShiftLiteral (operand *left,
7600 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7604 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7605 freeAsmop(right,NULL,ic,TRUE);
7607 aopOp(left,ic,FALSE);
7608 aopOp(result,ic,FALSE);
7610 size = getSize(operandType(result));
7613 pic14_emitcode("; shift left ","result %d, left %d",size,
7617 /* I suppose that the left size >= result size */
7620 movLeft2Result(left, size, result, size);
7624 else if(shCount >= (size * 8))
7626 aopPut(AOP(result),zero,size);
7630 genlshOne (result,left,shCount);
7635 genlshTwo (result,left,shCount);
7639 genlshFour (result,left,shCount);
7643 freeAsmop(left,NULL,ic,TRUE);
7644 freeAsmop(result,NULL,ic,TRUE);
7648 /*-----------------------------------------------------------------*
7649 * genMultiAsm - repeat assembly instruction for size of register.
7650 * if endian == 1, then the high byte (i.e base address + size of
7651 * register) is used first else the low byte is used first;
7652 *-----------------------------------------------------------------*/
7653 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7659 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7672 emitpcode(poc, popGet(AOP(reg),offset));
7679 /*-----------------------------------------------------------------*/
7680 /* genLeftShift - generates code for left shifting */
7681 /*-----------------------------------------------------------------*/
7682 static void genLeftShift (iCode *ic)
7684 operand *left,*right, *result;
7686 unsigned long lit = 0L;
7688 symbol *tlbl , *tlbl1;
7692 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7694 right = IC_RIGHT(ic);
7696 result = IC_RESULT(ic);
7698 aopOp(right,ic,FALSE);
7699 aopOp(left,ic,FALSE);
7700 aopOp(result,ic,FALSE);
7703 /* if the shift count is known then do it
7704 as efficiently as possible */
7705 if (AOP_TYPE(right) == AOP_LIT) {
7706 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7710 /* shift count is unknown then we have to form
7711 a loop get the loop count in B : Note: we take
7712 only the lower order byte since shifting
7713 more that 32 bits make no sense anyway, ( the
7714 largest size of an object can be only 32 bits ) */
7716 /* this code fails for RIGHT == RESULT */
7717 assert (!pic14_sameRegs (AOP(right), AOP(result)));
7719 /* now move the left to the result if they are not the
7721 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
7722 AOP_SIZE(result) > 1) {
7724 size = AOP_SIZE(result);
7727 l = aopGet(AOP(left),offset,FALSE,TRUE);
7728 if (*l == '@' && (IS_AOP_PREG(result))) {
7730 pic14_emitcode("mov","a,%s",l);
7731 aopPut(AOP(result),"a",offset);
7733 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
7734 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7735 //aopPut(AOP(result),l,offset);
7741 if(AOP_TYPE(left) == AOP_LIT)
7742 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7744 size = AOP_SIZE(result);
7746 /* if it is only one byte then */
7748 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7749 emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7750 emitpcode(POC_ANDLW, popGetLit(0xf0));
7751 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7752 emitpcode(POC_MOVFW, popGet(AOP(left),0));
7753 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7754 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7755 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7756 emitpcode(POC_RLFW, popGet(AOP(result),0));
7757 emitpcode(POC_ANDLW, popGetLit(0xfe));
7758 emitpcode(POC_ADDFW, popGet(AOP(result),0));
7759 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7760 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7763 tlbl = newiTempLabel(NULL);
7764 if (!pic14_sameRegs(AOP(left),AOP(result))) {
7765 mov2w (AOP(left), 0);
7766 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7769 emitpcode(POC_COMFW, popGet(AOP(right),0));
7770 emitpcode(POC_RRF, popGet(AOP(result),0));
7771 emitpLabel(tlbl->key);
7772 emitpcode(POC_RLF, popGet(AOP(result),0));
7773 emitpcode(POC_ADDLW, popGetLit(1));
7775 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7780 if (pic14_sameRegs(AOP(left),AOP(result))) {
7782 tlbl = newiTempLabel(NULL);
7783 emitpcode(POC_COMFW, popGet(AOP(right),0));
7784 genMultiAsm(POC_RRF, result, size,1);
7785 emitpLabel(tlbl->key);
7786 genMultiAsm(POC_RLF, result, size,0);
7787 emitpcode(POC_ADDLW, popGetLit(1));
7789 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7793 //tlbl = newiTempLabel(NULL);
7795 //tlbl1 = newiTempLabel(NULL);
7797 //reAdjustPreg(AOP(result));
7799 //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7800 //pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7801 //l = aopGet(AOP(result),offset,FALSE,FALSE);
7803 //pic14_emitcode("add","a,acc");
7804 //aopPut(AOP(result),"a",offset++);
7806 // l = aopGet(AOP(result),offset,FALSE,FALSE);
7808 // pic14_emitcode("rlc","a");
7809 // aopPut(AOP(result),"a",offset++);
7811 //reAdjustPreg(AOP(result));
7813 //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7814 //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7817 tlbl = newiTempLabel(NULL);
7818 tlbl1= newiTempLabel(NULL);
7820 size = AOP_SIZE(result);
7823 pctemp = popGetTempReg(); /* grab a temporary working register. */
7825 emitpcode(POC_MOVFW, popGet(AOP(right),0));
7827 /* offset should be 0, 1 or 3 */
7828 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7830 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
7832 emitpcode(POC_MOVWF, pctemp);
7835 emitpLabel(tlbl->key);
7838 emitpcode(POC_RLF, popGet(AOP(result),0));
7840 emitpcode(POC_RLF, popGet(AOP(result),offset++));
7842 emitpcode(POC_DECFSZ, pctemp);
7843 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7844 emitpLabel(tlbl1->key);
7846 popReleaseTempReg(pctemp);
7850 freeAsmop (right,NULL,ic,TRUE);
7851 freeAsmop(left,NULL,ic,TRUE);
7852 freeAsmop(result,NULL,ic,TRUE);
7857 /*-----------------------------------------------------------------*/
7858 /* genrshOne - right shift a one byte quantity by known count */
7859 /*-----------------------------------------------------------------*/
7860 static void genrshOne (operand *result, operand *left,
7861 int shCount, int sign)
7864 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7865 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7868 /*-----------------------------------------------------------------*/
7869 /* genrshTwo - right shift two bytes by known amount != 0 */
7870 /*-----------------------------------------------------------------*/
7871 static void genrshTwo (operand *result,operand *left,
7872 int shCount, int sign)
7875 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7876 /* if shCount >= 8 */
7880 shiftR1Left2Result(left, MSB16, result, LSB,
7883 movLeft2Result(left, MSB16, result, LSB);
7885 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7888 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7889 emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7893 /* 1 <= shCount <= 7 */
7895 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
7898 /*-----------------------------------------------------------------*/
7899 /* shiftRLong - shift right one long from left to result */
7900 /* offl = LSB or MSB16 */
7901 /*-----------------------------------------------------------------*/
7902 static void shiftRLong (operand *left, int offl,
7903 operand *result, int sign)
7908 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7910 size = AOP_SIZE(left);
7911 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7914 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7918 assert (offl >= 0 && offl < size);
7920 same = pic14_sameRegs (AOP(left), AOP(result));
7922 /* perform the shift */
7925 if (same && !offl) {
7926 emitpcode (POC_RRF, popGet (AOP(result), size));
7928 emitpcode (POC_RRFW, popGet (AOP(left), size));
7929 emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7933 addSign (result, AOP_SIZE(left) - offl, sign);
7936 /*-----------------------------------------------------------------*/
7937 /* genrshFour - shift four byte by a known amount != 0 */
7938 /*-----------------------------------------------------------------*/
7939 static void genrshFour (operand *result, operand *left,
7940 int shCount, int sign)
7943 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7944 /* if shifting more that 3 bytes */
7945 if(shCount >= 24 ) {
7948 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7950 movLeft2Result(left, MSB32, result, LSB);
7952 addSign(result, MSB16, sign);
7954 else if(shCount >= 16){
7957 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7959 movLeft2Result(left, MSB24, result, LSB);
7960 movLeft2Result(left, MSB32, result, MSB16);
7962 addSign(result, MSB24, sign);
7964 else if(shCount >= 8){
7967 shiftRLong(left, MSB16, result, sign);
7968 else if(shCount == 0){
7969 movLeft2Result(left, MSB16, result, LSB);
7970 movLeft2Result(left, MSB24, result, MSB16);
7971 movLeft2Result(left, MSB32, result, MSB24);
7972 addSign(result, MSB32, sign);
7975 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7976 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7977 /* the last shift is signed */
7978 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7979 addSign(result, MSB32, sign);
7982 else{ /* 1 <= shCount <= 7 */
7984 shiftRLong(left, LSB, result, sign);
7986 shiftRLong(result, LSB, result, sign);
7989 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7990 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7991 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7996 /*-----------------------------------------------------------------*/
7997 /* genRightShiftLiteral - right shifting by known count */
7998 /*-----------------------------------------------------------------*/
7999 static void genRightShiftLiteral (operand *left,
8005 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8009 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8010 freeAsmop(right,NULL,ic,TRUE);
8012 aopOp(left,ic,FALSE);
8013 aopOp(result,ic,FALSE);
8016 pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8020 lsize = pic14_getDataSize(left);
8021 res_size = pic14_getDataSize(result);
8022 /* test the LEFT size !!! */
8024 /* I suppose that the left size >= result size */
8027 movLeft2Result(left, res_size, result, res_size);
8030 else if(shCount >= (lsize * 8)){
8033 emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8035 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8036 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8041 emitpcode(POC_MOVLW, popGetLit(0));
8042 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8043 emitpcode(POC_MOVLW, popGetLit(0xff));
8045 emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8050 emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8057 genrshOne (result,left,shCount,sign);
8061 genrshTwo (result,left,shCount,sign);
8065 genrshFour (result,left,shCount,sign);
8073 freeAsmop(left,NULL,ic,TRUE);
8074 freeAsmop(result,NULL,ic,TRUE);
8079 /*-----------------------------------------------------------------*/
8080 /* genSignedRightShift - right shift of signed number */
8081 /*-----------------------------------------------------------------*/
8082 static void genSignedRightShift (iCode *ic)
8084 operand *right, *left, *result;
8087 symbol *tlbl, *tlbl1 ;
8090 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8092 /* we do it the hard way put the shift count in b
8093 and loop thru preserving the sign */
8095 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8097 right = IC_RIGHT(ic);
8099 result = IC_RESULT(ic);
8101 aopOp(right,ic,FALSE);
8102 aopOp(left,ic,FALSE);
8103 aopOp(result,ic,FALSE);
8106 if ( AOP_TYPE(right) == AOP_LIT) {
8107 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8108 //genRightShiftLiteral (left,right,result,ic,1);
8111 /* shift count is unknown then we have to form
8112 a loop get the loop count in B : Note: we take
8113 only the lower order byte since shifting
8114 more that 32 bits make no sense anyway, ( the
8115 largest size of an object can be only 32 bits ) */
8117 //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8118 //pic14_emitcode("inc","b");
8119 //freeAsmop (right,NULL,ic,TRUE);
8120 //aopOp(left,ic,FALSE);
8121 //aopOp(result,ic,FALSE);
8123 /* now move the left to the result if they are not the
8125 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
8126 AOP_SIZE(result) > 1) {
8128 size = AOP_SIZE(result);
8132 l = aopGet(AOP(left),offset,FALSE,TRUE);
8133 if (*l == '@' && IS_AOP_PREG(result)) {
8134 pic14_emitcode("mov","a,%s",l);
8135 aopPut(AOP(result),"a",offset);
8137 aopPut(AOP(result),l,offset);
8139 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8140 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8146 /* mov the highest order bit to OVR */
8147 tlbl = newiTempLabel(NULL);
8148 tlbl1= newiTempLabel(NULL);
8150 size = AOP_SIZE(result);
8153 pctemp = popGetTempReg(); /* grab a temporary working register. */
8155 emitpcode(POC_MOVFW, popGet(AOP(right),0));
8157 /* offset should be 0, 1 or 3 */
8158 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8160 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8162 emitpcode(POC_MOVWF, pctemp);
8165 emitpLabel(tlbl->key);
8167 emitpcode(POC_RLFW, popGet(AOP(result),offset));
8168 emitpcode(POC_RRF, popGet(AOP(result),offset));
8171 emitpcode(POC_RRF, popGet(AOP(result),--offset));
8174 emitpcode(POC_DECFSZ, pctemp);
8175 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8176 emitpLabel(tlbl1->key);
8178 popReleaseTempReg(pctemp);
8180 size = AOP_SIZE(result);
8182 pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8183 pic14_emitcode("rlc","a");
8184 pic14_emitcode("mov","ov,c");
8185 /* if it is only one byte then */
8187 l = aopGet(AOP(left),0,FALSE,FALSE);
8189 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8190 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8191 pic14_emitcode("mov","c,ov");
8192 pic14_emitcode("rrc","a");
8193 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8194 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8195 aopPut(AOP(result),"a",0);
8199 reAdjustPreg(AOP(result));
8200 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8201 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8202 pic14_emitcode("mov","c,ov");
8204 l = aopGet(AOP(result),offset,FALSE,FALSE);
8206 pic14_emitcode("rrc","a");
8207 aopPut(AOP(result),"a",offset--);
8209 reAdjustPreg(AOP(result));
8210 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8211 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8216 freeAsmop(left,NULL,ic,TRUE);
8217 freeAsmop(result,NULL,ic,TRUE);
8218 freeAsmop(right,NULL,ic,TRUE);
8222 /*-----------------------------------------------------------------*/
8223 /* loadSignToC - load the operand's sign bit into CARRY */
8224 /*-----------------------------------------------------------------*/
8226 static void loadSignToC (operand *op)
8229 assert (op && AOP(op) && AOP_SIZE(op));
8232 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8236 /*-----------------------------------------------------------------*/
8237 /* genRightShift - generate code for right shifting */
8238 /*-----------------------------------------------------------------*/
8239 static void genGenericShift (iCode *ic, int shiftRight)
8241 operand *right, *left, *result;
8244 symbol *tlbl, *tlbl1, *inverselbl;
8247 /* if signed then we do it the hard way preserve the
8248 sign bit moving it inwards */
8249 retype = getSpec(operandType(IC_RESULT(ic)));
8250 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8252 /* signed & unsigned types are treated the same : i.e. the
8253 signed is NOT propagated inwards : quoting from the
8254 ANSI - standard : "for E1 >> E2, is equivalent to division
8255 by 2**E2 if unsigned or if it has a non-negative value,
8256 otherwise the result is implementation defined ", MY definition
8257 is that the sign does not get propagated */
8259 right = IC_RIGHT(ic);
8261 result = IC_RESULT(ic);
8263 aopOp(right,ic,FALSE);
8264 aopOp(left,ic,FALSE);
8265 aopOp(result,ic,FALSE);
8267 /* if the shift count is known then do it
8268 as efficiently as possible */
8269 if (AOP_TYPE(right) == AOP_LIT) {
8270 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8274 shiftRight = !shiftRight;
8278 shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8280 shiftLeft_Left2ResultLit (left, result, lit);
8281 //genRightShiftLiteral (left,right,result,ic, 0);
8285 /* shift count is unknown then we have to form
8286 a loop get the loop count in B : Note: we take
8287 only the lower order byte since shifting
8288 more that 32 bits make no sense anyway, ( the
8289 largest size of an object can be only 32 bits ) */
8291 /* we must not overwrite the shift counter */
8292 assert (!pic14_sameRegs(AOP(right),AOP(result)));
8294 /* now move the left to the result if they are not the
8296 if (!pic14_sameRegs(AOP(left),AOP(result)))
8298 size = min(AOP_SIZE(result), AOP_SIZE(left));
8300 mov2w(AOP(left), size);
8301 movwf(AOP(result), size);
8303 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8306 tlbl = newiTempLabel(NULL);
8307 tlbl1= newiTempLabel(NULL);
8309 size = AOP_SIZE(result);
8311 mov2w(AOP(right),0);
8312 if (!SPEC_USIGN(operandType(right)))
8314 inverselbl = newiTempLabel(NULL);
8315 /* signed shift count -- invert shift direction for c<0 */
8316 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8317 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8319 emitpcode(POC_SUBLW, popGetLit(0)); /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8320 /* check for `a = b >> c' with `-c == 0' */
8322 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8323 emitpLabel(tlbl->key);
8324 /* propagate the sign bit inwards for SIGNED result */
8325 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8326 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8327 emitpcode(POC_ADDLW, popGetLit(1)); /* clears CARRY (unless W==0 afterwards) */
8329 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8331 if (!SPEC_USIGN(operandType(right)))
8333 symbol *inv_loop = newiTempLabel(NULL);
8335 shiftRight = !shiftRight; /* invert shift direction */
8337 /* we came here from the code above -- we are done */
8338 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8340 /* emit code for shifting N<0 steps, count is already in W */
8341 emitpLabel(inverselbl->key);
8342 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8343 emitpLabel(inv_loop->key);
8344 /* propagate the sign bit inwards for SIGNED result */
8345 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8346 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8347 emitpcode(POC_ADDLW, popGetLit(1));
8349 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8352 emitpLabel(tlbl1->key);
8354 freeAsmop(left,NULL,ic,TRUE);
8355 freeAsmop (right,NULL,ic,TRUE);
8356 freeAsmop(result,NULL,ic,TRUE);
8359 static void genRightShift (iCode *ic)
8361 genGenericShift(ic, 1);
8364 static void genLeftShift (iCode *ic)
8366 genGenericShift(ic, 0);
8369 /*-----------------------------------------------------------------*/
8370 /* SetIrp - Set IRP bit */
8371 /*-----------------------------------------------------------------*/
8372 void SetIrp(operand *result) {
8374 if (AOP_TYPE(result) == AOP_LIT) {
8375 unsigned lit = (unsigned)operandLitValue(result);
8381 if (PCOP(AOP(result))->type == PO_LITERAL) {
8382 int addrs = PCOL(AOP(result))->lit;
8388 emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8389 if(AOP_SIZE(result) > 1) {
8390 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8398 setup_fsr (operand *ptr)
8401 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8403 /* also setup-up IRP */
8407 /*-----------------------------------------------------------------*/
8408 /* emitPtrByteGet - emits code to get a byte into WREG from an */
8409 /* arbitrary pointer (__code, __data, generic) */
8410 /*-----------------------------------------------------------------*/
8412 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8419 if (!alreadyAddressed) setup_fsr (src);
8420 emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8424 assert( AOP_SIZE(src) == 2 );
8426 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8428 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8429 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
8430 call_libraryfunc ("__gptrget1");
8434 assert( AOP_SIZE(src) == 3 );
8436 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8438 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8440 call_libraryfunc ("__gptrget1");
8444 assert( !"unhandled pointer type" );
8449 /*-----------------------------------------------------------------*/
8450 /* emitPtrByteSet - emits code to set a byte from src through a */
8451 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR). */
8452 /*-----------------------------------------------------------------*/
8454 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8461 if (!alreadyAddressed) setup_fsr (dst);
8462 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8466 assert( !"trying to assign to __code pointer" );
8470 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8472 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8474 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8476 call_libraryfunc ("__gptrput1");
8480 assert( !"unhandled pointer type" );
8485 /*-----------------------------------------------------------------*/
8486 /* genUnpackBits - generates code for unpacking bits */
8487 /*-----------------------------------------------------------------*/
8488 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8490 int rsize; /* result size */
8491 sym_link *etype; /* bitfield type information */
8492 int blen; /* bitfield length */
8493 int bstr; /* bitfield starting bit within byte */
8496 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8497 etype = getSpec(operandType(result));
8498 rsize = getSize (operandType (result));
8499 blen = SPEC_BLEN (etype);
8500 bstr = SPEC_BSTR (etype);
8502 /* single bit field case */
8504 if (ifx) { /* that is for an if statement */
8507 resolveIfx(&rIfx,ifx);
8508 if (ptype == -1) /* direct */
8509 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8511 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8512 emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8513 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8517 assert (!pic14_sameRegs (AOP(result), AOP(left)));
8518 for (i=0; i < AOP_SIZE(result); i++)
8519 emitpcode (POC_CLRF, popGet (AOP(result), i));
8524 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8525 /* adjust result below */
8532 emitPtrByteGet (left, ptype, FALSE);
8533 emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8535 /* adjust result below */
8539 assert( !"unhandled pointer type" );
8542 /* move sign-/zero extended bit to result */
8543 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8544 emitpcode (POC_INCF, popGet (AOP(result), 0));
8546 emitpcode (POC_DECF, popGet (AOP(result), 0));
8548 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8552 else if (blen <= 8 && ((blen + bstr) <= 8))
8557 for (i=0; i < AOP_SIZE(result); i++)
8558 emitpcode (POC_CLRF, popGet (AOP(result), i));
8563 mov2w(AOP(left), 0);
8570 emitPtrByteGet (left, ptype, FALSE);
8574 assert( !"unhandled pointer type" );
8578 emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8579 movwf(AOP(result), 0);
8580 AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8582 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8584 /* signed bitfield */
8585 assert (bstr + blen > 0);
8586 emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8587 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8588 emitpcode(POC_IORWF, popGet(AOP(result),0));
8590 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8594 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8598 /*-----------------------------------------------------------------*/
8599 /* genDataPointerGet - generates code when ptr offset is known */
8600 /*-----------------------------------------------------------------*/
8601 static void genDataPointerGet (operand *left,
8605 int size , offset = 0;
8608 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8611 /* optimization - most of the time, left and result are the same
8612 * address, but different types. for the pic code, we could omit
8615 aopOp(result,ic,TRUE);
8617 if (pic14_sameRegs (AOP(left), AOP(result)))
8620 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8622 //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8624 size = AOP_SIZE(result);
8625 if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8629 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8630 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8634 freeAsmop(left,NULL,ic,TRUE);
8635 freeAsmop(result,NULL,ic,TRUE);
8639 /*-----------------------------------------------------------------*/
8640 /* genNearPointerGet - pic14_emitcode for near pointer fetch */
8641 /*-----------------------------------------------------------------*/
8642 static void genNearPointerGet (operand *left,
8647 sym_link *ltype = operandType(left);
8648 sym_link *rtype = operandType(result);
8649 sym_link *retype= getSpec(rtype); /* bitfield type information */
8653 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8656 aopOp(left,ic,FALSE);
8658 /* if left is rematerialisable and
8659 result is not bit variable type and
8660 the left is pointer to data space i.e
8661 lower 128 bytes of space */
8662 if (AOP_TYPE(left) == AOP_PCODE && //AOP_TYPE(left) == AOP_IMMD &&
8663 !IS_BITVAR(retype) &&
8664 PIC_IS_DATA_PTR(ltype)) {
8665 genDataPointerGet (left,result,ic);
8669 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8670 aopOp (result,ic,FALSE);
8672 /* Check if can access directly instead of via a pointer */
8673 if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8674 && AOP_SIZE(result) == 1)
8679 if (IS_BITFIELD(getSpec(operandType(result))))
8681 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8685 /* If the pointer value is not in a the FSR then need to put it in */
8686 /* Must set/reset IRP bit for use with FSR. */
8691 /* if bitfield then unpack the bits */
8693 /* we have can just get the values */
8694 int size = AOP_SIZE(result);
8697 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8701 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8703 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8704 if (AOP_TYPE(result) == AOP_LIT) {
8705 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8707 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8709 if (size && !direct)
8710 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8715 /* now some housekeeping stuff */
8717 /* we had to allocate for this iCode */
8718 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8719 freeAsmop(NULL,aop,ic,TRUE);
8721 /* we did not allocate which means left
8722 already in a pointer register, then
8723 if size > 0 && this could be used again
8724 we have to point it back to where it
8726 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8727 if (AOP_SIZE(result) > 1 &&
8728 !OP_SYMBOL(left)->remat &&
8729 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8731 int size = AOP_SIZE(result) - 1;
8733 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8739 freeAsmop(left,NULL,ic,TRUE);
8740 freeAsmop(result,NULL,ic,TRUE);
8745 /*-----------------------------------------------------------------*/
8746 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch */
8747 /*-----------------------------------------------------------------*/
8748 static void genPagedPointerGet (operand *left,
8755 sym_link *rtype, *retype;
8758 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8760 rtype = operandType(result);
8761 retype= getSpec(rtype);
8763 aopOp(left,ic,FALSE);
8765 /* if the value is already in a pointer register
8766 then don't need anything more */
8767 if (!AOP_INPREG(AOP(left))) {
8768 /* otherwise get a free pointer register */
8770 preg = getFreePtr(ic,&aop,FALSE);
8771 pic14_emitcode("mov","%s,%s",
8773 aopGet(AOP(left),0,FALSE,TRUE));
8774 rname = preg->name ;
8776 rname = aopGet(AOP(left),0,FALSE,FALSE);
8778 freeAsmop(left,NULL,ic,TRUE);
8779 aopOp (result,ic,FALSE);
8781 /* if bitfield then unpack the bits */
8782 if (IS_BITFIELD(retype))
8783 genUnpackBits (result,left,rname,PPOINTER,0);
8785 /* we have can just get the values */
8786 int size = AOP_SIZE(result);
8791 pic14_emitcode("movx","a,@%s",rname);
8792 aopPut(AOP(result),"a",offset);
8797 pic14_emitcode("inc","%s",rname);
8801 /* now some housekeeping stuff */
8803 /* we had to allocate for this iCode */
8804 freeAsmop(NULL,aop,ic,TRUE);
8806 /* we did not allocate which means left
8807 already in a pointer register, then
8808 if size > 0 && this could be used again
8809 we have to point it back to where it
8811 if (AOP_SIZE(result) > 1 &&
8812 !OP_SYMBOL(left)->remat &&
8813 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8815 int size = AOP_SIZE(result) - 1;
8817 pic14_emitcode("dec","%s",rname);
8822 freeAsmop(result,NULL,ic,TRUE);
8827 /*-----------------------------------------------------------------*/
8828 /* genFarPointerGet - gget value from far space */
8829 /*-----------------------------------------------------------------*/
8830 static void genFarPointerGet (operand *left,
8831 operand *result, iCode *ic)
8834 sym_link *retype = getSpec(operandType(result));
8837 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8839 aopOp(left,ic,FALSE);
8841 /* if the operand is already in dptr
8842 then we do nothing else we move the value to dptr */
8843 if (AOP_TYPE(left) != AOP_STR) {
8844 /* if this is remateriazable */
8845 if (AOP_TYPE(left) == AOP_IMMD)
8846 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8847 else { /* we need to get it byte by byte */
8848 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8849 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8850 if (options.model == MODEL_FLAT24)
8852 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8856 /* so dptr know contains the address */
8857 freeAsmop(left,NULL,ic,TRUE);
8858 aopOp(result,ic,FALSE);
8860 /* if bit then unpack */
8861 if (IS_BITFIELD(retype))
8862 genUnpackBits(result,left,"dptr",FPOINTER,0);
8864 size = AOP_SIZE(result);
8868 pic14_emitcode("movx","a,@dptr");
8869 aopPut(AOP(result),"a",offset++);
8871 pic14_emitcode("inc","dptr");
8875 freeAsmop(result,NULL,ic,TRUE);
8880 /*-----------------------------------------------------------------*/
8881 /* genCodePointerGet - get value from code space */
8882 /*-----------------------------------------------------------------*/
8883 static void genCodePointerGet (operand *left,
8884 operand *result, iCode *ic)
8887 sym_link *retype = getSpec(operandType(result));
8889 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8891 aopOp(left,ic,FALSE);
8893 /* if the operand is already in dptr
8894 then we do nothing else we move the value to dptr */
8895 if (AOP_TYPE(left) != AOP_STR) {
8896 /* if this is remateriazable */
8897 if (AOP_TYPE(left) == AOP_IMMD)
8898 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8899 else { /* we need to get it byte by byte */
8900 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8901 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8902 if (options.model == MODEL_FLAT24)
8904 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8908 /* so dptr know contains the address */
8909 freeAsmop(left,NULL,ic,TRUE);
8910 aopOp(result,ic,FALSE);
8912 /* if bit then unpack */
8913 if (IS_BITFIELD(retype))
8914 genUnpackBits(result,left,"dptr",CPOINTER,0);
8916 size = AOP_SIZE(result);
8920 pic14_emitcode("clr","a");
8921 pic14_emitcode("movc","a,@a+dptr");
8922 aopPut(AOP(result),"a",offset++);
8924 pic14_emitcode("inc","dptr");
8928 freeAsmop(result,NULL,ic,TRUE);
8931 /*-----------------------------------------------------------------*/
8932 /* genGenPointerGet - gget value from generic pointer space */
8933 /*-----------------------------------------------------------------*/
8934 static void genGenPointerGet (operand *left,
8935 operand *result, iCode *ic)
8938 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8939 aopOp(left,ic,FALSE);
8940 aopOp(result,ic,FALSE);
8943 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8945 if (IS_BITFIELD(getSpec(operandType(result))))
8947 genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
8952 /* emit call to __gptrget */
8953 char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
8954 int size = AOP_SIZE(result);
8957 assert (size > 0 && size <= 4);
8959 /* pass arguments */
8960 assert (AOP_SIZE(left) == 3);
8961 mov2w(AOP(left), 0);
8962 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8963 mov2w(AOP(left), 1);
8964 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8965 mov2w(AOP(left), 2);
8966 call_libraryfunc (func[size]);
8969 movwf (AOP(result), --size);
8971 emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
8972 movwf (AOP(result), size);
8976 freeAsmop(left,NULL,ic,TRUE);
8977 freeAsmop(result,NULL,ic,TRUE);
8981 /*-----------------------------------------------------------------*/
8982 /* genConstPointerGet - get value from const generic pointer space */
8983 /*-----------------------------------------------------------------*/
8984 static void genConstPointerGet (operand *left,
8985 operand *result, iCode *ic)
8987 //sym_link *retype = getSpec(operandType(result));
8989 symbol *albl, *blbl;//, *clbl;
8996 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8997 aopOp(left,ic,FALSE);
8998 aopOp(result,ic,FALSE);
9000 size = AOP_SIZE(result);
9002 DEBUGpic14_AopType(__LINE__,left,NULL,result);
9004 DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
9006 lit = op_isLitLike (left);
9007 poc = lit ? POC_MOVLW : POC_MOVFW;
9009 if (IS_BITFIELD(getSpec(operandType(result))))
9011 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
9016 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
9017 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
9018 assert (size > 0 && size <= 4);
9021 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9023 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9024 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
9025 call_libraryfunc (func[size]);
9027 movwf(AOP(result),size-1);
9028 for (i = 1; i < size; i++)
9030 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
9031 movwf(AOP(result),size - 1 - i);
9036 freeAsmop(left,NULL,ic,TRUE);
9037 freeAsmop(result,NULL,ic,TRUE);
9040 /*-----------------------------------------------------------------*/
9041 /* genPointerGet - generate code for pointer get */
9042 /*-----------------------------------------------------------------*/
9043 static void genPointerGet (iCode *ic)
9045 operand *left, *result ;
9046 sym_link *type, *etype;
9050 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9053 result = IC_RESULT(ic) ;
9055 /* depending on the type of pointer we need to
9056 move it to the correct pointer register */
9057 type = operandType(left);
9058 etype = getSpec(type);
9060 if (IS_PTR_CONST(type))
9061 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9063 /* if left is of type of pointer then it is simple */
9064 if (IS_PTR(type) && !IS_FUNC(type->next))
9065 p_type = DCL_TYPE(type);
9067 /* we have to go by the storage class */
9068 p_type = PTR_TYPE(SPEC_OCLS(etype));
9070 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9072 if (SPEC_OCLS(etype)->codesp ) {
9073 DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9074 //p_type = CPOINTER ;
9077 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9078 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9079 /*p_type = FPOINTER ;*/
9081 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9082 DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9083 /* p_type = PPOINTER; */
9085 if (SPEC_OCLS(etype) == idata )
9086 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9087 /* p_type = IPOINTER; */
9089 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9090 /* p_type = POINTER ; */
9093 /* now that we have the pointer type we assign
9094 the pointer values */
9100 genNearPointerGet (left,result,ic);
9104 genPagedPointerGet(left,result,ic);
9108 genFarPointerGet (left,result,ic);
9112 genConstPointerGet (left,result,ic);
9116 genGenPointerGet (left,result,ic);
9119 assert ( !"unhandled pointer type" );
9125 /*-----------------------------------------------------------------*/
9126 /* genPackBits - generates code for packed bit storage */
9127 /*-----------------------------------------------------------------*/
9128 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9130 int blen; /* bitfield length */
9131 int bstr; /* bitfield starting bit within byte */
9132 int litval; /* source literal value (if AOP_LIT) */
9133 unsigned char mask; /* bitmask within current byte */
9136 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9138 blen = SPEC_BLEN (etype);
9139 bstr = SPEC_BSTR (etype);
9141 /* If the bitfield length is less than a byte and does not cross byte boundaries */
9142 if ((blen <= 8) && ((bstr + blen) <= 8))
9144 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9145 (unsigned char) (0xFF >> (8 - bstr)));
9147 if (AOP_TYPE (right) == AOP_LIT)
9149 /* Case with a bitfield length <8 and literal source */
9150 int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9157 if (AOP(result)->type == AOP_PCODE)
9158 pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9160 pcop = popGet(AOP(result),0);
9161 emitpcode(lit?POC_BSF:POC_BCF,pcop);
9167 emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9171 assert( !"trying to assign to bitfield via pointer to __code space" );
9175 emitPtrByteGet(result, p_type, FALSE);
9177 emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9179 emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9181 emitPtrByteSet(result, p_type, TRUE);
9185 assert( !"unhandled pointer type" );
9187 } // switch (p_type)
9190 litval = lit << bstr;
9191 litval &= (~mask) & 0x00ff;
9196 mov2w (AOP(result), 0);
9197 if ((litval|mask) != 0x00ff)
9198 emitpcode(POC_ANDLW, popGetLit (mask));
9200 emitpcode(POC_IORLW, popGetLit (litval));
9201 movwf (AOP(result), 0);
9207 emitPtrByteGet(result, p_type, FALSE);
9208 if ((litval|mask) != 0x00ff)
9209 emitpcode(POC_ANDLW, popGetLit (mask));
9211 emitpcode(POC_IORLW, popGetLit (litval));
9212 emitPtrByteSet(result, p_type, TRUE);
9216 assert( !"trying to assign to bitfield via pointer to __code space" );
9220 assert( !"unhandled pointer type" );
9227 /* right is no literal */
9232 /* Note more efficient code, of pre clearing bit then only setting it if required,
9233 * can only be done if it is known that the result is not a SFR */
9234 emitpcode(POC_RRFW,popGet(AOP(right),0));
9236 emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9238 emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9244 emitPtrByteGet (result, p_type, FALSE);
9245 emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9246 emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9247 emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9248 emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9249 emitPtrByteSet (result, p_type, TRUE);
9253 assert( !"trying to assign to bitfield via pointer to __code space" );
9257 assert( !"unhandled pointer type" );
9262 /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9263 pCodeOp *temp = popGetTempReg ();
9265 mov2w (AOP(right), 0);
9267 emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9269 emitpcode(POC_MOVWF, temp);
9271 AccLsh (temp, bstr);
9277 mov2w (AOP(result), 0);
9278 emitpcode(POC_ANDLW, popGetLit (mask));
9279 emitpcode(POC_IORFW, temp);
9280 movwf (AOP(result), 0);
9286 emitPtrByteGet (result, p_type, FALSE);
9287 emitpcode(POC_ANDLW, popGetLit (mask));
9288 emitpcode(POC_IORFW, temp);
9289 emitPtrByteSet (result, p_type, TRUE);
9293 assert( !"trying to assign to bitfield via pointer to __code space" );
9297 assert( !"unhandled pointer type" );
9301 popReleaseTempReg (temp);
9303 } // if (AOP(right)->type != AOP_LIT)
9305 } // if (blen <= 8 && ((blen + bstr) <= 8))
9307 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9310 /*-----------------------------------------------------------------*/
9311 /* genDataPointerSet - remat pointer to data space */
9312 /*-----------------------------------------------------------------*/
9313 static void genDataPointerSet(operand *right,
9317 int size, offset = 0 ;
9321 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9322 aopOp(right,ic,FALSE);
9323 aopOp(result,ic,FALSE);
9325 assert (IS_SYMOP(result));
9326 assert (IS_PTR(OP_SYM_TYPE(result)));
9328 if (AOP_TYPE(right) == AOP_LIT)
9331 size = AOP_SIZE(right);
9332 ressize = getSize(OP_SYM_ETYPE(result));
9333 if (size > ressize) size = ressize;
9334 //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9336 //assert( !"what's going on here?" );
9339 if ( AOP_TYPE(result) == AOP_PCODE) {
9340 fprintf(stderr,"genDataPointerSet %s, %d\n",
9341 AOP(result)->aopu.pcop->name,
9342 PCOI(AOP(result)->aopu.pcop)->offset);
9346 // tsd, was l+1 - the underline `_' prefix was being stripped
9348 emitpComment ("%s:%u: size=%d/%d, offset=%d, AOP_TYPE(res)=%d", __FILE__,__LINE__, size, ressize, offset, AOP_TYPE(result));
9350 if (AOP_TYPE(right) == AOP_LIT) {
9351 unsigned int lit = pic14aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
9352 //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9354 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9355 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9357 emitpcode(POC_CLRF, popGet(AOP(result), offset));
9360 //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9361 emitpcode(POC_MOVFW, popGet(AOP(right), offset));
9362 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9368 freeAsmop(right,NULL,ic,TRUE);
9369 freeAsmop(result,NULL,ic,TRUE);
9372 /*-----------------------------------------------------------------*/
9373 /* genNearPointerSet - pic14_emitcode for near pointer put */
9374 /*-----------------------------------------------------------------*/
9375 static void genNearPointerSet (operand *right,
9380 sym_link *ptype = operandType(result);
9381 sym_link *retype = getSpec(operandType(right));
9382 sym_link *letype = getSpec(ptype);
9387 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9388 aopOp(result,ic,FALSE);
9391 /* if the result is rematerializable &
9392 in data space & not a bit variable */
9393 //if (AOP_TYPE(result) == AOP_IMMD &&
9394 if (AOP_TYPE(result) == AOP_PCODE &&
9395 PIC_IS_DATA_PTR(ptype) &&
9396 !IS_BITVAR (retype) &&
9397 !IS_BITVAR (letype)) {
9398 genDataPointerSet (right,result,ic);
9399 freeAsmop(result,NULL,ic,TRUE);
9404 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9405 aopOp(right,ic,FALSE);
9406 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9408 /* Check if can access directly instead of via a pointer */
9409 if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9413 if (IS_BITFIELD (letype))
9415 genPackBits (letype, result, right, direct?-1:POINTER);
9419 /* If the pointer value is not in a the FSR then need to put it in */
9420 /* Must set/reset IRP bit for use with FSR. */
9421 /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9426 /* we have can just get the values */
9427 int size = AOP_SIZE(right);
9430 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9432 char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9434 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9436 if (AOP_TYPE(right) == AOP_LIT) {
9437 emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9439 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9442 emitpcode(POC_MOVWF,popGet(AOP(result),0));
9444 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9446 if (size && !direct)
9447 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9452 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9453 /* now some housekeeping stuff */
9455 /* we had to allocate for this iCode */
9456 freeAsmop(NULL,aop,ic,TRUE);
9458 /* we did not allocate which means left
9459 already in a pointer register, then
9460 if size > 0 && this could be used again
9461 we have to point it back to where it
9463 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9464 if (AOP_SIZE(right) > 1 &&
9465 !OP_SYMBOL(result)->remat &&
9466 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9468 int size = AOP_SIZE(right) - 1;
9470 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9474 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9477 freeAsmop(right,NULL,ic,TRUE);
9478 freeAsmop(result,NULL,ic,TRUE);
9482 /*-----------------------------------------------------------------*/
9483 /* genPagedPointerSet - pic14_emitcode for Paged pointer put */
9484 /*-----------------------------------------------------------------*/
9485 static void genPagedPointerSet (operand *right,
9495 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9497 retype= getSpec(operandType(right));
9499 aopOp(result,ic,FALSE);
9501 /* if the value is already in a pointer register
9502 then don't need anything more */
9503 if (!AOP_INPREG(AOP(result))) {
9504 /* otherwise get a free pointer register */
9506 preg = getFreePtr(ic,&aop,FALSE);
9507 pic14_emitcode("mov","%s,%s",
9509 aopGet(AOP(result),0,FALSE,TRUE));
9510 rname = preg->name ;
9512 rname = aopGet(AOP(result),0,FALSE,FALSE);
9514 freeAsmop(result,NULL,ic,TRUE);
9515 aopOp (right,ic,FALSE);
9517 /* if bitfield then unpack the bits */
9518 if (IS_BITFIELD(retype))
9519 genPackBits (retype,result,right,rname,PPOINTER);
9521 /* we have can just get the values */
9522 int size = AOP_SIZE(right);
9526 l = aopGet(AOP(right),offset,FALSE,TRUE);
9529 pic14_emitcode("movx","@%s,a",rname);
9532 pic14_emitcode("inc","%s",rname);
9538 /* now some housekeeping stuff */
9540 /* we had to allocate for this iCode */
9541 freeAsmop(NULL,aop,ic,TRUE);
9543 /* we did not allocate which means left
9544 already in a pointer register, then
9545 if size > 0 && this could be used again
9546 we have to point it back to where it
9548 if (AOP_SIZE(right) > 1 &&
9549 !OP_SYMBOL(result)->remat &&
9550 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9552 int size = AOP_SIZE(right) - 1;
9554 pic14_emitcode("dec","%s",rname);
9559 freeAsmop(right,NULL,ic,TRUE);
9564 /*-----------------------------------------------------------------*/
9565 /* genFarPointerSet - set value from far space */
9566 /*-----------------------------------------------------------------*/
9567 static void genFarPointerSet (operand *right,
9568 operand *result, iCode *ic)
9571 sym_link *retype = getSpec(operandType(right));
9574 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9575 aopOp(result,ic,FALSE);
9577 /* if the operand is already in dptr
9578 then we do nothing else we move the value to dptr */
9579 if (AOP_TYPE(result) != AOP_STR) {
9580 /* if this is remateriazable */
9581 if (AOP_TYPE(result) == AOP_IMMD)
9582 pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9583 else { /* we need to get it byte by byte */
9584 pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9585 pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9586 if (options.model == MODEL_FLAT24)
9588 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9592 /* so dptr know contains the address */
9593 freeAsmop(result,NULL,ic,TRUE);
9594 aopOp(right,ic,FALSE);
9596 /* if bit then unpack */
9597 if (IS_BITFIELD(retype))
9598 genPackBits(retype,result,right,"dptr",FPOINTER);
9600 size = AOP_SIZE(right);
9604 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9606 pic14_emitcode("movx","@dptr,a");
9608 pic14_emitcode("inc","dptr");
9612 freeAsmop(right,NULL,ic,TRUE);
9616 /*-----------------------------------------------------------------*/
9617 /* genGenPointerSet - set value from generic pointer space */
9618 /*-----------------------------------------------------------------*/
9619 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9621 sym_link *retype = getSpec(operandType(result));
9624 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9625 aopOp(right,ic,FALSE);
9626 aopOp(result,ic,FALSE);
9629 DEBUGpic14_AopType(__LINE__,right,NULL,result);
9631 if (IS_BITFIELD(retype))
9633 genPackBits (retype, result, right, GPOINTER);
9638 /* emit call to __gptrput */
9639 char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9640 int size = AOP_SIZE(right);
9643 /* The following assertion fails for
9644 * struct foo { char a; char b; } bar;
9645 * void demo(struct foo *dst, char c) { dst->b = c; }
9646 * as size will be 1 (sizeof(c)), whereas dst->b will be accessed
9647 * using (((char *)dst)+1), whose OP_SYM_ETYPE still is struct foo
9649 * The frontend seems to guarantee that IC_LEFT has the correct size,
9650 * it works fine both for larger and smaller types of `char c'.
9652 //assert (size == getSize(OP_SYM_ETYPE(result)));
9653 assert (size > 0 && size <= 4);
9655 /* pass arguments */
9656 /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9662 mov2w_op (right, off);
9663 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9668 assert (AOP_SIZE(result) == 3);
9669 mov2w(AOP(result), 0);
9670 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9671 mov2w(AOP(result), 1);
9672 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9673 mov2w(AOP(result), 2);
9674 call_libraryfunc (func[size]);
9677 freeAsmop(right,NULL,ic,TRUE);
9678 freeAsmop(result,NULL,ic,TRUE);
9681 /*-----------------------------------------------------------------*/
9682 /* genPointerSet - stores the value into a pointer location */
9683 /*-----------------------------------------------------------------*/
9684 static void genPointerSet (iCode *ic)
9686 operand *right, *result ;
9687 sym_link *type, *etype;
9691 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9693 right = IC_RIGHT(ic);
9694 result = IC_RESULT(ic) ;
9696 /* depending on the type of pointer we need to
9697 move it to the correct pointer register */
9698 type = operandType(result);
9699 etype = getSpec(type);
9700 /* if left is of type of pointer then it is simple */
9701 if (IS_PTR(type) && !IS_FUNC(type->next)) {
9702 p_type = DCL_TYPE(type);
9705 /* we have to go by the storage class */
9706 p_type = PTR_TYPE(SPEC_OCLS(etype));
9708 /* if (SPEC_OCLS(etype)->codesp ) { */
9709 /* p_type = CPOINTER ; */
9712 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9713 /* p_type = FPOINTER ; */
9715 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9716 /* p_type = PPOINTER ; */
9718 /* if (SPEC_OCLS(etype) == idata ) */
9719 /* p_type = IPOINTER ; */
9721 /* p_type = POINTER ; */
9724 /* now that we have the pointer type we assign
9725 the pointer values */
9731 genNearPointerSet (right,result,ic);
9735 genPagedPointerSet (right,result,ic);
9739 genFarPointerSet (right,result,ic);
9743 genGenPointerSet (right,result,ic);
9747 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9748 "genPointerSet: illegal pointer type");
9752 /*-----------------------------------------------------------------*/
9753 /* genIfx - generate code for Ifx statement */
9754 /*-----------------------------------------------------------------*/
9755 static void genIfx (iCode *ic, iCode *popIc)
9757 operand *cond = IC_COND(ic);
9761 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9763 aopOp(cond,ic,FALSE);
9765 /* get the value into acc */
9766 if (AOP_TYPE(cond) != AOP_CRY)
9767 pic14_toBoolean(cond);
9771 /* if there was something to be popped then do it */
9777 /* This assumes that CARRY is set iff cond is true */
9780 assert (!IC_FALSE(ic));
9781 emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
9783 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9785 assert (IC_FALSE(ic));
9786 emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
9788 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9792 static int hasWarned = 0;
9795 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
9802 /* now Z is set iff !cond */
9805 assert (!IC_FALSE(ic));
9807 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9810 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9816 /* the result is now in the accumulator */
9817 freeAsmop(cond,NULL,ic,TRUE);
9820 /*-----------------------------------------------------------------*/
9821 /* genAddrOf - generates code for address of */
9822 /*-----------------------------------------------------------------*/
9823 static void genAddrOf (iCode *ic)
9825 operand *right, *result, *left;
9829 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9832 //aopOp(IC_RESULT(ic),ic,FALSE);
9834 aopOp((left=IC_LEFT(ic)),ic,FALSE);
9835 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9836 aopOp((result=IC_RESULT(ic)),ic,TRUE);
9838 DEBUGpic14_AopType(__LINE__,left,right,result);
9839 assert (IS_SYMOP (left));
9841 /* sanity check: generic pointers to code space are not yet supported,
9842 * pionters to codespace must not be assigned addresses of __data values. */
9844 fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9845 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)));
9846 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)));
9847 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)));
9848 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)));
9851 if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9852 fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9853 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9854 OP_SYMBOL(left)->name);
9855 } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9856 fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9857 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9858 OP_SYMBOL(left)->name);
9861 size = AOP_SIZE(IC_RESULT(ic));
9862 if (IS_GENPTR(OP_SYM_TYPE(result))) {
9864 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9869 /* fixing bug #863624, reported from (errolv) */
9870 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9871 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9874 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9875 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9880 if (IS_GENPTR(OP_SYM_TYPE(result)))
9882 /* provide correct tag */
9883 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9884 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9885 movwf (AOP(result), 2);
9888 freeAsmop(left,NULL,ic,FALSE);
9889 freeAsmop(result,NULL,ic,TRUE);
9894 /*-----------------------------------------------------------------*/
9895 /* genFarFarAssign - assignment when both are in far space */
9896 /*-----------------------------------------------------------------*/
9897 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9899 int size = AOP_SIZE(right);
9902 /* first push the right side on to the stack */
9904 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9906 pic14_emitcode ("push","acc");
9909 freeAsmop(right,NULL,ic,FALSE);
9910 /* now assign DPTR to result */
9911 aopOp(result,ic,FALSE);
9912 size = AOP_SIZE(result);
9914 pic14_emitcode ("pop","acc");
9915 aopPut(AOP(result),"a",--offset);
9917 freeAsmop(result,NULL,ic,FALSE);
9922 /*-----------------------------------------------------------------*/
9923 /* genAssign - generate code for assignment */
9924 /*-----------------------------------------------------------------*/
9925 static void genAssign (iCode *ic)
9927 operand *result, *right;
9928 int size, offset,know_W;
9929 unsigned long lit = 0L;
9931 result = IC_RESULT(ic);
9932 right = IC_RIGHT(ic) ;
9935 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9937 /* if they are the same */
9938 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9941 aopOp(right,ic,FALSE);
9942 aopOp(result,ic,TRUE);
9944 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9946 /* if they are the same registers */
9947 if (pic14_sameRegs(AOP(right),AOP(result)))
9950 /* special case: assign from __code */
9951 if (!IS_ITEMP(right) /* --> iTemps never reside in __code */
9952 && IS_SYMOP (right) /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
9953 && !IS_FUNC(OP_SYM_TYPE(right)) /* --> we would want its address instead of the first instruction */
9954 && !IS_CODEPTR(OP_SYM_TYPE(right)) /* --> get symbols address instread */
9955 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
9957 emitpComment ("genAssign from CODESPACE");
9958 genConstPointerGet (right, result, ic);
9962 /* just for symmetry reasons... */
9963 if (!IS_ITEMP(result)
9964 && IS_SYMOP (result)
9965 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
9967 assert ( !"cannot write to CODESPACE" );
9970 /* if the result is a bit */
9971 if (AOP_TYPE(result) == AOP_CRY) {
9973 /* if the right size is a literal then
9974 we know what the value is */
9975 if (AOP_TYPE(right) == AOP_LIT) {
9977 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9978 popGet(AOP(result),0));
9980 if (((int) operandLitValue(right)))
9981 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9982 AOP(result)->aopu.aop_dir,
9983 AOP(result)->aopu.aop_dir);
9985 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9986 AOP(result)->aopu.aop_dir,
9987 AOP(result)->aopu.aop_dir);
9991 /* the right is also a bit variable */
9992 if (AOP_TYPE(right) == AOP_CRY) {
9993 emitpcode(POC_BCF, popGet(AOP(result),0));
9994 emitpcode(POC_BTFSC, popGet(AOP(right),0));
9995 emitpcode(POC_BSF, popGet(AOP(result),0));
9997 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9998 AOP(result)->aopu.aop_dir,
9999 AOP(result)->aopu.aop_dir);
10000 pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
10001 AOP(right)->aopu.aop_dir,
10002 AOP(right)->aopu.aop_dir);
10003 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10004 AOP(result)->aopu.aop_dir,
10005 AOP(result)->aopu.aop_dir);
10009 /* we need to or */
10010 emitpcode(POC_BCF, popGet(AOP(result),0));
10011 pic14_toBoolean(right);
10013 emitpcode(POC_BSF, popGet(AOP(result),0));
10014 //aopPut(AOP(result),"a",0);
10018 /* bit variables done */
10020 size = AOP_SIZE(result);
10022 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
10023 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10024 if(aopIdx(AOP(result),0) == 4) {
10025 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10026 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10027 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10030 DEBUGpic14_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
10036 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10037 if(AOP_TYPE(right) == AOP_LIT) {
10038 lit = (unsigned long)pic14aopLiteral(AOP(right)->aopu.aop_lit, offset) & 0x0ff;
10040 if(know_W != (int)(lit&0xff))
10041 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10043 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10045 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10047 } else if (AOP_TYPE(right) == AOP_CRY) {
10048 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10050 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10051 emitpcode(POC_INCF, popGet(AOP(result),0));
10054 mov2w_op (right, offset);
10055 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10063 freeAsmop (right,NULL,ic,FALSE);
10064 freeAsmop (result,NULL,ic,TRUE);
10067 /*-----------------------------------------------------------------*/
10068 /* genJumpTab - genrates code for jump table */
10069 /*-----------------------------------------------------------------*/
10070 static void genJumpTab (iCode *ic)
10076 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10078 aopOp(IC_JTCOND(ic),ic,FALSE);
10079 /* get the condition into accumulator */
10080 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10082 /* multiply by three */
10083 pic14_emitcode("add","a,acc");
10084 pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10086 jtab = newiTempLabel(NULL);
10087 pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10088 pic14_emitcode("jmp","@a+dptr");
10089 pic14_emitcode("","%05d_DS_:",jtab->key+100);
10091 emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10092 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10093 emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10094 emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10096 emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10097 emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10098 emitpLabel(jtab->key);
10100 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10102 /* now generate the jump labels */
10103 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10104 jtab = setNextItem(IC_JTLABELS(ic))) {
10105 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10106 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10112 /*-----------------------------------------------------------------*/
10113 /* genMixedOperation - gen code for operators between mixed types */
10114 /*-----------------------------------------------------------------*/
10116 TSD - Written for the PIC port - but this unfortunately is buggy.
10117 This routine is good in that it is able to efficiently promote
10118 types to different (larger) sizes. Unfortunately, the temporary
10119 variables that are optimized out by this routine are sometimes
10120 used in other places. So until I know how to really parse the
10121 iCode tree, I'm going to not be using this routine :(.
10123 static int genMixedOperation (iCode *ic)
10127 operand *result = IC_RESULT(ic);
10128 sym_link *ctype = operandType(IC_LEFT(ic));
10129 operand *right = IC_RIGHT(ic);
10135 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10137 pic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10143 nextright = IC_RIGHT(nextic);
10144 nextleft = IC_LEFT(nextic);
10145 nextresult = IC_RESULT(nextic);
10147 aopOp(right,ic,FALSE);
10148 aopOp(result,ic,FALSE);
10149 aopOp(nextright, nextic, FALSE);
10150 aopOp(nextleft, nextic, FALSE);
10151 aopOp(nextresult, nextic, FALSE);
10153 if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10155 operand *t = right;
10159 pic14_emitcode(";remove right +","");
10161 } else if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10163 operand *t = right;
10167 pic14_emitcode(";remove left +","");
10171 big = AOP_SIZE(nextleft);
10172 small = AOP_SIZE(nextright);
10174 switch(nextic->op) {
10177 pic14_emitcode(";optimize a +","");
10178 /* if unsigned or not an integral type */
10179 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10180 pic14_emitcode(";add a bit to something","");
10183 pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10185 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10186 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10187 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10189 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10197 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10198 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10199 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10202 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10204 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10205 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10206 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10207 pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10208 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10211 pic14_emitcode("rlf","known_zero,w");
10218 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10219 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10220 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10222 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10232 freeAsmop(right,NULL,ic,TRUE);
10233 freeAsmop(result,NULL,ic,TRUE);
10234 freeAsmop(nextright,NULL,ic,TRUE);
10235 freeAsmop(nextleft,NULL,ic,TRUE);
10237 nextic->generated = 1;
10244 /*-----------------------------------------------------------------*/
10245 /* genCast - gen code for casting */
10246 /*-----------------------------------------------------------------*/
10247 static void genCast (iCode *ic)
10249 operand *result = IC_RESULT(ic);
10250 sym_link *restype = operandType(result);
10251 sym_link *rtype = operandType(IC_RIGHT(ic));
10252 operand *right = IC_RIGHT(ic);
10256 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10257 /* if they are equivalent then do nothing */
10258 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10261 aopOp(right,ic,FALSE) ;
10262 aopOp(result,ic,FALSE);
10264 DEBUGpic14_AopType(__LINE__,NULL,right,result);
10266 /* if the result is a bit */
10267 if (AOP_TYPE(result) == AOP_CRY) {
10268 assert(!"assigning to bit variables is not supported");
10271 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10273 size = AOP_SIZE(result);
10275 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10277 emitpcode(POC_CLRF, popGet(AOP(result),0));
10278 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10279 emitpcode(POC_INCF, popGet(AOP(result),0));
10282 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
10287 if (IS_PTR(restype))
10289 operand *result = IC_RESULT(ic);
10290 //operand *left = IC_LEFT(ic);
10291 operand *right = IC_RIGHT(ic);
10294 /* copy common part */
10295 int max, size = AOP_SIZE(result);
10296 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10297 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10299 /* warn if we discard generic opinter tag */
10300 if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10302 //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10308 mov2w_op (right, size);
10309 movwf (AOP(result), size);
10312 /* upcast into generic pointer type? */
10313 if (IS_GENPTR(restype)
10314 && (size < AOP_SIZE(result))
10315 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10317 //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10320 switch (DCL_TYPE(rtype))
10322 case POINTER: /* __data */
10323 case FPOINTER: /* __data */
10324 assert (AOP_SIZE(right) == 2);
10325 tag = GPTRTAG_DATA;
10328 case CPOINTER: /* __code */
10329 assert (AOP_SIZE(right) == 2);
10330 tag = GPTRTAG_CODE;
10333 case GPOINTER: /* unknown destination, __data or __code */
10334 /* assume __data space (address of immediate) */
10335 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10336 if (AOP(right)->code)
10337 tag = GPTRTAG_CODE;
10339 tag = GPTRTAG_DATA;
10343 assert (!"unhandled pointer type");
10346 /* convert other values into pointers to __data space */
10347 tag = GPTRTAG_DATA;
10350 assert (AOP_SIZE(result) == 3);
10352 emitpcode(POC_CLRF, popGet(AOP(result), 2));
10354 emitpcode(POC_MOVLW, popGetLit(tag));
10355 movwf(AOP(result), 2);
10358 addSign(result, max, 0);
10363 /* if they are the same size : or less */
10364 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10366 /* if they are in the same place */
10367 if (pic14_sameRegs(AOP(right),AOP(result)))
10370 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10371 if (IS_PTR_CONST(rtype))
10372 DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10373 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10374 DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10376 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10377 emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10378 emitpcode(POC_MOVWF, popGet(AOP(result),0));
10379 emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10380 emitpcode(POC_MOVWF, popGet(AOP(result),1));
10381 if(AOP_SIZE(result) <2)
10382 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10386 /* if they in different places then copy */
10387 size = AOP_SIZE(result);
10390 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10391 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10393 //aopPut(AOP(result),
10394 // aopGet(AOP(right),offset,FALSE,FALSE),
10403 /* so we now know that the size of destination is greater
10404 than the size of the source.
10405 Now, if the next iCode is an operator then we might be
10406 able to optimize the operation without performing a cast.
10408 if(0 && genMixedOperation(ic)) {
10409 /* XXX: cannot optimize: must copy regs! */
10413 /* we move to result for the size of source */
10414 size = AOP_SIZE(right);
10417 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10418 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10422 addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10425 freeAsmop(right,NULL,ic,TRUE);
10426 freeAsmop(result,NULL,ic,TRUE);
10430 /*-----------------------------------------------------------------*/
10431 /* genDjnz - generate decrement & jump if not zero instrucion */
10432 /*-----------------------------------------------------------------*/
10433 static int genDjnz (iCode *ic, iCode *ifx)
10435 symbol *lbl, *lbl1;
10437 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10442 /* if the if condition has a false label
10443 then we cannot save */
10447 /* if the minus is not of the form
10449 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10450 !IS_OP_LITERAL(IC_RIGHT(ic)))
10453 if (operandLitValue(IC_RIGHT(ic)) != 1)
10456 /* if the size of this greater than one then no
10458 if (getSize(operandType(IC_RESULT(ic))) > 1)
10461 /* otherwise we can save BIG */
10462 lbl = newiTempLabel(NULL);
10463 lbl1= newiTempLabel(NULL);
10465 aopOp(IC_RESULT(ic),ic,FALSE);
10467 if (IS_AOP_PREG(IC_RESULT(ic))) {
10468 pic14_emitcode("dec","%s",
10469 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10470 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10471 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10475 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10476 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10478 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10479 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10482 /* pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10483 /* pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10484 /* pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10485 /* pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10488 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10489 ifx->generated = 1;
10493 /*-----------------------------------------------------------------*/
10494 /* genReceive - generate code for a receive iCode */
10495 /*-----------------------------------------------------------------*/
10496 static void genReceive (iCode *ic)
10499 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10501 if (isOperandInFarSpace(IC_RESULT(ic)) &&
10502 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10503 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10505 int size = getSize(operandType(IC_RESULT(ic)));
10506 int offset = fReturnSizePic - size;
10508 pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10509 fReturn[fReturnSizePic - offset - 1] : "acc"));
10512 aopOp(IC_RESULT(ic),ic,FALSE);
10513 size = AOP_SIZE(IC_RESULT(ic));
10516 pic14_emitcode ("pop","acc");
10517 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10522 aopOp(IC_RESULT(ic),ic,FALSE);
10524 GpsuedoStkPtr = ic->parmBytes; // address used arg on stack
10525 assignResultValue(IC_RESULT(ic));
10528 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10531 /*-----------------------------------------------------------------*/
10532 /* genDummyRead - generate code for dummy read of volatiles */
10533 /*-----------------------------------------------------------------*/
10535 genDummyRead (iCode * ic)
10538 pic14_emitcode ("; genDummyRead","");
10539 pic14_emitcode ("; not implemented","");
10544 /*-----------------------------------------------------------------*/
10545 /* genpic14Code - generate code for pic14 based controllers */
10546 /*-----------------------------------------------------------------*/
10548 * At this point, ralloc.c has gone through the iCode and attempted
10549 * to optimize in a way suitable for a PIC. Now we've got to generate
10550 * PIC instructions that correspond to the iCode.
10552 * Once the instructions are generated, we'll pass through both the
10553 * peep hole optimizer and the pCode optimizer.
10554 *-----------------------------------------------------------------*/
10556 void genpic14Code (iCode *lic)
10563 lineHead = lineCurr = NULL;
10565 pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10568 /* if debug information required */
10569 if (options.debug && debugFile && currFunc) {
10570 debugFile->writeFunction (currFunc, lic);
10574 for (ic = lic ; ic ; ic = ic->next ) {
10576 //DEBUGpic14_emitcode(";ic","");
10577 //fprintf (stderr, "in ic loop\n");
10578 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10579 //ic->lineno, printCLine(ic->filename, ic->lineno));
10581 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10583 //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10584 cline = printCLine (ic->filename, ic->lineno);
10585 if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10586 addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10587 //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10590 if (options.iCodeInAsm) {
10591 char *iLine = printILine(ic);
10592 emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10595 /* if the result is marked as
10596 spilt and rematerializable or code for
10597 this has already been generated then
10599 if (resultRemat(ic) || ic->generated )
10602 /* depending on the operation */
10621 /* IPOP happens only when trying to restore a
10622 spilt live range, if there is an ifx statement
10623 following this pop then the if statement might
10624 be using some of the registers being popped which
10625 would destory the contents of the register so
10626 we need to check for this condition and handle it */
10628 ic->next->op == IFX &&
10629 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10630 genIfx (ic->next,ic);
10648 genEndFunction (ic);
10668 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10685 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
10689 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10696 /* note these two are xlated by algebraic equivalence
10697 during parsing SDCC.y */
10698 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10699 "got '>=' or '<=' shouldn't have come here");
10703 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10715 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10719 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10723 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10747 genRightShift (ic);
10750 case GET_VALUE_AT_ADDRESS:
10755 if (POINTER_SET(ic))
10782 addSet(&_G.sendSet,ic);
10785 case DUMMY_READ_VOLATILE:
10790 fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10797 /* now we are ready to call the
10798 peep hole optimizer */
10799 if (!options.nopeep) {
10800 peepHole (&lineHead);
10802 /* now do the actual printing */
10803 printLine (lineHead,codeOutBuf);
10806 DFPRINTF((stderr,"printing pBlock\n\n"));
10807 printpBlock(stdout,pb);
10813 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10814 * (meaning: representing its own address) or not (referencing its contents).
10815 * This can only be decided based on the operand's type. */
10817 aop_isLitLike (asmop *aop)
10820 if (aop->type == AOP_LIT) return 1;
10821 if (aop->type == AOP_IMMD) return 1;
10822 if ((aop->type == AOP_PCODE) &&
10823 ((aop->aopu.pcop->type == PO_LITERAL)))
10825 /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10826 * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10833 op_isLitLike (operand *op)
10836 if (aop_isLitLike (AOP(op))) return 1;
10837 if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10838 if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;