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 -------------------------------------------------------------------------*/
34 * This is the down and dirty file with all kinds of
35 * kludgy & hacky stuff. This is what it is all about
36 * CODE GENERATION for a specific MCU . some of the
37 * routines may be reusable, will have to see.
46 extern struct dbuf_s *codeOutBuf;
50 static pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
51 static pCodeOp *popRegFromString(char *str, int size, int offset);
52 static int aop_isLitLike(asmop *aop);
54 /* The PIC port(s) need not differentiate between POINTER and FPOINTER. */
55 #define PIC_IS_DATA_PTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
58 * max_key keeps track of the largest label number used in
59 * a function. This is then used to adjust the label offset
60 * for the next function.
62 static int max_key = 0;
63 static int labelOffset = 0;
64 static int GpsuedoStkPtr = 0;
65 static int pic14_inISR = 0;
67 static char *zero = "0x00";
68 static char *one = "0x01";
69 static char *spname = "sp";
71 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
72 static char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
73 static char **fReturn = fReturnpic14;
84 * Resolved ifx structure. This structure stores information
85 * about an iCode ifx that makes it easier to generate code.
87 typedef struct resolvedIfx {
88 symbol *lbl; /* pointer to a label */
89 int condition; /* true or false ifx */
90 int generated; /* set true when the code associated with the ifx
94 static lineNode *lineHead = NULL;
95 static lineNode *lineCurr = NULL;
98 /*-----------------------------------------------------------------*/
99 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
100 /* exponent of 2 is returned, otherwise -1 is */
102 /* note that this is similar to the function `powof2' in SDCCsymt */
106 /*-----------------------------------------------------------------*/
107 static int my_powof2 (unsigned long num)
110 if( (num & (num-1)) == 0) {
123 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
126 DEBUGpic14_emitcode ("; ","line = %d result %s=%s, size=%d, left %s=%s, size=%d, right %s=%s, size=%d",
128 ((result) ? AopType(AOP_TYPE(result)) : "-"),
129 ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
130 ((result) ? AOP_SIZE(result) : 0),
131 ((left) ? AopType(AOP_TYPE(left)) : "-"),
132 ((left) ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
133 ((left) ? AOP_SIZE(left) : 0),
134 ((right) ? AopType(AOP_TYPE(right)) : "-"),
135 ((right) ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
136 ((right) ? AOP_SIZE(right) : 0));
140 static void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
143 DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
145 ((result) ? AopType(AOP_TYPE(result)) : "-"),
146 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
147 ((left) ? AopType(AOP_TYPE(left)) : "-"),
148 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
149 ((right) ? AopType(AOP_TYPE(right)) : "-"),
150 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
154 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
157 char lb[INITIAL_INLINEASM];
158 unsigned char *lbp = (unsigned char *)lb;
160 if(!debug_verbose && !options.debug)
167 sprintf(lb,"%s\t",inst);
169 sprintf(lb,"%s",inst);
170 vsprintf(lb+(strlen(lb)),fmt,ap);
174 while (isspace(*lbp)) lbp++;
177 lineCurr = (lineCurr ?
178 connectLine(lineCurr,newLineNode(lb)) :
179 (lineHead = newLineNode(lb)));
180 lineCurr->isInline = _G.inLine;
181 lineCurr->isDebug = _G.debugLine;
183 addpCode2pBlock(pb,newpCodeCharP(lb));
188 static void Safe_vsnprintf (char *buf, size_t size, const char *fmt, va_list ap)
190 #if defined (HAVE_VSNPRINTF)
191 vsnprintf (buf, size, fmt, ap);
192 #elif defined (HAVE_VSPRINTF)
193 vsprintf (buf, size, fmt, ap);
194 if (strlen (buf) >= size)
196 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
198 #elif defined (HAVE_SNPRINTF)
199 snprintf (buf, size, "vs(n)printf required");
200 #elif defined (HAVE_SRINTF)
201 sprintf (buf, "vs(n)printf required");
202 if (strlen (buf) >= size)
204 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
207 assert ( !"neither vsnprintf nor vsprintf is present -- unable to proceed" );
211 void emitpComment (const char *fmt, ...)
218 Safe_vsnprintf (buffer, 4096, fmt, va);
219 //fprintf (stderr, "%s\n" ,buffer);
220 addpCode2pBlock (pb, newpCodeCharP (buffer));
225 void emitpLabel(int key)
227 addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
230 /* gen.h defines a macro emitpcode that should be used to call emitpcode
231 * as this allows for easy debugging (ever asked the question: where was
232 * this instruction geenrated? Here is the answer... */
233 void emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
236 addpCode2pBlock(pb,newpCode(poc,pcop));
238 static int has_warned = 0;
240 DEBUGpic14_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
243 fprintf( stderr, "WARNING: encountered NULL pcop--this is probably a compiler bug...\n" );
248 static void emitpcodeNULLop(PIC_OPCODE poc)
250 addpCode2pBlock(pb,newpCode(poc,NULL));
253 /*-----------------------------------------------------------------*/
254 /* pic14_emitcode - writes the code into a file : for now it is simple */
255 /*-----------------------------------------------------------------*/
256 void pic14_emitcode (char *inst,char *fmt, ...)
259 char lb[INITIAL_INLINEASM];
266 sprintf(lb,"%s\t",inst);
268 sprintf(lb,"%s",inst);
269 vsprintf(lb+(strlen(lb)),fmt,ap);
273 while (isspace(*lbp)) lbp++;
276 lineCurr = (lineCurr ?
277 connectLine(lineCurr,newLineNode(lb)) :
278 (lineHead = newLineNode(lb)));
279 lineCurr->isInline = _G.inLine;
280 lineCurr->isDebug = _G.debugLine;
281 lineCurr->isLabel = (lbp[strlen (lbp) - 1] == ':');
284 addpCode2pBlock(pb,newpCodeCharP(lb));
289 /*-----------------------------------------------------------------*/
290 /* pic14_emitDebuggerSymbol - associate the current code location */
291 /* with a debugger symbol */
292 /*-----------------------------------------------------------------*/
294 pic14_emitDebuggerSymbol (char * debugSym)
297 pic14_emitcode ("", ";%s ==.", debugSym);
301 /*-----------------------------------------------------------------*/
302 /* newAsmop - creates a new asmOp */
303 /*-----------------------------------------------------------------*/
304 static asmop *newAsmop (short type)
308 aop = Safe_calloc(1,sizeof(asmop));
313 /*-----------------------------------------------------------------*/
314 /* resolveIfx - converts an iCode ifx into a form more useful for */
315 /* generating code */
316 /*-----------------------------------------------------------------*/
317 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
322 // DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
324 resIfx->condition = 1; /* assume that the ifx is true */
325 resIfx->generated = 0; /* indicate that the ifx has not been used */
328 resIfx->lbl = NULL; /* this is wrong: newiTempLabel(NULL); / * oops, there is no ifx. so create a label */
331 resIfx->lbl = IC_TRUE(ifx);
333 resIfx->lbl = IC_FALSE(ifx);
334 resIfx->condition = 0;
338 // DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
342 /*-----------------------------------------------------------------*/
343 /* aopForSym - for a true symbol */
344 /*-----------------------------------------------------------------*/
345 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
348 memmap *space= SPEC_OCLS(sym->etype);
350 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
351 /* if already has one */
355 //DEBUGpic14_emitcode(";","%d",__LINE__);
356 /* if it is in direct space */
357 if (IN_DIRSPACE(space)) {
358 sym->aop = aop = newAsmop (AOP_DIR);
359 aop->aopu.aop_dir = sym->rname ;
360 aop->size = getSize(sym->type);
361 DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
365 /* special case for a function */
366 if (IS_FUNC(sym->type)) {
368 sym->aop = aop = newAsmop(AOP_PCODE);
369 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
370 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
371 PCOI(aop->aopu.pcop)->_function = 1;
372 PCOI(aop->aopu.pcop)->index = 0;
373 aop->size = FPTRSIZE;
374 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
378 if (IS_ARRAY(sym->type)) {
379 sym->aop = aop = newAsmop(AOP_PCODE);
380 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
381 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
382 PCOI(aop->aopu.pcop)->_function = 0;
383 PCOI(aop->aopu.pcop)->index = 0;
384 aop->size = getSize(sym->etype) * DCL_ELEM(sym->type);
386 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
390 /* only remaining is far space */
391 /* in which case DPTR gets the address */
392 sym->aop = aop = newAsmop(AOP_PCODE);
394 aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
395 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
396 PCOI(aop->aopu.pcop)->index = 0;
398 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
399 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
401 allocDirReg (IC_LEFT(ic));
403 aop->size = FPTRSIZE;
405 /* if it is in code space */
406 if (IN_CODESPACE(space))
412 /*-----------------------------------------------------------------*/
413 /* aopForRemat - rematerialzes an object */
414 /*-----------------------------------------------------------------*/
415 static asmop *aopForRemat (operand *op) // x symbol *sym)
417 symbol *sym = OP_SYMBOL(op);
419 asmop *aop = newAsmop(AOP_PCODE);
423 ic = sym->rematiCode;
425 DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
426 if(IS_OP_POINTER(op)) {
427 DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
431 val += (int) operandLitValue(IC_RIGHT(ic));
432 } else if (ic->op == '-') {
433 val -= (int) operandLitValue(IC_RIGHT(ic));
437 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
440 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
441 aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
442 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
443 PCOI(aop->aopu.pcop)->index = val;
445 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
446 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
447 val, IS_PTR_CONST(operandType(op)));
449 // DEBUGpic14_emitcode(";","aop type %s",AopType(AOP_TYPE(IC_LEFT(ic))));
451 allocDirReg (IC_LEFT(ic));
456 static int aopIdx (asmop *aop, int offset)
461 if(aop->type != AOP_REG)
464 return aop->aopu.aop_reg[offset]->rIdx;
468 /*-----------------------------------------------------------------*/
469 /* regsInCommon - two operands have some registers in common */
470 /*-----------------------------------------------------------------*/
471 static bool regsInCommon (operand *op1, operand *op2)
476 /* if they have registers in common */
477 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
480 sym1 = OP_SYMBOL(op1);
481 sym2 = OP_SYMBOL(op2);
483 if (sym1->nRegs == 0 || sym2->nRegs == 0)
486 for (i = 0 ; i < sym1->nRegs ; i++) {
491 for (j = 0 ; j < sym2->nRegs ;j++ ) {
495 if (sym2->regs[j] == sym1->regs[i])
503 /*-----------------------------------------------------------------*/
504 /* operandsEqu - equivalent */
505 /*-----------------------------------------------------------------*/
506 static bool operandsEqu ( operand *op1, operand *op2)
510 /* if they not symbols */
511 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
514 sym1 = OP_SYMBOL(op1);
515 sym2 = OP_SYMBOL(op2);
517 /* if both are itemps & one is spilt
518 and the other is not then false */
519 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
520 sym1->isspilt != sym2->isspilt )
523 /* if they are the same */
527 if (sym1->rname[0] && sym2->rname[0]
528 && strcmp (sym1->rname, sym2->rname) == 0)
532 /* if left is a tmp & right is not */
536 (sym1->usl.spillLoc == sym2))
543 (sym2->usl.spillLoc == sym1))
549 /*-----------------------------------------------------------------*/
550 /* pic14_sameRegs - two asmops have the same registers */
551 /*-----------------------------------------------------------------*/
552 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
559 if (aop1->type != AOP_REG ||
560 aop2->type != AOP_REG )
563 if (aop1->size != aop2->size )
566 for (i = 0 ; i < aop1->size ; i++ )
567 if (aop1->aopu.aop_reg[i] !=
568 aop2->aopu.aop_reg[i] )
574 /*-----------------------------------------------------------------*/
575 /* aopOp - allocates an asmop for an operand : */
576 /*-----------------------------------------------------------------*/
577 void aopOp (operand *op, iCode *ic, bool result)
586 /* if this a literal */
587 if (IS_OP_LITERAL(op)) {
588 op->aop = aop = newAsmop(AOP_LIT);
589 aop->aopu.aop_lit = op->operand.valOperand;
590 aop->size = getSize(operandType(op));
595 sym_link *type = operandType(op);
596 if(IS_PTR_CONST(type))
597 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
600 /* if already has a asmop then continue */
604 /* if the underlying symbol has a aop */
605 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
606 DEBUGpic14_emitcode(";","%d",__LINE__);
607 op->aop = OP_SYMBOL(op)->aop;
611 /* if this is a true symbol */
612 if (IS_TRUE_SYMOP(op)) {
613 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
614 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
618 /* this is a temporary : this has
624 e) can be a return use only */
629 /* if the type is a conditional */
630 if (sym->regType == REG_CND) {
631 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
636 /* if it is spilt then two situations
638 b) has a spill location */
639 if (sym->isspilt || sym->nRegs == 0) {
641 DEBUGpic14_emitcode(";","%d",__LINE__);
642 /* rematerialize it NOW */
645 sym->aop = op->aop = aop = aopForRemat (op);
646 aop->size = getSize(sym->type);
647 //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
652 if(sym->isptr) { // && sym->uptr
653 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
654 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
656 //PCOI(aop->aopu.pcop)->_const = 0;
657 //PCOI(aop->aopu.pcop)->index = 0;
659 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
660 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
662 //allocDirReg (IC_LEFT(ic));
664 aop->size = getSize(sym->type);
665 DEBUGpic14_emitcode(";","%d",__LINE__);
672 aop = op->aop = sym->aop = newAsmop(AOP_STR);
673 aop->size = getSize(sym->type);
674 for ( i = 0 ; i < fReturnSizePic ; i++ )
675 aop->aopu.aop_str[i] = fReturn[i];
677 DEBUGpic14_emitcode(";","%d",__LINE__);
682 /* else spill location */
683 if (sym->usl.spillLoc)
685 asmop *oldAsmOp = NULL;
687 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
689 /* force a new aop if sizes differ */
690 oldAsmOp = sym->usl.spillLoc->aop;
691 sym->usl.spillLoc->aop = NULL;
693 DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
694 __FUNCTION__,__LINE__,
695 sym->usl.spillLoc->rname,
696 sym->rname, sym->usl.spillLoc->offset);
698 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
699 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
701 /* Don't reuse the new aop, go with the last one */
702 sym->usl.spillLoc->aop = oldAsmOp;
704 //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
705 aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname,
707 sym->usl.spillLoc->offset);
708 aop->size = getSize(sym->type);
715 sym_link *type = operandType(op);
716 if(IS_PTR_CONST(type))
717 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
720 /* must be in a register */
721 DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
722 sym->aop = op->aop = aop = newAsmop(AOP_REG);
723 aop->size = sym->nRegs;
724 for ( i = 0 ; i < sym->nRegs ;i++)
725 aop->aopu.aop_reg[i] = sym->regs[i];
728 /*-----------------------------------------------------------------*/
729 /* freeAsmop - free up the asmop given to an operand */
730 /*----------------------------------------------------------------*/
731 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
745 /* all other cases just dealloc */
749 OP_SYMBOL(op)->aop = NULL;
750 /* if the symbol has a spill */
752 SPIL_LOC(op)->aop = NULL;
757 /*-----------------------------------------------------------------*/
758 /* pic14aopLiteral - string from a literal value */
759 /*-----------------------------------------------------------------*/
760 static unsigned int pic14aopLiteral (value *val, int offset)
767 /* if it is a float then it gets tricky */
768 /* otherwise it is fairly simple */
769 if (!IS_FLOAT(val->type)) {
770 unsigned long v = ulFromVal (val);
772 return ( (v >> (offset * 8)) & 0xff);
775 /* it is type float */
776 fl.f = (float) floatFromVal(val);
777 #ifdef WORDS_BIGENDIAN
778 return fl.c[3-offset];
784 /*-----------------------------------------------------------------*/
785 /* aopGet - for fetching value of the aop */
786 /*-----------------------------------------------------------------*/
787 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
792 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
793 /* offset is greater than
796 if (offset > (aop->size - 1) &&
797 aop->type != AOP_LIT)
800 /* depending on type */
805 sprintf (s,"%s",aop->aopu.aop_immd);
808 sprintf(s,"(%s >> %d)",
814 DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
815 rs = Safe_calloc(1,strlen(s)+1);
821 sprintf(s,"(%s + %d)",
824 DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
826 sprintf(s,"%s",aop->aopu.aop_dir);
827 rs = Safe_calloc(1,strlen(s)+1);
833 // return aop->aopu.aop_reg[offset]->dname;
835 return aop->aopu.aop_reg[offset]->name;
838 //pic14_emitcode(";","%d",__LINE__);
839 return aop->aopu.aop_dir;
842 sprintf(s, "0x%02x", pic14aopLiteral (aop->aopu.aop_lit, offset));
848 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
851 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
853 return aop->aopu.aop_str[offset];
857 pCodeOp *pcop = aop->aopu.pcop;
858 DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
860 if (pcop->type == PO_IMMEDIATE) {
861 offset += PCOI(pcop)->index;
864 DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
865 sprintf(s,"(%s+%d)", pcop->name,offset);
867 DEBUGpic14_emitcode(";","%s",pcop->name);
868 sprintf(s,"%s", pcop->name);
871 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
874 rs = Safe_calloc(1,strlen(s)+1);
880 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
881 "aopget got unsupported aop->type");
885 /*-----------------------------------------------------------------*/
886 /* popGetTempReg - create a new temporary pCodeOp */
887 /*-----------------------------------------------------------------*/
888 static pCodeOp *popGetTempReg(void)
893 pcop = newpCodeOp(NULL, PO_GPR_TEMP);
894 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
895 PCOR(pcop)->r->wasUsed=1;
896 PCOR(pcop)->r->isFree=0;
902 /*-----------------------------------------------------------------*/
903 /* popReleaseTempReg - create a new temporary pCodeOp */
904 /*-----------------------------------------------------------------*/
905 static void popReleaseTempReg(pCodeOp *pcop)
908 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
909 PCOR(pcop)->r->isFree = 1;
913 /*-----------------------------------------------------------------*/
914 /* popGetLabel - create a new pCodeOp of type PO_LABEL */
915 /*-----------------------------------------------------------------*/
916 pCodeOp *popGetLabel(unsigned int key)
919 DEBUGpic14_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, labelOffset);
921 if(key>(unsigned int)max_key)
924 return newpCodeOpLabel(NULL,key+100+labelOffset);
927 /*-------------------------------------------------------------------*/
928 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
929 /*-------------------------------------------------------------------*/
930 static pCodeOp *popGetHighLabel(unsigned int key)
933 pcop = popGetLabel(key);
934 PCOLAB(pcop)->offset = 1;
938 /*-----------------------------------------------------------------*/
939 /* popGetLit - asm operator to pcode operator conversion */
940 /*-----------------------------------------------------------------*/
941 pCodeOp *popGetLit(unsigned int lit)
944 return newpCodeOpLit((unsigned char)lit);
947 /*-----------------------------------------------------------------*/
948 /* popGetImmd - asm operator to pcode immediate conversion */
949 /*-----------------------------------------------------------------*/
950 static pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
953 return newpCodeOpImmd(name, offset,index, 0, is_func);
956 /*-----------------------------------------------------------------*/
957 /* popGetWithString - asm operator to pcode operator conversion */
958 /*-----------------------------------------------------------------*/
959 static pCodeOp *popGetWithString(char *str, int isExtern)
965 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
969 pcop = newpCodeOp(str,PO_STR);
970 PCOS(pcop)->isPublic = isExtern ? 1 : 0;
975 pCodeOp *popGetExternal (char *str, int isReg)
980 pcop = newpCodeOpRegFromStr(str);
982 pcop = popGetWithString (str, 1);
988 for (sym = setFirstItem (externs); sym; sym = setNextItem (externs))
990 if (!strcmp (str, sym->rname)) break;
995 sym = newSymbol(str, 0);
996 strncpy(sym->rname, str, SDCC_NAME_MAX);
997 addSet (&externs, sym);
1004 /*-----------------------------------------------------------------*/
1005 /* popRegFromString - */
1006 /*-----------------------------------------------------------------*/
1007 static pCodeOp *popRegFromString(char *str, int size, int offset)
1010 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1011 pcop->type = PO_DIR;
1013 DEBUGpic14_emitcode(";","%d",__LINE__);
1018 pcop->name = Safe_calloc(1,strlen(str)+1);
1019 strcpy(pcop->name,str);
1021 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1023 PCOR(pcop)->r = dirregWithName(pcop->name);
1024 if(PCOR(pcop)->r == NULL) {
1025 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1026 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1027 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1029 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1031 PCOR(pcop)->instance = offset;
1036 /*-----------------------------------------------------------------*/
1037 /*-----------------------------------------------------------------*/
1038 static pCodeOp *popRegFromIdx(int rIdx)
1042 DEBUGpic14_emitcode ("; ***","%s,%d , rIdx=0x%x",
1043 __FUNCTION__,__LINE__,rIdx);
1045 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1047 PCOR(pcop)->rIdx = rIdx;
1048 PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1049 PCOR(pcop)->r->isFree = 0;
1050 PCOR(pcop)->r->wasUsed = 1;
1052 pcop->type = PCOR(pcop)->r->pc_type;
1058 /*-----------------------------------------------------------------*/
1059 /* popGet - asm operator to pcode operator conversion */
1060 /*-----------------------------------------------------------------*/
1061 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1063 //char *s = buffer ;
1068 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1069 /* offset is greater than
1075 /* XXX: still needed for BIT operands (AOP_CRY) */
1076 if (offset > (aop->size - 1) &&
1077 aop->type != AOP_LIT &&
1078 aop->type != AOP_PCODE)
1080 printf( "%s: (offset[%d] > AOP_SIZE(op)[%d]-1) && AOP_TYPE(op) != AOP_LIT)\n", __FUNCTION__, offset, aop->size);
1081 return NULL; //zero;
1084 /* depending on type */
1085 switch (aop->type) {
1088 DEBUGpic14_emitcode(";","%d",__LINE__);
1089 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1092 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1097 assert (offset < aop->size);
1098 rIdx = aop->aopu.aop_reg[offset]->rIdx;
1100 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1101 PCOR(pcop)->rIdx = rIdx;
1102 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1103 PCOR(pcop)->r->wasUsed=1;
1104 PCOR(pcop)->r->isFree=0;
1106 PCOR(pcop)->instance = offset;
1107 pcop->type = PCOR(pcop)->r->pc_type;
1108 //rs = aop->aopu.aop_reg[offset]->name;
1109 DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1114 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1115 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1116 //if(PCOR(pcop)->r == NULL)
1117 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1121 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1124 DEBUGpic14_emitcode(";","%d %s",__LINE__,aop->aopu.aop_str[offset]);
1125 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1129 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1131 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1132 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1133 switch (aop->aopu.pcop->type)
1136 pcop = pCodeOpCopy (aop->aopu.pcop);
1137 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1138 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1139 PCOI(pcop)->index += offset;
1140 //PCOI(pcop)->offset = 0;
1143 pcop = pCodeOpCopy (aop->aopu.pcop);
1144 PCOR(pcop)->instance = offset;
1147 assert ( !"unhandled pCode type" );
1153 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1154 "popGet got unsupported aop->type");
1158 /*-----------------------------------------------------------------*/
1159 /* popGetAddr - access the low/high word of a symbol (immediate) */
1160 /* (for non-PO_IMMEDIATEs this is the same as popGet) */
1161 /*-----------------------------------------------------------------*/
1162 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1164 if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1166 pCodeOp *pcop = aop->aopu.pcop;
1167 assert (offset <= GPTRSIZE);
1169 /* special case: index >= 2 should return GPOINTER-style values */
1172 pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1176 pcop = pCodeOpCopy (pcop);
1177 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1178 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1179 PCOI(pcop)->offset += offset;
1180 PCOI(pcop)->index += index;
1181 //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);
1184 return popGet (aop, offset + index);
1188 /*-----------------------------------------------------------------*/
1189 /* aopPut - puts a string for a aop */
1190 /*-----------------------------------------------------------------*/
1191 void aopPut (asmop *aop, char *s, int offset)
1196 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1198 if (aop->size && offset > ( aop->size - 1)) {
1199 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1200 "aopPut got offset > aop->size");
1204 /* will assign value to value */
1205 /* depending on where it is ofcourse */
1206 switch (aop->type) {
1209 sprintf(d,"(%s + %d)",
1210 aop->aopu.aop_dir,offset);
1211 fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1214 sprintf(d,"%s",aop->aopu.aop_dir);
1217 DEBUGpic14_emitcode(";","%d",__LINE__);
1219 pic14_emitcode("movf","%s,w",s);
1220 pic14_emitcode("movwf","%s",d);
1223 pic14_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
1224 if(offset >= aop->size) {
1225 emitpcode(POC_CLRF,popGet(aop,offset));
1228 emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
1231 emitpcode(POC_MOVWF,popGet(aop,offset));
1237 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1238 if(strcmp(s,"W")==0 )
1239 pic14_emitcode("movf","%s,w ; %d",s,__LINE__);
1241 pic14_emitcode("movwf","%s",
1242 aop->aopu.aop_reg[offset]->name);
1244 if(strcmp(s,zero)==0) {
1245 emitpcode(POC_CLRF,popGet(aop,offset));
1247 } else if(strcmp(s,"W")==0) {
1248 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1249 pcop->type = PO_GPR_REGISTER;
1251 PCOR(pcop)->rIdx = -1;
1252 PCOR(pcop)->r = NULL;
1254 DEBUGpic14_emitcode(";","%d",__LINE__);
1255 pcop->name = Safe_strdup(s);
1256 emitpcode(POC_MOVFW,pcop);
1257 emitpcode(POC_MOVWF,popGet(aop,offset));
1258 } else if(strcmp(s,one)==0) {
1259 emitpcode(POC_CLRF,popGet(aop,offset));
1260 emitpcode(POC_INCF,popGet(aop,offset));
1262 emitpcode(POC_MOVWF,popGet(aop,offset));
1268 if (strcmp(s,"a") == 0)
1269 pic14_emitcode("push","acc");
1271 pic14_emitcode("push","%s",s);
1276 /* if bit variable */
1277 if (!aop->aopu.aop_dir) {
1278 pic14_emitcode("clr","a");
1279 pic14_emitcode("rlc","a");
1282 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1285 pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1288 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1290 lbl = newiTempLabel(NULL);
1292 if (strcmp(s,"a")) {
1295 pic14_emitcode("clr","c");
1296 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1297 pic14_emitcode("cpl","c");
1298 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1299 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1306 if (strcmp(aop->aopu.aop_str[offset],s))
1307 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1311 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1312 "aopPut got unsupported aop->type");
1318 /*-----------------------------------------------------------------*/
1319 /* mov2w_op - generate either a MOVLW or MOVFW based operand type */
1320 /*-----------------------------------------------------------------*/
1321 static void mov2w_op (operand *op, int offset)
1326 /* for PO_IMMEDIATEs: use address or value? */
1327 if (op_isLitLike (op))
1329 /* access address of op */
1330 if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
1331 if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
1333 if (offset == GPTRSIZE-1)
1334 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1336 emitpcode (POC_MOVLW, popGetLit (0));
1339 emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
1341 /* access value stored in op */
1342 mov2w (AOP(op), offset);
1347 /*-----------------------------------------------------------------*/
1348 /* mov2w - generate either a MOVLW or MOVFW based operand type */
1349 /*-----------------------------------------------------------------*/
1350 void mov2w (asmop *aop, int offset)
1356 DEBUGpic14_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
1358 if ( aop_isLitLike (aop) )
1359 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1361 emitpcode(POC_MOVFW,popGet(aop,offset));
1365 static void movwf (asmop *op, int offset)
1367 emitpcode (POC_MOVWF, popGet(op, offset));
1370 static pCodeOp *get_argument_pcop (int idx)
1372 assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1373 return popRegFromIdx (Gstack_base_addr - (idx - 1));
1376 static pCodeOp *get_return_val_pcop (int offset)
1378 assert (offset > 0 && "the most significant byte is returned via WREG");
1379 return popRegFromIdx (Gstack_base_addr - (offset - 1));
1382 static void pass_argument (operand *op, int offset, int idx)
1385 mov2w_op (op, offset);
1387 emitpcode(POC_MOVWF, get_argument_pcop (idx));
1390 static void get_returnvalue (operand *op, int offset, int idx)
1393 emitpcode(POC_MOVFW, get_return_val_pcop (idx));
1394 movwf(AOP(op), offset);
1397 static void call_libraryfunc (char *name)
1401 /* library code might reside in different page... */
1402 emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1403 /* call the library function */
1404 emitpcode (POC_CALL, popGetExternal (name, 0));
1405 /* might return from different page... */
1406 emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1408 /* create symbol, mark it as `extern' */
1409 sym = findSym(SymbolTab, NULL, name);
1411 sym = newSymbol(name, 0);
1412 strncpy(sym->rname, name, SDCC_NAME_MAX);
1413 addSym(SymbolTab, sym, sym->rname, 0, 0, 0);
1414 addSet(&externs, sym);
1419 /*-----------------------------------------------------------------*/
1420 /* pic14_getDataSize - get the operand data size */
1421 /*-----------------------------------------------------------------*/
1422 int pic14_getDataSize(operand *op)
1426 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1429 size = getSize(OP_SYM_ETYPE(op));
1431 //return AOP_SIZE(op);
1433 // tsd- in the pic port, the genptr size is 1, so this code here
1434 // fails. ( in the 8051 port, the size was 4).
1436 size = AOP_SIZE(op);
1437 if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)))
1439 sym_link *type = operandType(op);
1440 if (IS_GENPTR(type))
1442 /* generic pointer; arithmetic operations
1443 * should ignore the high byte (pointer type).
1446 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1453 /*-----------------------------------------------------------------*/
1454 /* pic14_outAcc - output Acc */
1455 /*-----------------------------------------------------------------*/
1456 void pic14_outAcc(operand *result)
1459 DEBUGpic14_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
1460 DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1463 size = pic14_getDataSize(result);
1465 emitpcode(POC_MOVWF,popGet(AOP(result),0));
1468 /* unsigned or positive */
1470 emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1475 /*-----------------------------------------------------------------*/
1476 /* pic14_outBitC - output a bit C */
1477 /*-----------------------------------------------------------------*/
1478 static void pic14_outBitC(operand *result)
1481 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1482 /* if the result is bit */
1483 if (AOP_TYPE(result) == AOP_CRY)
1484 aopPut(AOP(result),"c",0);
1486 pic14_emitcode("clr","a ; %d", __LINE__);
1487 pic14_emitcode("rlc","a");
1488 pic14_outAcc(result);
1492 /*-----------------------------------------------------------------*/
1493 /* pic14_toBoolean - emit code for orl a,operator(sizeop) */
1494 /*-----------------------------------------------------------------*/
1495 static void pic14_toBoolean(operand *oper)
1497 int size = AOP_SIZE(oper);
1500 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1505 /* MOVFW does not load the flags... */
1506 emitpcode(POC_MOVLW, popGetLit(0));
1509 emitpcode(POC_MOVFW,popGet(AOP(oper),0));
1513 while (offset < size) {
1514 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
1516 /* Z is set iff (oper == 0) */
1520 /*-----------------------------------------------------------------*/
1521 /* genNot - generate code for ! operation */
1522 /*-----------------------------------------------------------------*/
1523 static void genNot (iCode *ic)
1530 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1531 /* assign asmOps to operand & result */
1532 aopOp (IC_LEFT(ic),ic,FALSE);
1533 aopOp (IC_RESULT(ic),ic,TRUE);
1535 DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1536 /* if in bit space then a special case */
1537 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1538 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1539 emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
1540 emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
1542 emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
1543 emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
1544 emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
1549 size = AOP_SIZE(IC_LEFT(ic));
1550 mov2w (AOP(IC_LEFT(ic)),0);
1553 if (op_isLitLike (IC_LEFT(ic)))
1554 emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
1556 emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
1558 emitpcode(POC_MOVLW, popGetLit (0));
1560 emitpcode(POC_MOVLW, popGetLit (1));
1561 movwf(AOP(IC_RESULT(ic)), 0);
1563 for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
1565 emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
1570 /* release the aops */
1571 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1572 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1576 /*-----------------------------------------------------------------*/
1577 /* genCpl - generate code for complement */
1578 /*-----------------------------------------------------------------*/
1579 static void genCpl (iCode *ic)
1581 operand *left, *result;
1586 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1587 aopOp((left = IC_LEFT(ic)),ic,FALSE);
1588 aopOp((result=IC_RESULT(ic)),ic,TRUE);
1590 /* if both are in bit space then
1592 if (AOP_TYPE(result) == AOP_CRY &&
1593 AOP_TYPE(left) == AOP_CRY ) {
1595 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir);
1596 pic14_emitcode("cpl","c");
1597 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir);
1601 size = AOP_SIZE(result);
1602 if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
1604 emitpcode(POC_COMFW,popGet(AOP(left),offset));
1605 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
1608 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
1612 /* release the aops */
1613 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1614 freeAsmop(result,NULL,ic,TRUE);
1617 /*-----------------------------------------------------------------*/
1618 /* genUminusFloat - unary minus for floating points */
1619 /*-----------------------------------------------------------------*/
1621 genUminusFloat(operand *op, operand *result)
1627 DEBUGpic14_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
1628 /* for this we just need to flip the
1629 first it then copy the rest in place */
1630 size = AOP_SIZE(op) - 1;
1633 emitpcode(POC_XORLW, popGetLit(0x80));
1634 movwf(AOP(result), size);
1639 movwf(AOP(result), size);
1643 /*-----------------------------------------------------------------*/
1644 /* genUminus - unary minus code generation */
1645 /*-----------------------------------------------------------------*/
1646 static void genUminus (iCode *ic)
1649 sym_link *optype, *rtype;
1653 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1655 aopOp(IC_LEFT(ic),ic,FALSE);
1656 aopOp(IC_RESULT(ic),ic,TRUE);
1658 /* if both in bit space then special
1660 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1661 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1663 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0));
1664 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
1665 emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0));
1670 optype = operandType(IC_LEFT(ic));
1671 rtype = operandType(IC_RESULT(ic));
1673 /* if float then do float stuff */
1674 if (IS_FLOAT(optype)) {
1675 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1679 /* otherwise subtract from zero by taking the 2's complement */
1680 size = AOP_SIZE(IC_LEFT(ic));
1682 for(i=0; i<size; i++) {
1683 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
1684 emitpcode(POC_COMF, popGet(AOP(IC_LEFT(ic)),i));
1686 emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
1687 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
1691 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0));
1692 for(i=1; i<size; i++) {
1694 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),i));
1698 /* release the aops */
1699 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1700 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1703 /*-----------------------------------------------------------------*/
1704 /* saverbank - saves an entire register bank on the stack */
1705 /*-----------------------------------------------------------------*/
1706 static void saverbank (int bank, iCode *ic, bool pushPsw)
1710 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
1716 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1717 if (options.useXstack) {
1720 r = getFreePtr(ic,&aop,FALSE);
1721 pic14_emitcode("mov","%s,_spx",r->name);
1725 for (i = 0 ; i < pic14_nRegs ;i++) {
1726 if (options.useXstack) {
1727 pic14_emitcode("inc","%s",r->name);
1728 //pic14_emitcode("mov","a,(%s+%d)",
1729 // regspic14[i].base,8*bank+regspic14[i].offset);
1730 pic14_emitcode("movx","@%s,a",r->name);
1732 pic14_emitcode("push","");// "(%s+%d)",
1733 //regspic14[i].base,8*bank+regspic14[i].offset);
1737 if (options.useXstack) {
1738 pic14_emitcode("mov","a,psw");
1739 pic14_emitcode("movx","@%s,a",r->name);
1740 pic14_emitcode("inc","%s",r->name);
1741 pic14_emitcode("mov","_spx,%s",r->name);
1742 freeAsmop (NULL,aop,ic,TRUE);
1745 pic14_emitcode("push","psw");
1747 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1753 /*-----------------------------------------------------------------*/
1754 /* saveRegisters - will look for a call and save the registers */
1755 /*-----------------------------------------------------------------*/
1756 static void saveRegisters(iCode *lic)
1764 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1766 for (ic = lic ; ic ; ic = ic->next)
1767 if (ic->op == CALL || ic->op == PCALL)
1771 fprintf(stderr,"found parameter push with no function call\n");
1775 /* if the registers have been saved already then
1777 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
1780 /* find the registers in use at this time
1781 and push them away to safety */
1782 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1787 //fprintf(stderr, "ERROR: saveRegisters did not do anything to save registers, please report this as a bug.\n");
1789 dtype = operandType(IC_LEFT(ic));
1790 if (currFunc && dtype &&
1791 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
1792 IFFUNC_ISISR(currFunc->type) &&
1795 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
1798 /*-----------------------------------------------------------------*/
1799 /* unsaveRegisters - pop the pushed registers */
1800 /*-----------------------------------------------------------------*/
1801 static void unsaveRegisters (iCode *ic)
1808 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1809 /* find the registers in use at this time
1810 and push them away to safety */
1811 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1814 if (options.useXstack) {
1815 pic14_emitcode("mov","r0,%s",spname);
1816 for (i = pic14_nRegs ; i >= 0 ; i--) {
1817 if (bitVectBitValue(rsave,i)) {
1818 pic14_emitcode("dec","r0");
1819 pic14_emitcode("movx","a,@r0");
1820 pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
1824 pic14_emitcode("mov","%s,r0",spname);
1826 //for (i = pic14_nRegs ; i >= 0 ; i--) {
1827 // if (bitVectBitValue(rsave,i))
1828 // pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
1834 /*-----------------------------------------------------------------*/
1836 /*-----------------------------------------------------------------*/
1837 static void pushSide(operand * oper, int size)
1841 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1843 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1844 if (AOP_TYPE(oper) != AOP_REG &&
1845 AOP_TYPE(oper) != AOP_DIR &&
1847 pic14_emitcode("mov","a,%s",l);
1848 pic14_emitcode("push","acc");
1850 pic14_emitcode("push","%s",l);
1855 /*-----------------------------------------------------------------*/
1856 /* assignResultValue - */
1857 /*-----------------------------------------------------------------*/
1858 static void assignResultValue(operand * oper)
1860 int size = AOP_SIZE(oper);
1865 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1867 DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
1869 /* assign MSB first (passed via WREG) */
1871 get_returnvalue (oper, size, offset + GpsuedoStkPtr);
1877 /*-----------------------------------------------------------------*/
1878 /* genIpush - genrate code for pushing this gets a little complex */
1879 /*-----------------------------------------------------------------*/
1880 static void genIpush (iCode *ic)
1884 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
1886 int size, offset = 0 ;
1890 /* if this is not a parm push : ie. it is spill push
1891 and spill push is always done on the local stack */
1892 if (!ic->parmPush) {
1894 /* and the item is spilt then do nothing */
1895 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1898 aopOp(IC_LEFT(ic),ic,FALSE);
1899 size = AOP_SIZE(IC_LEFT(ic));
1900 /* push it on the stack */
1902 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1907 pic14_emitcode("push","%s",l);
1912 /* this is a paramter push: in this case we call
1913 the routine to find the call and save those
1914 registers that need to be saved */
1917 /* then do the push */
1918 aopOp(IC_LEFT(ic),ic,FALSE);
1921 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1922 size = AOP_SIZE(IC_LEFT(ic));
1925 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1926 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1927 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1929 pic14_emitcode("mov","a,%s",l);
1930 pic14_emitcode("push","acc");
1932 pic14_emitcode("push","%s",l);
1935 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1939 /*-----------------------------------------------------------------*/
1940 /* genIpop - recover the registers: can happen only for spilling */
1941 /*-----------------------------------------------------------------*/
1942 static void genIpop (iCode *ic)
1946 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
1947 assert (!"genIpop -- unimplemented");
1952 /* if the temp was not pushed then */
1953 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1956 aopOp(IC_LEFT(ic),ic,FALSE);
1957 size = AOP_SIZE(IC_LEFT(ic));
1960 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1963 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1967 /*-----------------------------------------------------------------*/
1968 /* unsaverbank - restores the resgister bank from stack */
1969 /*-----------------------------------------------------------------*/
1970 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1974 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
1980 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1982 if (options.useXstack) {
1984 r = getFreePtr(ic,&aop,FALSE);
1987 pic14_emitcode("mov","%s,_spx",r->name);
1988 pic14_emitcode("movx","a,@%s",r->name);
1989 pic14_emitcode("mov","psw,a");
1990 pic14_emitcode("dec","%s",r->name);
1993 pic14_emitcode ("pop","psw");
1996 for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
1997 if (options.useXstack) {
1998 pic14_emitcode("movx","a,@%s",r->name);
1999 //pic14_emitcode("mov","(%s+%d),a",
2000 // regspic14[i].base,8*bank+regspic14[i].offset);
2001 pic14_emitcode("dec","%s",r->name);
2004 pic14_emitcode("pop",""); //"(%s+%d)",
2005 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2008 if (options.useXstack) {
2010 pic14_emitcode("mov","_spx,%s",r->name);
2011 freeAsmop(NULL,aop,ic,TRUE);
2017 /*-----------------------------------------------------------------*/
2018 /* genCall - generates a call statement */
2019 /*-----------------------------------------------------------------*/
2020 static void genCall (iCode *ic)
2029 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2031 /* if caller saves & we have not saved then */
2035 /* if we are calling a function that is not using
2036 the same register bank then we need to save the
2037 destination registers on the stack */
2038 dtype = operandType(IC_LEFT(ic));
2039 if (currFunc && dtype &&
2040 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2041 IFFUNC_ISISR(currFunc->type) &&
2044 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2046 /* if send set is not empty the assign */
2049 /* For the Pic port, there is no data stack.
2050 * So parameters passed to functions are stored
2051 * in registers. (The pCode optimizer will get
2052 * rid of most of these :).
2054 int psuedoStkPtr=-1;
2055 int firstTimeThruLoop = 1;
2057 _G.sendSet = reverseSet(_G.sendSet);
2059 /* First figure how many parameters are getting passed */
2060 for (sic = setFirstItem(_G.sendSet) ; sic ;
2061 sic = setNextItem(_G.sendSet)) {
2063 aopOp(IC_LEFT(sic),sic,FALSE);
2064 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2065 freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2068 for (sic = setFirstItem(_G.sendSet) ; sic ;
2069 sic = setNextItem(_G.sendSet)) {
2070 int size, offset = 0;
2072 aopOp(IC_LEFT(sic),sic,FALSE);
2073 size = AOP_SIZE(IC_LEFT(sic));
2076 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2077 AopType(AOP_TYPE(IC_LEFT(sic))));
2079 if(!firstTimeThruLoop) {
2080 /* If this is not the first time we've been through the loop
2081 * then we need to save the parameter in a temporary
2082 * register. The last byte of the last parameter is
2084 emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2087 firstTimeThruLoop=0;
2089 mov2w_op (IC_LEFT(sic), offset);
2092 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2097 sym = OP_SYMBOL(IC_LEFT(ic));
2098 name = sym->rname[0] ? sym->rname : sym->name;
2100 * As SDCC emits code as soon as it reaches the end of each
2101 * function's definition, prototyped functions that are implemented
2102 * after the current one are always considered EXTERN, which
2103 * introduces many unneccessary PAGESEL instructions.
2104 * XXX: Use a post pass to iterate over all `CALL _name' statements
2105 * and insert `PAGESEL _name' and `PAGESEL $' around the CALL
2106 * only iff there is no definition of the function in the whole
2107 * file (might include this in the PAGESEL pass).
2109 isExtern = IS_EXTERN(sym->etype) || pic14_inISR;
2111 /* Extern functions and ISRs maybe on a different page;
2112 * must call pagesel */
2113 emitpcode(POC_PAGESEL,popGetWithString(name,1));
2115 emitpcode(POC_CALL,popGetWithString(name,isExtern));
2117 /* May have returned from a different page;
2118 * must use pagesel to restore PCLATH before next
2119 * goto or call instruction */
2120 emitpcode(POC_PAGESEL,popGetWithString("$",0));
2123 /* if we need assign a result value */
2124 if ((IS_ITEMP(IC_RESULT(ic)) &&
2125 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2126 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2127 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2130 aopOp(IC_RESULT(ic),ic,FALSE);
2133 assignResultValue(IC_RESULT(ic));
2135 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2136 AopType(AOP_TYPE(IC_RESULT(ic))));
2138 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2141 /* if register bank was saved then pop them */
2143 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2145 /* if we hade saved some registers then unsave them */
2146 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2147 unsaveRegisters (ic);
2152 /*-----------------------------------------------------------------*/
2153 /* genPcall - generates a call by pointer statement */
2154 /*-----------------------------------------------------------------*/
2155 static void genPcall (iCode *ic)
2158 symbol *albl = newiTempLabel(NULL);
2159 symbol *blbl = newiTempLabel(NULL);
2166 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2167 /* if caller saves & we have not saved then */
2171 /* if we are calling a function that is not using
2172 the same register bank then we need to save the
2173 destination registers on the stack */
2174 dtype = operandType(IC_LEFT(ic));
2175 if (currFunc && dtype &&
2176 IFFUNC_ISISR(currFunc->type) &&
2177 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2178 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2181 aopOp(left,ic,FALSE);
2182 DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2184 poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2186 pushSide(IC_LEFT(ic), FPTRSIZE);
2188 /* if send set is not empty, assign parameters */
2191 DEBUGpic14_emitcode ("; ***","%s %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2192 /* no way to pass args - W always gets used to make the call */
2194 /* first idea - factor out a common helper function and call it.
2195 But don't know how to get it generated only once in its own block
2197 if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2200 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2201 DEBUGpic14_emitcode ("; ***","%s %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2202 buffer = Safe_calloc(1,strlen(rname)+16);
2203 sprintf(buffer, "%s_goto_helper", rname);
2204 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2208 emitpcode(POC_CALL,popGetLabel(albl->key));
2209 pcop = popGetLabel(blbl->key);
2210 emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
2211 emitpcode(POC_GOTO,pcop);
2212 emitpLabel(albl->key);
2214 emitpcode(poc,popGetAddr(AOP(left),1,0));
2215 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2216 emitpcode(poc,popGetAddr(AOP(left),0,0));
2217 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2219 emitpLabel(blbl->key);
2221 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2223 /* if we need to assign a result value */
2224 if ((IS_ITEMP(IC_RESULT(ic)) &&
2225 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2226 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2227 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2230 aopOp(IC_RESULT(ic),ic,FALSE);
2235 assignResultValue(IC_RESULT(ic));
2237 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2240 /* if register bank was saved then unsave them */
2241 if (currFunc && dtype &&
2242 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2243 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2245 /* if we hade saved some registers then
2248 unsaveRegisters (ic);
2252 /*-----------------------------------------------------------------*/
2253 /* resultRemat - result is rematerializable */
2254 /*-----------------------------------------------------------------*/
2255 static int resultRemat (iCode *ic)
2257 // DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2260 if (SKIP_IC(ic) || ic->op == IFX)
2263 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2264 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2265 if (sym->remat && !POINTER_SET(ic))
2272 /*-----------------------------------------------------------------*/
2273 /* genFunction - generated code for function entry */
2274 /*-----------------------------------------------------------------*/
2275 static void genFunction (iCode *ic)
2282 DEBUGpic14_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2284 labelOffset += (max_key+4);
2288 /* create the function header */
2289 pic14_emitcode(";","-----------------------------------------");
2290 pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2291 pic14_emitcode(";","-----------------------------------------");
2293 /* prevent this symbol from being emitted as 'extern' */
2294 pic14_stringInSet(sym->rname, &pic14_localFunctions, 1);
2296 pic14_emitcode("","%s:",sym->rname);
2297 addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2299 /* mark symbol as NOT extern (even if it was declared so previously) */
2300 assert(IS_SPEC(sym->etype));
2301 SPEC_EXTR(sym->etype) = 0;
2303 if (!SPEC_OCLS(sym->etype)) SPEC_OCLS(sym->etype) = code;
2304 addSetIfnotP(&SPEC_OCLS(sym->etype)->syms, sym);
2306 ftype = operandType(IC_LEFT(ic));
2308 /* if critical function then turn interrupts off */
2309 if (IFFUNC_ISCRITICAL(ftype))
2310 pic14_emitcode("clr","ea");
2312 /* here we need to generate the equates for the
2313 register bank if required */
2315 if (FUNC_REGBANK(ftype) != rbank) {
2318 rbank = FUNC_REGBANK(ftype);
2319 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2320 if (strcmp(regspic14[i].base,"0") == 0)
2321 pic14_emitcode("","%s = 0x%02x",
2323 8*rbank+regspic14[i].offset);
2325 pic14_emitcode ("","%s = %s + 0x%02x",
2328 8*rbank+regspic14[i].offset);
2333 /* if this is an interrupt service routine */
2335 if (IFFUNC_ISISR(sym->type)) {
2337 emitpcode(POC_MOVWF, popCopyReg(&pc_wsave));
2338 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2339 /* XXX: Why? Does this assume that ssave and psave reside
2340 * in a shared bank or bank0? We cannot guarantee the
2343 emitpcode(POC_CLRF, popCopyReg(&pc_status));
2344 emitpcode(POC_MOVWF, popCopyReg(&pc_ssave));
2345 //emitpcode(POC_MOVWF, popGetExternal("___sdcc_saved_status",1 ));
2346 emitpcode(POC_MOVFW, popCopyReg(&pc_pclath));
2347 /* during an interrupt PCLATH must be cleared before a goto or call statement */
2348 emitpcode(POC_CLRF, popCopyReg(&pc_pclath));
2349 emitpcode(POC_MOVWF, popCopyReg(&pc_psave));
2350 //emitpcode(POC_MOVWF, popGetExternal("___sdcc_saved_pclath", 1));
2351 emitpcode(POC_MOVFW, popCopyReg(&pc_fsr));
2352 emitpcode(POC_MOVWF, popGetExternal("___sdcc_saved_fsr", 1));
2354 pBlockConvert2ISR(pb);
2355 pic14_hasInterrupt = 1;
2357 /* if callee-save to be used for this function
2358 then save the registers being used in this function */
2359 if (IFFUNC_CALLEESAVES(sym->type)) {
2362 /* if any registers used */
2363 if (sym->regsUsed) {
2364 /* save the registers used */
2365 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2366 if (bitVectBitValue(sym->regsUsed,i)) {
2367 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2375 /* set the register bank to the desired value */
2376 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2377 pic14_emitcode("push","psw");
2378 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);
2381 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2383 if (options.useXstack) {
2384 pic14_emitcode("mov","r0,%s",spname);
2385 pic14_emitcode("mov","a,_bp");
2386 pic14_emitcode("movx","@r0,a");
2387 pic14_emitcode("inc","%s",spname);
2391 /* set up the stack */
2392 pic14_emitcode ("push","_bp"); /* save the callers stack */
2394 pic14_emitcode ("mov","_bp,%s",spname);
2397 /* adjust the stack for the function */
2402 werror(W_STACK_OVERFLOW,sym->name);
2404 if (i > 3 && sym->recvSize < 4) {
2406 pic14_emitcode ("mov","a,sp");
2407 pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2408 pic14_emitcode ("mov","sp,a");
2413 pic14_emitcode("inc","sp");
2418 pic14_emitcode ("mov","a,_spx");
2419 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2420 pic14_emitcode ("mov","_spx,a");
2425 /*-----------------------------------------------------------------*/
2426 /* genEndFunction - generates epilogue for functions */
2427 /*-----------------------------------------------------------------*/
2428 static void genEndFunction (iCode *ic)
2430 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2434 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2436 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2438 pic14_emitcode ("mov","%s,_bp",spname);
2441 /* if use external stack but some variables were
2442 added to the local stack then decrement the
2444 if (options.useXstack && sym->stack) {
2445 pic14_emitcode("mov","a,sp");
2446 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2447 pic14_emitcode("mov","sp,a");
2451 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2452 if (options.useXstack) {
2453 pic14_emitcode("mov","r0,%s",spname);
2454 pic14_emitcode("movx","a,@r0");
2455 pic14_emitcode("mov","_bp,a");
2456 pic14_emitcode("dec","%s",spname);
2460 pic14_emitcode ("pop","_bp");
2464 /* restore the register bank */
2465 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2466 pic14_emitcode ("pop","psw");
2468 if (IFFUNC_ISISR(sym->type)) {
2470 /* now we need to restore the registers */
2471 /* if this isr has no bank i.e. is going to
2472 run with bank 0 , then we need to save more
2474 if (!FUNC_REGBANK(sym->type)) {
2476 /* if this function does not call any other
2477 function then we can be economical and
2478 save only those registers that are used */
2479 if (! IFFUNC_HASFCALL(sym->type)) {
2482 /* if any registers used */
2483 if (sym->regsUsed) {
2484 /* save the registers used */
2485 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2486 if (bitVectBitValue(sym->regsUsed,i)) {
2487 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2493 /* this function has a function call; cannot
2494 determines register usage so we will have the
2496 unsaverbank(0,ic,FALSE);
2500 /* if debug then send end of function */
2501 if (options.debug && debugFile && currFunc) {
2502 debugFile->writeEndFunction (currFunc, ic, 1);
2505 emitpcode(POC_MOVFW, popGetExternal("___sdcc_saved_fsr", 1));
2506 emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
2507 //emitpcode(POC_MOVFW, popGetExternal("___sdcc_saved_pclath", 1));
2508 emitpcode(POC_MOVFW, popCopyReg(&pc_psave));
2509 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
2510 emitpcode(POC_CLRF, popCopyReg(&pc_status)); // see genFunction
2511 //emitpcode(POC_SWAPFW, popGetExternal("___sdcc_saved_status", 1));
2512 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
2513 emitpcode(POC_MOVWF, popCopyReg(&pc_status));
2514 emitpcode(POC_SWAPF, popCopyReg(&pc_wsave));
2515 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
2516 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
2517 emitpcodeNULLop(POC_RETFIE);
2520 if (IFFUNC_ISCRITICAL(sym->type))
2521 pic14_emitcode("setb","ea");
2523 if (IFFUNC_CALLEESAVES(sym->type)) {
2526 /* if any registers used */
2527 if (sym->regsUsed) {
2528 /* save the registers used */
2529 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2530 if (bitVectBitValue(sym->regsUsed,i)) {
2531 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2537 /* if debug then send end of function */
2538 if (options.debug && debugFile && currFunc) {
2539 debugFile->writeEndFunction (currFunc, ic, 1);
2542 pic14_emitcode ("return","");
2543 emitpcodeNULLop(POC_RETURN);
2545 /* Mark the end of a function */
2546 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
2551 /*-----------------------------------------------------------------*/
2552 /* genRet - generate code for return statement */
2553 /*-----------------------------------------------------------------*/
2554 static void genRet (iCode *ic)
2556 int size,offset = 0;
2560 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2561 /* if we have no return value then
2562 just generate the "ret" */
2566 /* we have something to return then
2567 move the return value into place */
2568 aopOp(IC_LEFT(ic),ic,FALSE);
2569 size = AOP_SIZE(IC_LEFT(ic));
2571 for (offset = 0; offset < size; offset++)
2573 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
2576 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2579 /* generate a jump to the return label
2580 if the next is not the return statement */
2581 if (!(ic->next && ic->next->op == LABEL &&
2582 IC_LABEL(ic->next) == returnLabel)) {
2584 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
2589 /*-----------------------------------------------------------------*/
2590 /* genLabel - generates a label */
2591 /*-----------------------------------------------------------------*/
2592 static void genLabel (iCode *ic)
2596 /* special case never generate */
2597 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2598 if (IC_LABEL(ic) == entryLabel)
2601 emitpLabel(IC_LABEL(ic)->key);
2602 pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
2605 /*-----------------------------------------------------------------*/
2606 /* genGoto - generates a goto */
2607 /*-----------------------------------------------------------------*/
2609 static void genGoto (iCode *ic)
2613 emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
2614 pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
2618 /*-----------------------------------------------------------------*/
2619 /* genMultbits :- multiplication of bits */
2620 /*-----------------------------------------------------------------*/
2621 static void genMultbits (operand *left,
2626 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2628 if(!pic14_sameRegs(AOP(result),AOP(right)))
2629 emitpcode(POC_BSF, popGet(AOP(result),0));
2631 emitpcode(POC_BTFSC,popGet(AOP(right),0));
2632 emitpcode(POC_BTFSS,popGet(AOP(left),0));
2633 emitpcode(POC_BCF, popGet(AOP(result),0));
2638 /*-----------------------------------------------------------------*/
2639 /* genMultOneByte : 8 bit multiplication & division */
2640 /*-----------------------------------------------------------------*/
2641 static void genMultOneByte (operand *left,
2645 char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
2653 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2654 DEBUGpic14_AopType(__LINE__,left,right,result);
2655 DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
2657 /* (if two literals, the value is computed before) */
2658 /* if one literal, literal on the right */
2659 if (AOP_TYPE(left) == AOP_LIT){
2665 assert (AOP_SIZE(left) == AOP_SIZE(right));
2667 size = min(AOP_SIZE(result),AOP_SIZE(left));
2668 offset = Gstack_base_addr - (2*size - 1);
2670 /* pass right operand as argument */
2671 for (i=0; i < size; i++)
2673 mov2w (AOP(right), i);
2674 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
2677 /* pass left operand as argument */
2678 for (i=0; i < size; i++)
2680 mov2w (AOP(left), i);
2681 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
2683 assert (offset == Gstack_base_addr);
2685 /* call library routine */
2686 assert (size > 0 && size <= 4);
2687 call_libraryfunc (func[size]);
2690 movwf (AOP(result), size-1);
2691 for (i=0; i < size - 1; i++)
2693 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
2694 movwf (AOP(result), size - 2 - i);
2697 /* now (zero-/sign) extend the result to its size */
2698 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2701 /*-----------------------------------------------------------------*/
2702 /* genMult - generates code for multiplication */
2703 /*-----------------------------------------------------------------*/
2704 static void genMult (iCode *ic)
2706 operand *left = IC_LEFT(ic);
2707 operand *right = IC_RIGHT(ic);
2708 operand *result= IC_RESULT(ic);
2712 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2713 /* assign the amsops */
2714 aopOp (left,ic,FALSE);
2715 aopOp (right,ic,FALSE);
2716 aopOp (result,ic,TRUE);
2718 DEBUGpic14_AopType(__LINE__,left,right,result);
2720 /* special cases first */
2722 if (AOP_TYPE(left) == AOP_CRY &&
2723 AOP_TYPE(right)== AOP_CRY) {
2724 genMultbits(left,right,result);
2728 /* if both are of size == 1 */
2729 if (AOP_SIZE(left) == 1 &&
2730 AOP_SIZE(right) == 1 ) {
2731 genMultOneByte(left,right,result);
2735 /* should have been converted to function call */
2739 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2740 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2741 freeAsmop(result,NULL,ic,TRUE);
2744 /*-----------------------------------------------------------------*/
2745 /* genDivbits :- division of bits */
2746 /*-----------------------------------------------------------------*/
2747 static void genDivbits (operand *left,
2756 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2757 /* the result must be bit */
2758 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
2759 l = aopGet(AOP(left),0,FALSE,FALSE);
2763 pic14_emitcode("div","ab");
2764 pic14_emitcode("rrc","a");
2765 aopPut(AOP(result),"c",0);
2768 /*-----------------------------------------------------------------*/
2769 /* genDivOneByte : 8 bit division */
2770 /*-----------------------------------------------------------------*/
2771 static void genDivOneByte (operand *left,
2779 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2781 assert (AOP_SIZE(right) == 1);
2782 assert (AOP_SIZE(left) == 1);
2784 size = min(AOP_SIZE(result),AOP_SIZE(left));
2785 sign = !(SPEC_USIGN(operandType(left))
2786 && SPEC_USIGN(operandType(right)));
2788 if (AOP_TYPE(right) == AOP_LIT)
2790 /* XXX: might add specialized code */
2795 /* unsigned division */
2797 mov2w(AOP(right),0);
2798 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
2800 call_libraryfunc("__divuchar");
2801 movwf(AOP(result),0);
2806 temp = popGetTempReg();
2807 lbl = newiTempLabel(NULL);
2809 /* XXX: improve this naive approach:
2810 [result] = [a] / [b]
2811 ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
2815 movwf temp // temp <-- left
2816 movf right,W // W <-- right
2820 subwf temp,F // temp <-- temp - W
2821 skipNC // subwf clears CARRY (i.e. sets BORROW) if temp < W
2823 decf result // we just subtract once too often
2826 /* XXX: This loops endlessly on DIVIDE BY ZERO */
2827 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
2830 emitpcode(POC_MOVWF, temp);
2831 mov2w(AOP(right),0);
2832 emitpcode(POC_CLRF, popGet(AOP(result),0));
2834 emitpLabel(lbl->key);
2835 emitpcode(POC_INCF, popGet(AOP(result),0));
2836 emitpcode(POC_SUBWF, temp);
2838 emitpcode(POC_GOTO, popGetLabel(lbl->key));
2839 emitpcode(POC_DECF, popGet(AOP(result),0));
2840 popReleaseTempReg(temp);
2845 /* signed division */
2846 mov2w(AOP(right),0);
2847 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
2849 call_libraryfunc("__divschar");
2850 movwf(AOP(result),0);
2853 /* now performed the signed/unsigned division -- extend result */
2854 addSign(result, 1, sign);
2857 /*-----------------------------------------------------------------*/
2858 /* genDiv - generates code for division */
2859 /*-----------------------------------------------------------------*/
2860 static void genDiv (iCode *ic)
2862 operand *left = IC_LEFT(ic);
2863 operand *right = IC_RIGHT(ic);
2864 operand *result= IC_RESULT(ic);
2867 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2868 /* assign the amsops */
2869 aopOp (left,ic,FALSE);
2870 aopOp (right,ic,FALSE);
2871 aopOp (result,ic,TRUE);
2873 /* special cases first */
2875 if (AOP_TYPE(left) == AOP_CRY &&
2876 AOP_TYPE(right)== AOP_CRY) {
2877 genDivbits(left,right,result);
2881 /* if both are of size == 1 */
2882 if (AOP_SIZE(left) == 1 &&
2883 AOP_SIZE(right) == 1 ) {
2884 genDivOneByte(left,right,result);
2888 /* should have been converted to function call */
2891 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2892 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2893 freeAsmop(result,NULL,ic,TRUE);
2896 /*-----------------------------------------------------------------*/
2897 /* genModOneByte : 8 bit modulus */
2898 /*-----------------------------------------------------------------*/
2899 static void genModOneByte (operand *left,
2907 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2909 assert (AOP_SIZE(right) == 1);
2910 assert (AOP_SIZE(left) == 1);
2912 size = min(AOP_SIZE(result),AOP_SIZE(left));
2913 sign = !(SPEC_USIGN(operandType(left))
2914 && SPEC_USIGN(operandType(right)));
2916 if (AOP_TYPE(right) == AOP_LIT)
2918 /* XXX: might add specialized code */
2923 /* unsigned division */
2925 mov2w(AOP(right),0);
2926 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
2928 call_libraryfunc("__moduchar");
2929 movwf(AOP(result),0);
2934 lbl = newiTempLabel(NULL);
2936 assert(!pic14_sameRegs(AOP(right),AOP(result)));
2938 /* XXX: improve this naive approach:
2939 [result] = [a] % [b]
2940 ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
2944 movwf result // result <-- left
2945 movf right,W // W <-- right
2947 subwf result,F // result <-- result - W
2948 skipNC // subwf clears CARRY (i.e. sets BORROW) if result < W
2950 addwf result, F // we just subtract once too often
2953 /* XXX: This loops endlessly on DIVIDE BY ZERO */
2954 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
2956 if (!pic14_sameRegs(AOP(left), AOP(result)))
2959 emitpcode(POC_MOVWF, popGet(AOP(result),0));
2961 mov2w(AOP(right),0);
2963 emitpLabel(lbl->key);
2964 emitpcode(POC_SUBWF, popGet(AOP(result),0));
2966 emitpcode(POC_GOTO, popGetLabel(lbl->key));
2967 emitpcode(POC_ADDWF, popGet(AOP(result),0));
2972 /* signed division */
2973 mov2w(AOP(right),0);
2974 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
2976 call_libraryfunc("__modschar");
2977 movwf(AOP(result),0);
2980 /* now we performed the signed/unsigned modulus -- extend result */
2981 addSign(result, 1, sign);
2984 /*-----------------------------------------------------------------*/
2985 /* genMod - generates code for division */
2986 /*-----------------------------------------------------------------*/
2987 static void genMod (iCode *ic)
2989 operand *left = IC_LEFT(ic);
2990 operand *right = IC_RIGHT(ic);
2991 operand *result= IC_RESULT(ic);
2994 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2995 /* assign the amsops */
2996 aopOp (left,ic,FALSE);
2997 aopOp (right,ic,FALSE);
2998 aopOp (result,ic,TRUE);
3000 /* if both are of size == 1 */
3001 if (AOP_SIZE(left) == 1 &&
3002 AOP_SIZE(right) == 1 ) {
3003 genModOneByte(left,right,result);
3007 /* should have been converted to function call */
3011 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3012 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3013 freeAsmop(result,NULL,ic,TRUE);
3016 /*-----------------------------------------------------------------*/
3017 /* genIfxJump :- will create a jump depending on the ifx */
3018 /*-----------------------------------------------------------------*/
3020 note: May need to add parameter to indicate when a variable is in bit space.
3022 static void genIfxJump (iCode *ic, char *jval)
3026 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3027 /* if true label then we jump if condition
3029 if ( IC_TRUE(ic) ) {
3031 if(strcmp(jval,"a") == 0)
3033 else if (strcmp(jval,"c") == 0)
3036 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3037 emitpcode(POC_BTFSC, newpCodeOpBit(jval,-1,1));
3040 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3041 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3045 /* false label is present */
3046 if(strcmp(jval,"a") == 0)
3048 else if (strcmp(jval,"c") == 0)
3051 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3052 emitpcode(POC_BTFSS, newpCodeOpBit(jval,-1,1));
3055 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3056 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3061 /* mark the icode as generated */
3065 /*-----------------------------------------------------------------*/
3067 /*-----------------------------------------------------------------*/
3068 static void genSkipc(resolvedIfx *rifx)
3079 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3080 emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3081 rifx->generated = 1;
3084 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3085 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
3086 #define DEBUGpc emitpComment
3088 /*-----------------------------------------------------------------*/
3089 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
3090 /* aop (if it's NOT a literal) or from lit (if */
3091 /* aop is a literal) */
3092 /*-----------------------------------------------------------------*/
3093 static void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset)
3095 if (aop->type == AOP_LIT) {
3096 emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3098 emitpcode (POC_MOVFW, popGet (aop, offset));
3102 /* genCmp performs a left < right comparison, stores
3103 * the outcome in result (if != NULL) and generates
3104 * control flow code for the ifx (if != NULL).
3106 * This version leaves in sequences like
3107 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3108 * which should be optmized by the peephole
3109 * optimizer - RN 2005-01-01 */
3110 static void genCmp (operand *left,operand *right,
3111 operand *result, iCode *ifx, int sign)
3121 int invert_result = 0;
3125 assert (AOP_SIZE(left) == AOP_SIZE(right));
3126 assert (left && right);
3128 size = AOP_SIZE(right) - 1;
3129 mask = (0x100UL << (size*8)) - 1;
3130 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3135 resolveIfx (&rIfx, ifx);
3137 /**********************************************************************
3138 * handle bits - bit compares are promoted to int compares seemingly! *
3139 **********************************************************************/
3141 // THIS IS COMPLETELY UNTESTED!
3142 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3143 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3144 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3145 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3148 // 1 < {0,1} is false --> clear C by skipping the next instruction
3149 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3150 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3151 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3152 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3153 emitCLRC; // only skipped for left=0 && right=1
3155 goto correct_result_in_carry;
3159 /*************************************************
3160 * make sure that left is register (or the like) *
3161 *************************************************/
3162 if (!isAOP_REGlike(left)) {
3163 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
3164 assert (isAOP_LIT(left));
3165 assert (isAOP_REGlike(right));
3166 // swap left and right
3167 // left < right <==> right > left <==> (right >= left + 1)
3168 lit = ulFromVal(AOP(left)->aopu.aop_lit);
3170 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
3171 // MAXVALUE < right? always false
3172 if (performedLt) emitCLRC; else emitSETC;
3173 goto correct_result_in_carry;
3176 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
3177 // that's why we handled it above.
3184 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
3185 } else if (isAOP_LIT(right)) {
3186 lit = ulFromVal(AOP(right)->aopu.aop_lit);
3189 assert (isAOP_REGlike(left)); // left must be register or the like
3190 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
3192 /*************************************************
3193 * special cases go here *
3194 *************************************************/
3196 if (isAOP_LIT(right)) {
3198 // unsigned comparison to a literal
3199 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
3201 // unsigned left < 0? always false
3202 if (performedLt) emitCLRC; else emitSETC;
3203 goto correct_result_in_carry;
3206 // signed comparison to a literal
3207 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
3208 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
3209 // signed left < 0x80000000? always false
3210 if (performedLt) emitCLRC; else emitSETC;
3211 goto correct_result_in_carry;
3212 } else if (lit == 0) {
3213 // compare left < 0; set CARRY if SIGNBIT(left) is set
3214 if (performedLt) emitSETC; else emitCLRC;
3215 emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
3216 if (performedLt) emitCLRC; else emitSETC;
3217 goto correct_result_in_carry;
3220 } // right is literal
3222 /*************************************************
3223 * perform a general case comparison *
3224 * make sure we get CARRY==1 <==> left >= right *
3225 *************************************************/
3226 // compare most significant bytes
3227 //DEBUGpc ("comparing bytes at offset %d", size);
3229 // unsigned comparison
3230 pic14_mov2w_regOrLit (AOP(right), lit, size);
3231 emitpcode (POC_SUBFW, popGet (AOP(left), size));
3233 // signed comparison
3234 // (add 2^n to both operands then perform an unsigned comparison)
3235 if (isAOP_LIT(right)) {
3236 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
3237 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
3239 if (litbyte == 0x80) {
3240 // left >= 0x80 -- always true, but more bytes to come
3241 mov2w (AOP(left), size);
3242 emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
3245 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
3246 mov2w (AOP(left), size);
3247 emitpcode (POC_ADDLW, popGetLit (0x80));
3248 emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
3251 pCodeOp *pctemp = popGetTempReg();
3252 mov2w (AOP(left), size);
3253 emitpcode (POC_ADDLW, popGetLit (0x80));
3254 emitpcode (POC_MOVWF, pctemp);
3255 mov2w (AOP(right), size);
3256 emitpcode (POC_ADDLW, popGetLit (0x80));
3257 emitpcode (POC_SUBFW, pctemp);
3258 popReleaseTempReg(pctemp);
3262 // compare remaining bytes (treat as unsigned case from above)
3263 templbl = newiTempLabel ( NULL );
3266 //DEBUGpc ("comparing bytes at offset %d", offs);
3268 emitpcode (POC_GOTO, popGetLabel (templbl->key));
3269 pic14_mov2w_regOrLit (AOP(right), lit, offs);
3270 emitpcode (POC_SUBFW, popGet (AOP(left), offs));
3272 emitpLabel (templbl->key);
3273 goto result_in_carry;
3277 /****************************************************
3278 * now CARRY contains the result of the comparison: *
3279 * SUBWF sets CARRY iff *
3280 * F-W >= 0 <==> F >= W <==> !(F < W) *
3281 * (F=left, W=right) *
3282 ****************************************************/
3286 // value will be used in the following genSkipc()
3287 rIfx.condition ^= 1;
3290 correct_result_in_carry:
3292 // assign result to variable (if neccessary)
3293 if (result && AOP_TYPE(result) != AOP_CRY) {
3294 //DEBUGpc ("assign result");
3295 size = AOP_SIZE(result);
3297 emitpcode (POC_CLRF, popGet (AOP(result), size));
3299 if (invert_result) {
3301 emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
3303 emitpcode (POC_RLF, popGet (AOP(result), 0));
3307 // perform conditional jump
3309 //DEBUGpc ("generate control flow");
3315 /*-----------------------------------------------------------------*/
3316 /* genCmpGt :- greater than comparison */
3317 /*-----------------------------------------------------------------*/
3318 static void genCmpGt (iCode *ic, iCode *ifx)
3320 operand *left, *right, *result;
3321 sym_link *letype , *retype;
3325 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3327 right= IC_RIGHT(ic);
3328 result = IC_RESULT(ic);
3330 letype = getSpec(operandType(left));
3331 retype =getSpec(operandType(right));
3332 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3333 /* assign the amsops */
3334 aopOp (left,ic,FALSE);
3335 aopOp (right,ic,FALSE);
3336 aopOp (result,ic,TRUE);
3338 genCmp(right, left, result, ifx, sign);
3340 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3341 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3342 freeAsmop(result,NULL,ic,TRUE);
3345 /*-----------------------------------------------------------------*/
3346 /* genCmpLt - less than comparisons */
3347 /*-----------------------------------------------------------------*/
3348 static void genCmpLt (iCode *ic, iCode *ifx)
3350 operand *left, *right, *result;
3351 sym_link *letype , *retype;
3355 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3357 right= IC_RIGHT(ic);
3358 result = IC_RESULT(ic);
3360 letype = getSpec(operandType(left));
3361 retype =getSpec(operandType(right));
3362 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3364 /* assign the amsops */
3365 aopOp (left,ic,FALSE);
3366 aopOp (right,ic,FALSE);
3367 aopOp (result,ic,TRUE);
3369 genCmp(left, right, result, ifx, sign);
3371 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3372 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3373 freeAsmop(result,NULL,ic,TRUE);
3376 /*-----------------------------------------------------------------*/
3377 /* genCmpEq - generates code for equal to */
3378 /*-----------------------------------------------------------------*/
3379 static void genCmpEq (iCode *ic, iCode *ifx)
3381 operand *left, *right, *result;
3383 symbol *false_label;
3386 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3389 DEBUGpic14_emitcode ("; ifx is non-null","");
3391 DEBUGpic14_emitcode ("; ifx is null","");
3393 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3394 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3395 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3397 DEBUGpic14_AopType(__LINE__,left,right,result);
3399 /* if literal, move literal to right */
3400 if (op_isLitLike (IC_LEFT(ic))) {
3401 operand *tmp = right ;
3407 if (ifx && !IC_TRUE(ifx))
3409 assert (IC_FALSE(ifx));
3410 false_label = IC_FALSE(ifx);
3413 size = min(AOP_SIZE(left),AOP_SIZE(right));
3414 assert(!pic14_sameRegs(AOP(result),AOP(left)));
3415 assert(!pic14_sameRegs(AOP(result),AOP(right)));
3417 /* assume left != right */
3420 for (i=0; i < AOP_SIZE(result); i++)
3422 emitpcode(POC_CLRF, popGet(AOP(result),i));
3426 if (AOP_TYPE(right) == AOP_LIT)
3428 unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit);
3430 size = AOP_SIZE(left);
3431 assert(!op_isLitLike(left));
3436 mov2w(AOP(left), 0);
3437 for (i=1; i < size; i++)
3438 emitpcode(POC_IORFW,popGet(AOP(left),i));
3439 /* now Z is set iff `left == right' */
3441 if (!false_label) false_label = newiTempLabel(NULL);
3442 emitpcode(POC_GOTO, popGetLabel(false_label->key));
3446 for (i=0; i < size; i++)
3449 emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
3450 /* now Z is cleared if `left != right' */
3452 if (!false_label) false_label = newiTempLabel(NULL);
3453 emitpcode(POC_GOTO, popGetLabel(false_label->key));
3460 /* right is no literal */
3463 for (i=0; i < size; i++)
3465 mov2w(AOP(right),i);
3466 emitpcode(POC_XORFW,popGet(AOP(left),i));
3467 /* now Z is cleared if `left != right' */
3469 if (!false_label) false_label = newiTempLabel(NULL);
3470 emitpcode(POC_GOTO, popGetLabel(false_label->key));
3474 /* if we reach here, left == right */
3476 if (AOP_SIZE(result) > 0)
3478 emitpcode(POC_INCF, popGet(AOP(result),0));
3481 if (ifx && IC_TRUE(ifx))
3483 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3486 if (false_label && (!ifx || IC_TRUE(ifx)))
3487 emitpLabel(false_label->key);
3489 if (ifx) ifx->generated = 1;
3491 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3492 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3493 freeAsmop(result,NULL,ic,TRUE);
3496 /*-----------------------------------------------------------------*/
3497 /* ifxForOp - returns the icode containing the ifx for operand */
3498 /*-----------------------------------------------------------------*/
3499 static iCode *ifxForOp ( operand *op, iCode *ic )
3502 /* if true symbol then needs to be assigned */
3503 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3504 if (IS_TRUE_SYMOP(op))
3507 /* if this has register type condition and
3508 the next instruction is ifx with the same operand
3509 and live to of the operand is upto the ifx only then */
3511 ic->next->op == IFX &&
3512 IC_COND(ic->next)->key == op->key &&
3513 OP_SYMBOL(op)->liveTo <= ic->next->seq )
3517 ic->next->op == IFX &&
3518 IC_COND(ic->next)->key == op->key) {
3519 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
3523 DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
3525 ic->next->op == IFX)
3526 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
3529 ic->next->op == IFX &&
3530 IC_COND(ic->next)->key == op->key) {
3531 DEBUGpic14_emitcode ("; "," key is okay");
3532 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
3533 OP_SYMBOL(op)->liveTo,
3540 /*-----------------------------------------------------------------*/
3541 /* genAndOp - for && operation */
3542 /*-----------------------------------------------------------------*/
3543 static void genAndOp (iCode *ic)
3545 operand *left,*right, *result;
3549 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3550 /* note here that && operations that are in an
3551 if statement are taken away by backPatchLabels
3552 only those used in arthmetic operations remain */
3553 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3554 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3555 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3557 DEBUGpic14_AopType(__LINE__,left,right,result);
3559 emitpcode(POC_MOVFW,popGet(AOP(left),0));
3560 emitpcode(POC_ANDFW,popGet(AOP(right),0));
3561 emitpcode(POC_MOVWF,popGet(AOP(result),0));
3563 /* if both are bit variables */
3564 /* if (AOP_TYPE(left) == AOP_CRY && */
3565 /* AOP_TYPE(right) == AOP_CRY ) { */
3566 /* pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
3567 /* pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
3568 /* pic14_outBitC(result); */
3570 /* tlbl = newiTempLabel(NULL); */
3571 /* pic14_toBoolean(left); */
3572 /* pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
3573 /* pic14_toBoolean(right); */
3574 /* pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
3575 /* pic14_outBitAcc(result); */
3578 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3579 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3580 freeAsmop(result,NULL,ic,TRUE);
3584 /*-----------------------------------------------------------------*/
3585 /* genOrOp - for || operation */
3586 /*-----------------------------------------------------------------*/
3589 modified this code, but it doesn't appear to ever get called
3592 static void genOrOp (iCode *ic)
3594 operand *left,*right, *result;
3598 /* note here that || operations that are in an
3599 if statement are taken away by backPatchLabels
3600 only those used in arthmetic operations remain */
3602 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3603 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3604 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3605 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3607 DEBUGpic14_AopType(__LINE__,left,right,result);
3609 for (i=0; i < AOP_SIZE(result); i++)
3611 emitpcode(POC_CLRF, popGet(AOP(result), i));
3614 tlbl = newiTempLabel(NULL);
3615 pic14_toBoolean(left);
3617 emitpcode(POC_GOTO, popGetLabel(tlbl->key));
3618 pic14_toBoolean(right);
3619 emitpLabel(tlbl->key);
3620 /* here Z is clear IFF `left || right' */
3622 emitpcode(POC_INCF, popGet(AOP(result), 0));
3624 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3625 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3626 freeAsmop(result,NULL,ic,TRUE);
3629 /*-----------------------------------------------------------------*/
3630 /* isLiteralBit - test if lit == 2^n */
3631 /*-----------------------------------------------------------------*/
3632 static int isLiteralBit(unsigned long lit)
3634 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
3635 0x100L,0x200L,0x400L,0x800L,
3636 0x1000L,0x2000L,0x4000L,0x8000L,
3637 0x10000L,0x20000L,0x40000L,0x80000L,
3638 0x100000L,0x200000L,0x400000L,0x800000L,
3639 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
3640 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
3644 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3645 for(idx = 0; idx < 32; idx++)
3651 /*-----------------------------------------------------------------*/
3652 /* continueIfTrue - */
3653 /*-----------------------------------------------------------------*/
3654 static void continueIfTrue (iCode *ic)
3657 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3661 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
3662 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
3667 /*-----------------------------------------------------------------*/
3669 /*-----------------------------------------------------------------*/
3670 static void jumpIfTrue (iCode *ic)
3673 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3677 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
3678 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
3683 /*-----------------------------------------------------------------*/
3684 /* jmpTrueOrFalse - */
3685 /*-----------------------------------------------------------------*/
3686 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
3689 // ugly but optimized by peephole
3690 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3692 symbol *nlbl = newiTempLabel(NULL);
3693 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);
3694 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
3695 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
3696 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
3699 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
3700 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
3705 /*-----------------------------------------------------------------*/
3706 /* genAnd - code for and */
3707 /*-----------------------------------------------------------------*/
3708 static void genAnd (iCode *ic, iCode *ifx)
3710 operand *left, *right, *result;
3712 unsigned long lit = 0L;
3717 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3718 aopOp((left = IC_LEFT(ic)),ic,FALSE);
3719 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
3720 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3722 resolveIfx(&rIfx,ifx);
3724 /* if left is a literal & right is not then exchange them */
3725 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3726 AOP_NEEDSACC(left)) {
3727 operand *tmp = right ;
3732 /* if result = right then exchange them */
3733 if(pic14_sameRegs(AOP(result),AOP(right))){
3734 operand *tmp = right ;
3739 /* if right is bit then exchange them */
3740 if (AOP_TYPE(right) == AOP_CRY &&
3741 AOP_TYPE(left) != AOP_CRY){
3742 operand *tmp = right ;
3746 if(AOP_TYPE(right) == AOP_LIT)
3747 lit = ulFromVal (AOP(right)->aopu.aop_lit);
3749 size = AOP_SIZE(result);
3751 DEBUGpic14_AopType(__LINE__,left,right,result);
3754 // result = bit & yy;
3755 if (AOP_TYPE(left) == AOP_CRY){
3756 // c = bit & literal;
3757 if(AOP_TYPE(right) == AOP_LIT){
3759 if(size && pic14_sameRegs(AOP(result),AOP(left)))
3762 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3765 if(size && (AOP_TYPE(result) == AOP_CRY)){
3766 pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
3769 if((AOP_TYPE(result) == AOP_CRY) && ifx){
3773 pic14_emitcode("clr","c");
3776 if (AOP_TYPE(right) == AOP_CRY){
3778 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3779 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3782 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
3784 pic14_emitcode("rrc","a");
3785 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3791 pic14_outBitC(result);
3793 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
3794 genIfxJump(ifx, "c");
3798 // if(val & 0xZZ) - size = 0, ifx != FALSE -
3799 // bit = val & 0xZZ - size = 1, ifx = FALSE -
3800 if((AOP_TYPE(right) == AOP_LIT) &&
3801 (AOP_TYPE(result) == AOP_CRY) &&
3802 (AOP_TYPE(left) != AOP_CRY)){
3803 int posbit = isLiteralBit(lit);
3807 //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
3810 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
3815 while (posbit > 7) {
3819 emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
3820 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
3821 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
3828 symbol *tlbl = newiTempLabel(NULL);
3829 int sizel = AOP_SIZE(left);
3831 pic14_emitcode("setb","c");
3833 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
3834 mov2w( AOP(left), offset);
3836 if((posbit = isLiteralBit(bytelit)) != 0) {
3837 emitpcode(rIfx.condition ? POC_BTFSC : POC_BTFSS, // XXX: or the other way round?
3838 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit - 1, 0));
3839 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
3842 emitpcode(POC_ANDLW, newpCodeOpLit(bytelit & 0x0ff));
3843 if (rIfx.condition) emitSKPZ;
3846 if(bytelit != 0x0FFL)
3848 pic14_emitcode("anl","a,%s",
3849 aopGet(AOP(right),offset,FALSE,TRUE));
3851 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
3854 emitpcode(POC_GOTO, popGetLabel(rIfx.lbl->key));
3860 // bit = left & literal
3862 pic14_emitcode("clr","c");
3863 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
3865 // if(left & literal)
3868 jmpTrueOrFalse(ifx, tlbl);
3872 pic14_outBitC(result);
3876 /* if left is same as result */
3877 if(pic14_sameRegs(AOP(result),AOP(left))){
3879 for(;size--; offset++,lit>>=8) {
3880 if(AOP_TYPE(right) == AOP_LIT){
3881 switch(lit & 0xff) {
3883 /* and'ing with 0 has clears the result */
3884 emitpcode(POC_CLRF,popGet(AOP(result),offset));
3887 /* and'ing with 0xff is a nop when the result and left are the same */
3892 int p = my_powof2( (~lit) & 0xff );
3894 /* only one bit is set in the literal, so use a bcf instruction */
3895 emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
3898 if(know_W != (int)(lit&0xff))
3899 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
3901 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
3906 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
3907 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
3912 // left & result in different registers
3913 if(AOP_TYPE(result) == AOP_CRY){
3915 // if(size), result in bit
3916 // if(!size && ifx), conditional oper: if(left & right)
3917 symbol *tlbl = newiTempLabel(NULL);
3918 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
3920 pic14_emitcode("setb","c");
3922 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3923 pic14_emitcode("anl","a,%s",
3924 aopGet(AOP(left),offset,FALSE,FALSE));
3925 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
3930 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
3931 pic14_outBitC(result);
3933 jmpTrueOrFalse(ifx, tlbl);
3935 for(;(size--);offset++) {
3937 // result = left & right
3938 if(AOP_TYPE(right) == AOP_LIT){
3939 int t = (lit >> (offset*8)) & 0x0FFL;
3942 emitpcode(POC_CLRF,popGet(AOP(result),offset));
3945 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
3946 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
3949 emitpcode(POC_MOVLW, popGetLit(t));
3950 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
3951 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
3956 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
3957 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
3958 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
3964 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3965 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3966 freeAsmop(result,NULL,ic,TRUE);
3969 /*-----------------------------------------------------------------*/
3970 /* genOr - code for or */
3971 /*-----------------------------------------------------------------*/
3972 static void genOr (iCode *ic, iCode *ifx)
3974 operand *left, *right, *result;
3976 unsigned long lit = 0L;
3979 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3981 aopOp((left = IC_LEFT(ic)),ic,FALSE);
3982 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
3983 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3985 DEBUGpic14_AopType(__LINE__,left,right,result);
3987 /* if left is a literal & right is not then exchange them */
3988 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3989 AOP_NEEDSACC(left)) {
3990 operand *tmp = right ;
3995 /* if result = right then exchange them */
3996 if(pic14_sameRegs(AOP(result),AOP(right))){
3997 operand *tmp = right ;
4002 /* if right is bit then exchange them */
4003 if (AOP_TYPE(right) == AOP_CRY &&
4004 AOP_TYPE(left) != AOP_CRY){
4005 operand *tmp = right ;
4010 DEBUGpic14_AopType(__LINE__,left,right,result);
4012 if(AOP_TYPE(right) == AOP_LIT)
4013 lit = ulFromVal (AOP(right)->aopu.aop_lit);
4015 size = AOP_SIZE(result);
4019 if (AOP_TYPE(left) == AOP_CRY){
4020 if(AOP_TYPE(right) == AOP_LIT){
4021 // c = bit & literal;
4023 // lit != 0 => result = 1
4024 if(AOP_TYPE(result) == AOP_CRY){
4026 emitpcode(POC_BSF, popGet(AOP(result),0));
4027 //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
4028 // AOP(result)->aopu.aop_dir,
4029 // AOP(result)->aopu.aop_dir);
4031 continueIfTrue(ifx);
4035 // lit == 0 => result = left
4036 if(size && pic14_sameRegs(AOP(result),AOP(left)))
4038 pic14_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
4041 if (AOP_TYPE(right) == AOP_CRY){
4042 if(pic14_sameRegs(AOP(result),AOP(left))){
4044 emitpcode(POC_BCF, popGet(AOP(result),0));
4045 emitpcode(POC_BTFSC, popGet(AOP(right),0));
4046 emitpcode(POC_BSF, popGet(AOP(result),0));
4048 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
4049 AOP(result)->aopu.aop_dir,
4050 AOP(result)->aopu.aop_dir);
4051 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
4052 AOP(right)->aopu.aop_dir,
4053 AOP(right)->aopu.aop_dir);
4054 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
4055 AOP(result)->aopu.aop_dir,
4056 AOP(result)->aopu.aop_dir);
4058 emitpcode(POC_BCF, popGet(AOP(result),0));
4059 emitpcode(POC_BTFSS, popGet(AOP(right),0));
4060 emitpcode(POC_BTFSC, popGet(AOP(left),0));
4061 emitpcode(POC_BSF, popGet(AOP(result),0));
4065 symbol *tlbl = newiTempLabel(NULL);
4066 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4069 emitpcode(POC_BCF, popGet(AOP(result),0));
4071 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4072 pic14_emitcode(";XXX setb","c");
4073 pic14_emitcode(";XXX jb","%s,%05d_DS_",
4074 AOP(left)->aopu.aop_dir,tlbl->key+100);
4075 pic14_toBoolean(right);
4076 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
4077 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4078 jmpTrueOrFalse(ifx, tlbl);
4082 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4089 pic14_outBitC(result);
4091 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4092 genIfxJump(ifx, "c");
4096 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4097 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4098 if((AOP_TYPE(right) == AOP_LIT) &&
4099 (AOP_TYPE(result) == AOP_CRY) &&
4100 (AOP_TYPE(left) != AOP_CRY)){
4102 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4105 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
4107 continueIfTrue(ifx);
4110 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4111 // lit = 0, result = boolean(left)
4113 pic14_emitcode(";XXX setb","c");
4114 pic14_toBoolean(right);
4116 symbol *tlbl = newiTempLabel(NULL);
4117 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
4119 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4121 genIfxJump (ifx,"a");
4125 pic14_outBitC(result);
4129 /* if left is same as result */
4130 if(pic14_sameRegs(AOP(result),AOP(left))){
4132 for(;size--; offset++,lit>>=8) {
4133 if(AOP_TYPE(right) == AOP_LIT){
4134 if((lit & 0xff) == 0)
4135 /* or'ing with 0 has no effect */
4138 int p = my_powof2(lit & 0xff);
4140 /* only one bit is set in the literal, so use a bsf instruction */
4142 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
4144 if(know_W != (int)(lit & 0xff))
4145 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
4146 know_W = lit & 0xff;
4147 emitpcode(POC_IORWF, popGet(AOP(left),offset));
4152 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
4153 emitpcode(POC_IORWF, popGet(AOP(left),offset));
4157 // left & result in different registers
4158 if(AOP_TYPE(result) == AOP_CRY){
4160 // if(size), result in bit
4161 // if(!size && ifx), conditional oper: if(left | right)
4162 symbol *tlbl = newiTempLabel(NULL);
4163 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4164 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4168 pic14_emitcode(";XXX setb","c");
4170 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4171 pic14_emitcode(";XXX orl","a,%s",
4172 aopGet(AOP(left),offset,FALSE,FALSE));
4173 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
4178 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4179 pic14_outBitC(result);
4181 jmpTrueOrFalse(ifx, tlbl);
4182 } else for(;(size--);offset++){
4184 // result = left | right
4185 if(AOP_TYPE(right) == AOP_LIT){
4186 int t = (lit >> (offset*8)) & 0x0FFL;
4189 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
4190 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
4194 emitpcode(POC_MOVLW, popGetLit(t));
4195 emitpcode(POC_IORFW, popGet(AOP(left),offset));
4196 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
4201 // faster than result <- left, anl result,right
4202 // and better if result is SFR
4203 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
4204 emitpcode(POC_IORFW,popGet(AOP(left),offset));
4205 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
4210 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4211 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4212 freeAsmop(result,NULL,ic,TRUE);
4215 /*-----------------------------------------------------------------*/
4216 /* genXor - code for xclusive or */
4217 /*-----------------------------------------------------------------*/
4218 static void genXor (iCode *ic, iCode *ifx)
4220 operand *left, *right, *result;
4222 unsigned long lit = 0L;
4225 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4227 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4228 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4229 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4231 /* if left is a literal & right is not ||
4232 if left needs acc & right does not */
4233 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4234 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4235 operand *tmp = right ;
4240 /* if result = right then exchange them */
4241 if(pic14_sameRegs(AOP(result),AOP(right))){
4242 operand *tmp = right ;
4247 /* if right is bit then exchange them */
4248 if (AOP_TYPE(right) == AOP_CRY &&
4249 AOP_TYPE(left) != AOP_CRY){
4250 operand *tmp = right ;
4254 if(AOP_TYPE(right) == AOP_LIT)
4255 lit = ulFromVal (AOP(right)->aopu.aop_lit);
4257 size = AOP_SIZE(result);
4261 if (AOP_TYPE(left) == AOP_CRY){
4262 if(AOP_TYPE(right) == AOP_LIT){
4263 // c = bit & literal;
4265 // lit>>1 != 0 => result = 1
4266 if(AOP_TYPE(result) == AOP_CRY){
4268 {emitpcode(POC_BSF, popGet(AOP(result),offset));
4269 pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
4271 continueIfTrue(ifx);
4274 pic14_emitcode("setb","c");
4278 // lit == 0, result = left
4279 if(size && pic14_sameRegs(AOP(result),AOP(left)))
4281 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4283 // lit == 1, result = not(left)
4284 if(size && pic14_sameRegs(AOP(result),AOP(left))){
4285 emitpcode(POC_MOVLW, popGet(AOP(result),offset));
4286 emitpcode(POC_XORWF, popGet(AOP(result),offset));
4287 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4290 assert ( !"incomplete genXor" );
4291 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4292 pic14_emitcode("cpl","c");
4299 symbol *tlbl = newiTempLabel(NULL);
4300 if (AOP_TYPE(right) == AOP_CRY){
4302 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4305 int sizer = AOP_SIZE(right);
4307 // if val>>1 != 0, result = 1
4308 pic14_emitcode("setb","c");
4310 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
4312 // test the msb of the lsb
4313 pic14_emitcode("anl","a,#0xfe");
4314 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
4318 pic14_emitcode("rrc","a");
4320 pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4321 pic14_emitcode("cpl","c");
4322 pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
4327 pic14_outBitC(result);
4329 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4330 genIfxJump(ifx, "c");
4334 if(pic14_sameRegs(AOP(result),AOP(left))){
4335 /* if left is same as result */
4336 for(;size--; offset++) {
4337 if(AOP_TYPE(right) == AOP_LIT){
4338 int t = (lit >> (offset*8)) & 0x0FFL;
4342 emitpcode(POC_MOVLW, popGetLit(t));
4343 emitpcode(POC_XORWF,popGet(AOP(left),offset));
4346 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
4347 emitpcode(POC_XORWF,popGet(AOP(left),offset));
4351 // left & result in different registers
4352 if(AOP_TYPE(result) == AOP_CRY){
4354 // if(size), result in bit
4355 // if(!size && ifx), conditional oper: if(left ^ right)
4356 symbol *tlbl = newiTempLabel(NULL);
4357 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4359 pic14_emitcode("setb","c");
4361 if((AOP_TYPE(right) == AOP_LIT) &&
4362 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4363 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4365 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4366 pic14_emitcode("xrl","a,%s",
4367 aopGet(AOP(left),offset,FALSE,FALSE));
4369 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
4374 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4375 pic14_outBitC(result);
4377 jmpTrueOrFalse(ifx, tlbl);
4378 } else for(;(size--);offset++){
4380 // result = left & right
4381 if(AOP_TYPE(right) == AOP_LIT){
4382 int t = (lit >> (offset*8)) & 0x0FFL;
4385 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4386 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
4389 emitpcode(POC_COMFW,popGet(AOP(left),offset));
4390 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
4393 emitpcode(POC_MOVLW, popGetLit(t));
4394 emitpcode(POC_XORFW,popGet(AOP(left),offset));
4395 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
4400 // faster than result <- left, anl result,right
4401 // and better if result is SFR
4402 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
4403 emitpcode(POC_XORFW,popGet(AOP(left),offset));
4404 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
4409 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4410 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4411 freeAsmop(result,NULL,ic,TRUE);
4414 /*-----------------------------------------------------------------*/
4415 /* genInline - write the inline code out */
4416 /*-----------------------------------------------------------------*/
4417 static void genInline (iCode *ic)
4419 char *buffer, *bp, *bp1;
4420 bool inComment = FALSE;
4423 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4425 _G.inLine += (!options.asmpeep);
4427 buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
4442 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
4447 /* Add \n for labels, not dirs such as c:\mydir */
4448 if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
4453 /* print label, use this special format with NULL directive
4454 * to denote that the argument should not be indented with tab */
4455 addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
4463 if ((bp1 != bp) && *bp1)
4464 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
4468 _G.inLine -= (!options.asmpeep);
4471 /*-----------------------------------------------------------------*/
4472 /* genRRC - rotate right with carry */
4473 /*-----------------------------------------------------------------*/
4474 static void genRRC (iCode *ic)
4476 operand *left , *result ;
4477 int size, offset = 0, same;
4480 /* rotate right with carry */
4482 result=IC_RESULT(ic);
4483 aopOp (left,ic,FALSE);
4484 aopOp (result,ic,FALSE);
4486 DEBUGpic14_AopType(__LINE__,left,NULL,result);
4488 same = pic14_sameRegs(AOP(result),AOP(left));
4490 size = AOP_SIZE(result);
4492 /* get the lsb and put it into the carry */
4493 emitpcode(POC_RRFW, popGet(AOP(left),size-1));
4500 emitpcode(POC_RRF, popGet(AOP(left),offset));
4502 emitpcode(POC_RRFW, popGet(AOP(left),offset));
4503 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
4509 freeAsmop(left,NULL,ic,TRUE);
4510 freeAsmop(result,NULL,ic,TRUE);
4513 /*-----------------------------------------------------------------*/
4514 /* genRLC - generate code for rotate left with carry */
4515 /*-----------------------------------------------------------------*/
4516 static void genRLC (iCode *ic)
4518 operand *left , *result ;
4519 int size, offset = 0;
4523 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4524 /* rotate right with carry */
4526 result=IC_RESULT(ic);
4527 aopOp (left,ic,FALSE);
4528 aopOp (result,ic,FALSE);
4530 DEBUGpic14_AopType(__LINE__,left,NULL,result);
4532 same = pic14_sameRegs(AOP(result),AOP(left));
4534 /* move it to the result */
4535 size = AOP_SIZE(result);
4537 /* get the msb and put it into the carry */
4538 emitpcode(POC_RLFW, popGet(AOP(left),size-1));
4545 emitpcode(POC_RLF, popGet(AOP(left),offset));
4547 emitpcode(POC_RLFW, popGet(AOP(left),offset));
4548 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
4555 freeAsmop(left,NULL,ic,TRUE);
4556 freeAsmop(result,NULL,ic,TRUE);
4559 /*-----------------------------------------------------------------*/
4560 /* genGetHbit - generates code get highest order bit */
4561 /*-----------------------------------------------------------------*/
4562 static void genGetHbit (iCode *ic)
4564 operand *left, *result;
4566 result=IC_RESULT(ic);
4567 aopOp (left,ic,FALSE);
4568 aopOp (result,ic,FALSE);
4571 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4572 /* get the highest order byte into a */
4573 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
4574 if(AOP_TYPE(result) == AOP_CRY){
4575 pic14_emitcode("rlc","a");
4576 pic14_outBitC(result);
4579 pic14_emitcode("rl","a");
4580 pic14_emitcode("anl","a,#0x01");
4581 pic14_outAcc(result);
4585 freeAsmop(left,NULL,ic,TRUE);
4586 freeAsmop(result,NULL,ic,TRUE);
4589 /*-----------------------------------------------------------------*/
4590 /* AccLsh - shift left accumulator by known count */
4591 /* MARK: pic14 always rotates through CARRY! */
4592 /*-----------------------------------------------------------------*/
4593 static void AccLsh (pCodeOp *pcop,int shCount)
4596 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4597 shCount &= 0x0007; // shCount : 0..7
4604 emitpcode(POC_RLF,pcop);
4608 emitpcode(POC_RLF,pcop);
4609 emitpcode(POC_RLF,pcop);
4612 emitpcode(POC_RLF,pcop);
4613 emitpcode(POC_RLF,pcop);
4614 emitpcode(POC_RLF,pcop);
4617 emitpcode(POC_SWAPF,pcop);
4620 emitpcode(POC_SWAPF,pcop);
4621 emitpcode(POC_RLF,pcop);
4624 emitpcode(POC_SWAPF,pcop);
4625 emitpcode(POC_RLF,pcop);
4626 emitpcode(POC_RLF,pcop);
4629 emitpcode(POC_RRFW,pcop);
4630 emitpcode(POC_RRF,pcop);
4633 /* clear invalid bits */
4634 emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
4635 emitpcode(POC_ANDWF, pcop);
4638 /*-----------------------------------------------------------------*/
4639 /* AccRsh - shift right accumulator by known count */
4640 /* MARK: pic14 always rotates through CARRY! */
4641 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
4642 /* 1: mask out invalid bits (zero-extend) */
4643 /* 2: sign-extend result (pretty slow) */
4644 /*-----------------------------------------------------------------*/
4645 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
4648 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4649 shCount &= 0x0007; // shCount : 0..7
4655 /* load sign if needed */
4656 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
4657 else if (mask_mode == 1) emitCLRC;
4658 emitpcode(POC_RRF,pcop);
4662 /* load sign if needed */
4663 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
4664 emitpcode(POC_RRF,pcop);
4665 /* load sign if needed */
4666 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
4667 emitpcode(POC_RRF,pcop);
4668 if (mask_mode == 2) return;
4671 /* load sign if needed */
4672 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
4673 emitpcode(POC_RRF,pcop);
4674 /* load sign if needed */
4675 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
4676 emitpcode(POC_RRF,pcop);
4677 /* load sign if needed */
4678 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
4679 emitpcode(POC_RRF,pcop);
4680 if (mask_mode == 2) return;
4683 emitpcode(POC_SWAPF,pcop);
4686 emitpcode(POC_SWAPF,pcop);
4687 emitpcode(POC_RRF,pcop);
4690 emitpcode(POC_SWAPF,pcop);
4691 emitpcode(POC_RRF,pcop);
4692 emitpcode(POC_RRF,pcop);
4698 emitpcode(POC_RLFW,pcop);
4699 emitpcode(POC_CLRF,pcop);
4701 emitpcode(POC_COMF,pcop);
4704 emitpcode(POC_RLFW,pcop);
4705 emitpcode(POC_RLF,pcop);
4712 /* leave invalid bits undefined */
4716 /* clear invalid bits -- zero-extend */
4717 emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
4718 emitpcode(POC_ANDWF, pcop);
4720 if (mask_mode == 2) {
4722 emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
4723 emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
4724 emitpcode(POC_IORWF, pcop);
4728 /*-----------------------------------------------------------------*/
4729 /* movLeft2Result - move byte from left to result */
4730 /*-----------------------------------------------------------------*/
4731 static void movLeft2Result (operand *left, int offl,
4732 operand *result, int offr)
4735 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4736 if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
4737 aopGet(AOP(left),offl,FALSE,FALSE);
4739 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
4740 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
4744 /*-----------------------------------------------------------------*/
4745 /* shiftLeft_Left2ResultLit - shift left by known count */
4746 /*-----------------------------------------------------------------*/
4748 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
4750 int size, same, offr, i;
4752 size = AOP_SIZE(left);
4753 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
4755 same = pic14_sameRegs (AOP(left), AOP(result));
4758 shCount = shCount & 0x07;
4764 case 0: /* takes 0 or 2N cycles (for offr==0) */
4765 if (!same || offr) {
4766 for (i=size-1; i >= 0; i--)
4767 movLeft2Result (left, i, result, offr + i);
4771 case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
4773 shiftLeft_Left2ResultLit (left, result, 8 * offr);
4774 shiftLeft_Left2ResultLit (result, result, shCount);
4775 return; /* prevent clearing result again */
4778 for (i=0; i < size; i++) {
4779 if (same && !offr) {
4780 emitpcode (POC_RLF, popGet (AOP(left), i));
4782 emitpcode (POC_RLFW, popGet (AOP(left), i));
4783 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
4789 case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
4790 /* works in-place/with offr as well */
4791 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
4792 emitpcode (POC_ANDLW, popGetLit (0xF0));
4793 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
4795 for (i = size - 2; i >= 0; i--)
4797 emitpcode (POC_SWAPFW, popGet (AOP(left), i));
4798 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
4799 emitpcode (POC_ANDLW, popGetLit (0x0F));
4800 emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
4801 emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
4805 case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
4806 /* works in-place/with offr as well */
4807 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
4808 for (i = size-2; i >= 0; i--) {
4809 emitpcode (POC_RRFW, popGet (AOP(left), i));
4810 emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
4812 emitpcode (POC_CLRF, popGet (AOP(result), offr));
4813 emitpcode (POC_RRF, popGet (AOP(result), offr));
4817 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
4818 shiftLeft_Left2ResultLit (result, result, 1);
4819 return; /* prevent clearing result again */
4825 emitpcode (POC_CLRF, popGet (AOP(result), offr));
4829 /*-----------------------------------------------------------------*/
4830 /* shiftRight_Left2ResultLit - shift right by known count */
4831 /*-----------------------------------------------------------------*/
4833 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
4835 int size, same, offr, i;
4837 size = AOP_SIZE(left);
4838 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
4840 same = pic14_sameRegs (AOP(left), AOP(result));
4843 shCount = shCount & 0x07;
4851 case 0: /* takes 0 or 2N cycles (for offr==0) */
4852 if (!same || offr) {
4853 for (i=0; i < size; i++)
4854 movLeft2Result (left, i + offr, result, i);
4858 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
4859 emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
4861 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
4862 shiftRight_Left2ResultLit (result, result, shCount, sign);
4863 return; /* prevent sign-extending result again */
4867 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
4870 for (i = size-1; i >= 0; i--) {
4871 if (same && !offr) {
4872 emitpcode (POC_RRF, popGet (AOP(left), i));
4874 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
4875 emitpcode (POC_MOVWF, popGet (AOP(result), i));
4881 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
4882 /* works in-place/with offr as well */
4883 emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
4884 emitpcode (POC_ANDLW, popGetLit (0x0F));
4885 emitpcode (POC_MOVWF, popGet(AOP(result), 0));
4887 for (i = 1; i < size; i++)
4889 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
4890 emitpcode (POC_MOVWF, popGet (AOP(result), i));
4891 emitpcode (POC_ANDLW, popGetLit (0xF0));
4892 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
4893 emitpcode (POC_XORWF, popGet (AOP(result), i));
4898 emitpcode (POC_MOVLW, popGetLit (0xF0));
4899 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
4900 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
4904 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
4905 /* works in-place/with offr as well */
4906 emitpcode (POC_RLFW, popGet (AOP(left), offr));
4907 for (i = 0; i < size-1; i++) {
4908 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
4909 emitpcode (POC_MOVWF, popGet (AOP(result), i));
4911 emitpcode (POC_CLRF, popGet (AOP(result), size-1));
4913 emitpcode (POC_RLF, popGet (AOP(result), size-1));
4916 emitpcode (POC_DECF, popGet (AOP(result), size-1));
4921 shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
4922 shiftRight_Left2ResultLit (result, result, 1, sign);
4923 return; /* prevent sign extending result again */
4928 addSign (result, size, sign);
4931 /*-----------------------------------------------------------------*
4932 * genMultiAsm - repeat assembly instruction for size of register.
4933 * if endian == 1, then the high byte (i.e base address + size of
4934 * register) is used first else the low byte is used first;
4935 *-----------------------------------------------------------------*/
4936 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
4942 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4955 emitpcode(poc, popGet(AOP(reg),offset));
4961 /*-----------------------------------------------------------------*/
4962 /* loadSignToC - load the operand's sign bit into CARRY */
4963 /*-----------------------------------------------------------------*/
4965 static void loadSignToC (operand *op)
4968 assert (op && AOP(op) && AOP_SIZE(op));
4971 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
4975 /*-----------------------------------------------------------------*/
4976 /* genRightShift - generate code for right shifting */
4977 /*-----------------------------------------------------------------*/
4978 static void genGenericShift (iCode *ic, int shiftRight)
4980 operand *right, *left, *result;
4983 symbol *tlbl, *tlbl1, *inverselbl;
4986 /* if signed then we do it the hard way preserve the
4987 sign bit moving it inwards */
4988 retype = getSpec(operandType(IC_RESULT(ic)));
4989 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4991 /* signed & unsigned types are treated the same : i.e. the
4992 signed is NOT propagated inwards : quoting from the
4993 ANSI - standard : "for E1 >> E2, is equivalent to division
4994 by 2**E2 if unsigned or if it has a non-negative value,
4995 otherwise the result is implementation defined ", MY definition
4996 is that the sign does not get propagated */
4998 right = IC_RIGHT(ic);
5000 result = IC_RESULT(ic);
5002 aopOp(right,ic,FALSE);
5003 aopOp(left,ic,FALSE);
5004 aopOp(result,ic,FALSE);
5006 /* if the shift count is known then do it
5007 as efficiently as possible */
5008 if (AOP_TYPE(right) == AOP_LIT) {
5009 int lit = (int) ulFromVal (AOP(right)->aopu.aop_lit);
5013 shiftRight = !shiftRight;
5017 shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
5019 shiftLeft_Left2ResultLit (left, result, lit);
5020 //genRightShiftLiteral (left,right,result,ic, 0);
5024 /* shift count is unknown then we have to form
5025 a loop get the loop count in B : Note: we take
5026 only the lower order byte since shifting
5027 more that 32 bits make no sense anyway, ( the
5028 largest size of an object can be only 32 bits ) */
5030 /* we must not overwrite the shift counter */
5031 assert (!pic14_sameRegs(AOP(right),AOP(result)));
5033 /* now move the left to the result if they are not the
5035 if (!pic14_sameRegs(AOP(left),AOP(result)))
5037 size = min(AOP_SIZE(result), AOP_SIZE(left));
5039 mov2w(AOP(left), size);
5040 movwf(AOP(result), size);
5042 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
5045 tlbl = newiTempLabel(NULL);
5046 tlbl1= newiTempLabel(NULL);
5048 size = AOP_SIZE(result);
5050 mov2w(AOP(right),0);
5051 if (!SPEC_USIGN(operandType(right)))
5053 inverselbl = newiTempLabel(NULL);
5054 /* signed shift count -- invert shift direction for c<0 */
5055 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
5056 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
5058 emitpcode(POC_SUBLW, popGetLit(0)); /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
5059 /* check for `a = b >> c' with `-c == 0' */
5061 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
5062 emitpLabel(tlbl->key);
5063 /* propagate the sign bit inwards for SIGNED result */
5064 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
5065 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
5066 emitpcode(POC_ADDLW, popGetLit(1)); /* clears CARRY (unless W==0 afterwards) */
5068 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
5070 if (!SPEC_USIGN(operandType(right)))
5072 symbol *inv_loop = newiTempLabel(NULL);
5074 shiftRight = !shiftRight; /* invert shift direction */
5076 /* we came here from the code above -- we are done */
5077 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
5079 /* emit code for shifting N<0 steps, count is already in W */
5080 emitpLabel(inverselbl->key);
5081 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
5082 emitpLabel(inv_loop->key);
5083 /* propagate the sign bit inwards for SIGNED result */
5084 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
5085 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
5086 emitpcode(POC_ADDLW, popGetLit(1));
5088 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
5091 emitpLabel(tlbl1->key);
5093 freeAsmop(left,NULL,ic,TRUE);
5094 freeAsmop (right,NULL,ic,TRUE);
5095 freeAsmop(result,NULL,ic,TRUE);
5098 static void genRightShift (iCode *ic)
5100 genGenericShift(ic, 1);
5103 static void genLeftShift (iCode *ic)
5105 genGenericShift(ic, 0);
5108 /*-----------------------------------------------------------------*/
5109 /* SetIrp - Set IRP bit */
5110 /*-----------------------------------------------------------------*/
5111 static void SetIrp(operand *result)
5114 if (AOP_TYPE(result) == AOP_LIT) {
5115 unsigned lit = (unsigned) double2ul (operandLitValue(result));
5121 if ((AOP_TYPE(result) == AOP_PCODE)
5122 && (AOP(result)->aopu.pcop->type == PO_LITERAL))
5124 int addrs = PCOL(AOP(result)->aopu.pcop)->lit;
5130 emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
5131 if(AOP_SIZE(result) > 1) {
5132 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
5140 setup_fsr (operand *ptr)
5143 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
5145 /* also setup-up IRP */
5149 /*-----------------------------------------------------------------*/
5150 /* emitPtrByteGet - emits code to get a byte into WREG from an */
5151 /* arbitrary pointer (__code, __data, generic) */
5152 /*-----------------------------------------------------------------*/
5154 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
5161 if (!alreadyAddressed) setup_fsr (src);
5162 emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
5166 assert( AOP_SIZE(src) == 2 );
5168 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
5170 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
5171 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
5172 call_libraryfunc ("__gptrget1");
5176 assert( AOP_SIZE(src) == 3 );
5178 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
5180 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
5182 call_libraryfunc ("__gptrget1");
5186 assert( !"unhandled pointer type" );
5191 /*-----------------------------------------------------------------*/
5192 /* emitPtrByteSet - emits code to set a byte from src through a */
5193 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR). */
5194 /*-----------------------------------------------------------------*/
5196 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
5203 if (!alreadyAddressed) setup_fsr (dst);
5204 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
5208 assert( !"trying to assign to __code pointer" );
5212 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
5214 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
5216 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
5218 call_libraryfunc ("__gptrput1");
5222 assert( !"unhandled pointer type" );
5227 /*-----------------------------------------------------------------*/
5228 /* genUnpackBits - generates code for unpacking bits */
5229 /*-----------------------------------------------------------------*/
5230 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
5232 int rsize; /* result size */
5233 sym_link *etype; /* bitfield type information */
5234 int blen; /* bitfield length */
5235 int bstr; /* bitfield starting bit within byte */
5238 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5239 etype = getSpec(operandType(result));
5240 rsize = getSize (operandType (result));
5241 blen = SPEC_BLEN (etype);
5242 bstr = SPEC_BSTR (etype);
5244 /* single bit field case */
5246 if (ifx) { /* that is for an if statement */
5249 resolveIfx(&rIfx,ifx);
5250 if (ptype == -1) /* direct */
5251 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
5253 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
5254 emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
5255 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5259 assert (!pic14_sameRegs (AOP(result), AOP(left)));
5260 for (i=0; i < AOP_SIZE(result); i++)
5261 emitpcode (POC_CLRF, popGet (AOP(result), i));
5266 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
5267 /* adjust result below */
5274 emitPtrByteGet (left, ptype, FALSE);
5275 emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
5277 /* adjust result below */
5281 assert( !"unhandled pointer type" );
5284 /* move sign-/zero extended bit to result */
5285 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
5286 emitpcode (POC_INCF, popGet (AOP(result), 0));
5288 emitpcode (POC_DECF, popGet (AOP(result), 0));
5290 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
5294 else if (blen <= 8 && ((blen + bstr) <= 8))
5299 for (i=0; i < AOP_SIZE(result); i++)
5300 emitpcode (POC_CLRF, popGet (AOP(result), i));
5305 mov2w(AOP(left), 0);
5312 emitPtrByteGet (left, ptype, FALSE);
5316 assert( !"unhandled pointer type" );
5320 emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
5321 movwf(AOP(result), 0);
5322 AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
5324 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
5326 /* signed bitfield */
5327 assert (bstr + blen > 0);
5328 emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
5329 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
5330 emitpcode(POC_IORWF, popGet(AOP(result),0));
5332 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
5336 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
5340 /*-----------------------------------------------------------------*/
5341 /* genDataPointerGet - generates code when ptr offset is known */
5342 /*-----------------------------------------------------------------*/
5343 static void genDataPointerGet (operand *left,
5347 int size , offset = 0;
5350 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5353 /* optimization - most of the time, left and result are the same
5354 * address, but different types. for the pic code, we could omit
5357 aopOp(result,ic,TRUE);
5359 if (pic14_sameRegs (AOP(left), AOP(result)))
5362 DEBUGpic14_AopType(__LINE__,left,NULL,result);
5364 //emitpcode(POC_MOVFW, popGet(AOP(left),0));
5366 size = AOP_SIZE(result);
5367 if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
5371 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
5372 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5376 freeAsmop(left,NULL,ic,TRUE);
5377 freeAsmop(result,NULL,ic,TRUE);
5381 /*-----------------------------------------------------------------*/
5382 /* genNearPointerGet - pic14_emitcode for near pointer fetch */
5383 /*-----------------------------------------------------------------*/
5384 static void genNearPointerGet (operand *left,
5389 sym_link *ltype = operandType(left);
5390 sym_link *rtype = operandType(result);
5391 sym_link *retype= getSpec(rtype); /* bitfield type information */
5395 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5398 aopOp(left,ic,FALSE);
5400 /* if left is rematerialisable and
5401 result is not bit variable type and
5402 the left is pointer to data space i.e
5403 lower 128 bytes of space */
5404 if (AOP_TYPE(left) == AOP_PCODE && //AOP_TYPE(left) == AOP_IMMD &&
5405 !IS_BITVAR(retype) &&
5406 PIC_IS_DATA_PTR(ltype)) {
5407 genDataPointerGet (left,result,ic);
5411 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5412 aopOp (result,ic,FALSE);
5414 /* Check if can access directly instead of via a pointer */
5415 if ((AOP_TYPE(left) == AOP_PCODE)
5416 && (AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
5417 && (AOP_SIZE(result) == 1))
5422 if (IS_BITFIELD(getSpec(operandType(result))))
5424 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
5428 /* If the pointer value is not in a the FSR then need to put it in */
5429 /* Must set/reset IRP bit for use with FSR. */
5434 /* if bitfield then unpack the bits */
5436 /* we have can just get the values */
5437 int size = AOP_SIZE(result);
5440 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5444 emitpcode(POC_MOVWF,popGet(AOP(left),0));
5446 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
5447 if (AOP_TYPE(result) == AOP_LIT) {
5448 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
5450 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5452 if (size && !direct)
5453 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
5458 /* now some housekeeping stuff */
5460 /* we had to allocate for this iCode */
5461 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5462 freeAsmop(NULL,aop,ic,TRUE);
5464 /* we did not allocate which means left
5465 already in a pointer register, then
5466 if size > 0 && this could be used again
5467 we have to point it back to where it
5469 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5470 if (AOP_SIZE(result) > 1 &&
5471 !OP_SYMBOL(left)->remat &&
5472 ( OP_SYMBOL(left)->liveTo > ic->seq ||
5474 int size = AOP_SIZE(result) - 1;
5476 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
5482 freeAsmop(left,NULL,ic,TRUE);
5483 freeAsmop(result,NULL,ic,TRUE);
5487 /*-----------------------------------------------------------------*/
5488 /* genGenPointerGet - gget value from generic pointer space */
5489 /*-----------------------------------------------------------------*/
5490 static void genGenPointerGet (operand *left,
5491 operand *result, iCode *ic)
5494 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5495 aopOp(left,ic,FALSE);
5496 aopOp(result,ic,FALSE);
5499 DEBUGpic14_AopType(__LINE__,left,NULL,result);
5501 if (IS_BITFIELD(getSpec(operandType(result))))
5503 genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
5508 /* emit call to __gptrget */
5509 char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
5510 int size = AOP_SIZE(result);
5513 assert (size > 0 && size <= 4);
5515 /* pass arguments */
5516 assert (AOP_SIZE(left) == 3);
5517 mov2w(AOP(left), 0);
5518 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
5519 mov2w(AOP(left), 1);
5520 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
5521 mov2w(AOP(left), 2);
5522 call_libraryfunc (func[size]);
5525 movwf (AOP(result), --size);
5527 emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
5528 movwf (AOP(result), size);
5532 freeAsmop(left,NULL,ic,TRUE);
5533 freeAsmop(result,NULL,ic,TRUE);
5537 /*-----------------------------------------------------------------*/
5538 /* genConstPointerGet - get value from const generic pointer space */
5539 /*-----------------------------------------------------------------*/
5540 static void genConstPointerGet (operand *left,
5541 operand *result, iCode *ic)
5543 //sym_link *retype = getSpec(operandType(result));
5545 symbol *albl, *blbl;//, *clbl;
5552 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5553 aopOp(left,ic,FALSE);
5554 aopOp(result,ic,FALSE);
5556 size = AOP_SIZE(result);
5558 DEBUGpic14_AopType(__LINE__,left,NULL,result);
5560 DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
5562 lit = op_isLitLike (left);
5563 poc = lit ? POC_MOVLW : POC_MOVFW;
5565 if (IS_BITFIELD(getSpec(operandType(result))))
5567 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
5572 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
5573 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
5574 assert (size > 0 && size <= 4);
5577 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
5579 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
5580 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
5581 call_libraryfunc (func[size]);
5583 movwf(AOP(result),size-1);
5584 for (i = 1; i < size; i++)
5586 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
5587 movwf(AOP(result),size - 1 - i);
5592 freeAsmop(left,NULL,ic,TRUE);
5593 freeAsmop(result,NULL,ic,TRUE);
5596 /*-----------------------------------------------------------------*/
5597 /* genPointerGet - generate code for pointer get */
5598 /*-----------------------------------------------------------------*/
5599 static void genPointerGet (iCode *ic)
5601 operand *left, *result ;
5602 sym_link *type, *etype;
5606 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5609 result = IC_RESULT(ic) ;
5611 /* depending on the type of pointer we need to
5612 move it to the correct pointer register */
5613 type = operandType(left);
5614 etype = getSpec(type);
5616 if (IS_PTR_CONST(type))
5617 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
5619 /* if left is of type of pointer then it is simple */
5620 if (IS_PTR(type) && !IS_FUNC(type->next))
5621 p_type = DCL_TYPE(type);
5623 /* we have to go by the storage class */
5624 p_type = PTR_TYPE(SPEC_OCLS(etype));
5626 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
5628 if (SPEC_OCLS(etype)->codesp ) {
5629 DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
5630 //p_type = CPOINTER ;
5633 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
5634 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
5635 /*p_type = FPOINTER ;*/
5637 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
5638 DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
5639 /* p_type = PPOINTER; */
5641 if (SPEC_OCLS(etype) == idata )
5642 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
5643 /* p_type = IPOINTER; */
5645 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
5646 /* p_type = POINTER ; */
5649 /* now that we have the pointer type we assign
5650 the pointer values */
5656 genNearPointerGet (left,result,ic);
5660 genPagedPointerGet(left,result,ic);
5664 genFarPointerGet (left,result,ic);
5668 genConstPointerGet (left,result,ic);
5672 genGenPointerGet (left,result,ic);
5675 assert ( !"unhandled pointer type" );
5681 /*-----------------------------------------------------------------*/
5682 /* genPackBits - generates code for packed bit storage */
5683 /*-----------------------------------------------------------------*/
5684 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
5686 int blen; /* bitfield length */
5687 int bstr; /* bitfield starting bit within byte */
5688 int litval; /* source literal value (if AOP_LIT) */
5689 unsigned char mask; /* bitmask within current byte */
5692 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5694 blen = SPEC_BLEN (etype);
5695 bstr = SPEC_BSTR (etype);
5697 /* If the bitfield length is less than a byte and does not cross byte boundaries */
5698 if ((blen <= 8) && ((bstr + blen) <= 8))
5700 mask = ((unsigned char) (0xFF << (blen + bstr)) |
5701 (unsigned char) (0xFF >> (8 - bstr)));
5703 if (AOP_TYPE (right) == AOP_LIT)
5705 /* Case with a bitfield length <8 and literal source */
5706 int lit = (int) ulFromVal (AOP (right)->aopu.aop_lit);
5713 if (AOP(result)->type == AOP_PCODE)
5714 pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
5716 pcop = popGet(AOP(result),0);
5717 emitpcode(lit?POC_BSF:POC_BCF,pcop);
5723 emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
5727 assert( !"trying to assign to bitfield via pointer to __code space" );
5731 emitPtrByteGet(result, p_type, FALSE);
5733 emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
5735 emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
5737 emitPtrByteSet(result, p_type, TRUE);
5741 assert( !"unhandled pointer type" );
5743 } // switch (p_type)
5746 litval = lit << bstr;
5747 litval &= (~mask) & 0x00ff;
5752 mov2w (AOP(result), 0);
5753 if ((litval|mask) != 0x00ff)
5754 emitpcode(POC_ANDLW, popGetLit (mask));
5756 emitpcode(POC_IORLW, popGetLit (litval));
5757 movwf (AOP(result), 0);
5763 emitPtrByteGet(result, p_type, FALSE);
5764 if ((litval|mask) != 0x00ff)
5765 emitpcode(POC_ANDLW, popGetLit (mask));
5767 emitpcode(POC_IORLW, popGetLit (litval));
5768 emitPtrByteSet(result, p_type, TRUE);
5772 assert( !"trying to assign to bitfield via pointer to __code space" );
5776 assert( !"unhandled pointer type" );
5783 /* right is no literal */
5788 /* Note more efficient code, of pre clearing bit then only setting it if required,
5789 * can only be done if it is known that the result is not a SFR */
5790 emitpcode(POC_RRFW,popGet(AOP(right),0));
5792 emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
5794 emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
5800 emitPtrByteGet (result, p_type, FALSE);
5801 emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
5802 emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
5803 emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
5804 emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
5805 emitPtrByteSet (result, p_type, TRUE);
5809 assert( !"trying to assign to bitfield via pointer to __code space" );
5813 assert( !"unhandled pointer type" );
5818 /* Case with a bitfield 1 < length <= 8 and arbitrary source */
5819 pCodeOp *temp = popGetTempReg ();
5821 mov2w (AOP(right), 0);
5823 emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
5825 emitpcode(POC_MOVWF, temp);
5827 AccLsh (temp, bstr);
5833 mov2w (AOP(result), 0);
5834 emitpcode(POC_ANDLW, popGetLit (mask));
5835 emitpcode(POC_IORFW, temp);
5836 movwf (AOP(result), 0);
5842 emitPtrByteGet (result, p_type, FALSE);
5843 emitpcode(POC_ANDLW, popGetLit (mask));
5844 emitpcode(POC_IORFW, temp);
5845 emitPtrByteSet (result, p_type, TRUE);
5849 assert( !"trying to assign to bitfield via pointer to __code space" );
5853 assert( !"unhandled pointer type" );
5857 popReleaseTempReg (temp);
5859 } // if (AOP(right)->type != AOP_LIT)
5861 } // if (blen <= 8 && ((blen + bstr) <= 8))
5863 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
5866 /*-----------------------------------------------------------------*/
5867 /* genDataPointerSet - remat pointer to data space */
5868 /*-----------------------------------------------------------------*/
5869 static void genDataPointerSet(operand *right,
5873 int size, offset = 0 ;
5877 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5878 aopOp(right,ic,FALSE);
5879 aopOp(result,ic,FALSE);
5881 assert (IS_SYMOP(result));
5882 assert (IS_PTR(OP_SYM_TYPE(result)));
5884 if (AOP_TYPE(right) == AOP_LIT)
5887 size = AOP_SIZE(right);
5888 ressize = getSize(OP_SYM_ETYPE(result));
5889 if (size > ressize) size = ressize;
5890 //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
5892 //assert( !"what's going on here?" );
5895 if ( AOP_TYPE(result) == AOP_PCODE) {
5896 fprintf(stderr,"genDataPointerSet %s, %d\n",
5897 AOP(result)->aopu.pcop->name,
5898 PCOI(AOP(result)->aopu.pcop)->offset);
5902 // tsd, was l+1 - the underline `_' prefix was being stripped
5904 emitpComment ("%s:%u: size=%d/%d, offset=%d, AOP_TYPE(res)=%d", __FILE__,__LINE__, size, ressize, offset, AOP_TYPE(result));
5906 if (AOP_TYPE(right) == AOP_LIT) {
5907 unsigned int lit = pic14aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
5908 //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
5910 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
5911 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
5913 emitpcode(POC_CLRF, popGet(AOP(result), offset));
5916 //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
5917 emitpcode(POC_MOVFW, popGet(AOP(right), offset));
5918 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
5924 freeAsmop(right,NULL,ic,TRUE);
5925 freeAsmop(result,NULL,ic,TRUE);
5928 /*-----------------------------------------------------------------*/
5929 /* genNearPointerSet - pic14_emitcode for near pointer put */
5930 /*-----------------------------------------------------------------*/
5931 static void genNearPointerSet (operand *right,
5936 sym_link *ptype = operandType(result);
5937 sym_link *retype = getSpec(operandType(right));
5938 sym_link *letype = getSpec(ptype);
5943 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5944 aopOp(result,ic,FALSE);
5947 /* if the result is rematerializable &
5948 in data space & not a bit variable */
5949 //if (AOP_TYPE(result) == AOP_IMMD &&
5950 if (AOP_TYPE(result) == AOP_PCODE &&
5951 PIC_IS_DATA_PTR(ptype) &&
5952 !IS_BITVAR (retype) &&
5953 !IS_BITVAR (letype)) {
5954 genDataPointerSet (right,result,ic);
5955 freeAsmop(result,NULL,ic,TRUE);
5960 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5961 aopOp(right,ic,FALSE);
5962 DEBUGpic14_AopType(__LINE__,NULL,right,result);
5964 /* Check if can access directly instead of via a pointer */
5965 if ((AOP_TYPE(result) == AOP_PCODE)
5966 && (AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
5967 && (AOP_SIZE(right) == 1))
5972 if (IS_BITFIELD (letype))
5974 genPackBits (letype, result, right, direct?-1:POINTER);
5978 /* If the pointer value is not in a the FSR then need to put it in */
5979 /* Must set/reset IRP bit for use with FSR. */
5980 /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
5985 /* we have can just get the values */
5986 int size = AOP_SIZE(right);
5989 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5991 char *l = aopGet(AOP(right),offset,FALSE,TRUE);
5993 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
5995 if (AOP_TYPE(right) == AOP_LIT) {
5996 emitpcode(POC_MOVLW,popGet(AOP(right),offset));
5998 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6001 emitpcode(POC_MOVWF,popGet(AOP(result),0));
6003 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
6005 if (size && !direct)
6006 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
6011 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6012 /* now some housekeeping stuff */
6014 /* we had to allocate for this iCode */
6015 freeAsmop(NULL,aop,ic,TRUE);
6017 /* we did not allocate which means left
6018 already in a pointer register, then
6019 if size > 0 && this could be used again
6020 we have to point it back to where it
6022 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6023 if (AOP_SIZE(right) > 1 &&
6024 !OP_SYMBOL(result)->remat &&
6025 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6027 int size = AOP_SIZE(right) - 1;
6029 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
6033 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6036 freeAsmop(right,NULL,ic,TRUE);
6037 freeAsmop(result,NULL,ic,TRUE);
6040 /*-----------------------------------------------------------------*/
6041 /* genGenPointerSet - set value from generic pointer space */
6042 /*-----------------------------------------------------------------*/
6043 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
6045 sym_link *retype = getSpec(operandType(result));
6048 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6049 aopOp(right,ic,FALSE);
6050 aopOp(result,ic,FALSE);
6053 DEBUGpic14_AopType(__LINE__,right,NULL,result);
6055 if (IS_BITFIELD(retype))
6057 genPackBits (retype, result, right, GPOINTER);
6062 /* emit call to __gptrput */
6063 char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
6064 int size = AOP_SIZE(right);
6067 /* The following assertion fails for
6068 * struct foo { char a; char b; } bar;
6069 * void demo(struct foo *dst, char c) { dst->b = c; }
6070 * as size will be 1 (sizeof(c)), whereas dst->b will be accessed
6071 * using (((char *)dst)+1), whose OP_SYM_ETYPE still is struct foo
6073 * The frontend seems to guarantee that IC_LEFT has the correct size,
6074 * it works fine both for larger and smaller types of `char c'.
6076 //assert (size == getSize(OP_SYM_ETYPE(result)));
6077 assert (size > 0 && size <= 4);
6079 /* pass arguments */
6080 /* - value (MSB in Gstack_base_addr-2, growing downwards) */
6086 mov2w_op (right, off);
6087 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
6092 assert (AOP_SIZE(result) == 3);
6093 mov2w(AOP(result), 0);
6094 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
6095 mov2w(AOP(result), 1);
6096 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
6097 mov2w(AOP(result), 2);
6098 call_libraryfunc (func[size]);
6101 freeAsmop(right,NULL,ic,TRUE);
6102 freeAsmop(result,NULL,ic,TRUE);
6105 /*-----------------------------------------------------------------*/
6106 /* genPointerSet - stores the value into a pointer location */
6107 /*-----------------------------------------------------------------*/
6108 static void genPointerSet (iCode *ic)
6110 operand *right, *result ;
6111 sym_link *type, *etype;
6115 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6117 right = IC_RIGHT(ic);
6118 result = IC_RESULT(ic) ;
6120 /* depending on the type of pointer we need to
6121 move it to the correct pointer register */
6122 type = operandType(result);
6123 etype = getSpec(type);
6124 /* if left is of type of pointer then it is simple */
6125 if (IS_PTR(type) && !IS_FUNC(type->next)) {
6126 p_type = DCL_TYPE(type);
6129 /* we have to go by the storage class */
6130 p_type = PTR_TYPE(SPEC_OCLS(etype));
6132 /* if (SPEC_OCLS(etype)->codesp ) { */
6133 /* p_type = CPOINTER ; */
6136 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6137 /* p_type = FPOINTER ; */
6139 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6140 /* p_type = PPOINTER ; */
6142 /* if (SPEC_OCLS(etype) == idata ) */
6143 /* p_type = IPOINTER ; */
6145 /* p_type = POINTER ; */
6148 /* now that we have the pointer type we assign
6149 the pointer values */
6155 genNearPointerSet (right,result,ic);
6159 genPagedPointerSet (right,result,ic);
6163 genFarPointerSet (right,result,ic);
6167 genGenPointerSet (right,result,ic);
6171 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6172 "genPointerSet: illegal pointer type");
6176 /*-----------------------------------------------------------------*/
6177 /* genIfx - generate code for Ifx statement */
6178 /*-----------------------------------------------------------------*/
6179 static void genIfx (iCode *ic, iCode *popIc)
6181 operand *cond = IC_COND(ic);
6185 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6187 aopOp(cond,ic,FALSE);
6189 /* get the value into acc */
6190 if (AOP_TYPE(cond) != AOP_CRY)
6191 pic14_toBoolean(cond);
6195 /* if there was something to be popped then do it */
6201 /* This assumes that CARRY is set iff cond is true */
6204 assert (!IC_FALSE(ic));
6205 emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
6207 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
6209 assert (IC_FALSE(ic));
6210 emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
6212 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
6216 static int hasWarned = 0;
6219 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
6226 /* now Z is set iff !cond */
6229 assert (!IC_FALSE(ic));
6231 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
6234 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
6240 /* the result is now in the accumulator */
6241 freeAsmop(cond,NULL,ic,TRUE);
6244 /*-----------------------------------------------------------------*/
6245 /* genAddrOf - generates code for address of */
6246 /*-----------------------------------------------------------------*/
6247 static void genAddrOf (iCode *ic)
6249 operand *right, *result, *left;
6253 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6256 //aopOp(IC_RESULT(ic),ic,FALSE);
6258 aopOp((left=IC_LEFT(ic)),ic,FALSE);
6259 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6260 aopOp((result=IC_RESULT(ic)),ic,TRUE);
6262 DEBUGpic14_AopType(__LINE__,left,right,result);
6263 assert (IS_SYMOP (left));
6265 /* sanity check: generic pointers to code space are not yet supported,
6266 * pionters to codespace must not be assigned addresses of __data values. */
6268 fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
6269 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)));
6270 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)));
6271 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)));
6272 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)));
6275 if (IS_SYMOP(result) && IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
6276 fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
6277 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
6278 OP_SYMBOL(left)->name);
6279 } else if (IS_SYMOP(result) && !IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
6280 fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
6281 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
6282 OP_SYMBOL(left)->name);
6285 size = AOP_SIZE(IC_RESULT(ic));
6286 if (IS_SYMOP(result) && IS_GENPTR(OP_SYM_TYPE(result))) {
6288 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
6293 /* fixing bug #863624, reported from (errolv) */
6294 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
6295 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
6298 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
6299 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6304 if (IS_SYMOP(result) && IS_GENPTR(OP_SYM_TYPE(result)))
6306 /* provide correct tag */
6307 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
6308 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
6309 movwf (AOP(result), 2);
6312 freeAsmop(left,NULL,ic,FALSE);
6313 freeAsmop(result,NULL,ic,TRUE);
6317 /*-----------------------------------------------------------------*/
6318 /* genAssign - generate code for assignment */
6319 /*-----------------------------------------------------------------*/
6320 static void genAssign (iCode *ic)
6322 operand *result, *right;
6323 int size, offset,know_W;
6324 unsigned long lit = 0L;
6326 result = IC_RESULT(ic);
6327 right = IC_RIGHT(ic) ;
6330 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6332 /* if they are the same */
6333 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
6336 aopOp(right,ic,FALSE);
6337 aopOp(result,ic,TRUE);
6339 DEBUGpic14_AopType(__LINE__,NULL,right,result);
6341 /* if they are the same registers */
6342 if (pic14_sameRegs(AOP(right),AOP(result)))
6345 /* special case: assign from __code */
6346 if (!IS_ITEMP(right) /* --> iTemps never reside in __code */
6347 && IS_SYMOP (right) /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
6348 && !IS_FUNC(OP_SYM_TYPE(right)) /* --> we would want its address instead of the first instruction */
6349 && !IS_CODEPTR(OP_SYM_TYPE(right)) /* --> get symbols address instread */
6350 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
6352 emitpComment ("genAssign from CODESPACE");
6353 genConstPointerGet (right, result, ic);
6357 /* just for symmetry reasons... */
6358 if (!IS_ITEMP(result)
6359 && IS_SYMOP (result)
6360 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
6362 assert ( !"cannot write to CODESPACE" );
6365 /* if the result is a bit */
6366 if (AOP_TYPE(result) == AOP_CRY) {
6368 /* if the right size is a literal then
6369 we know what the value is */
6370 if (AOP_TYPE(right) == AOP_LIT) {
6372 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
6373 popGet(AOP(result),0));
6375 if (((int) operandLitValue(right)))
6376 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
6377 AOP(result)->aopu.aop_dir,
6378 AOP(result)->aopu.aop_dir);
6380 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
6381 AOP(result)->aopu.aop_dir,
6382 AOP(result)->aopu.aop_dir);
6386 /* the right is also a bit variable */
6387 if (AOP_TYPE(right) == AOP_CRY) {
6388 emitpcode(POC_BCF, popGet(AOP(result),0));
6389 emitpcode(POC_BTFSC, popGet(AOP(right),0));
6390 emitpcode(POC_BSF, popGet(AOP(result),0));
6392 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
6393 AOP(result)->aopu.aop_dir,
6394 AOP(result)->aopu.aop_dir);
6395 pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
6396 AOP(right)->aopu.aop_dir,
6397 AOP(right)->aopu.aop_dir);
6398 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
6399 AOP(result)->aopu.aop_dir,
6400 AOP(result)->aopu.aop_dir);
6405 emitpcode(POC_BCF, popGet(AOP(result),0));
6406 pic14_toBoolean(right);
6408 emitpcode(POC_BSF, popGet(AOP(result),0));
6409 //aopPut(AOP(result),"a",0);
6413 /* bit variables done */
6415 size = AOP_SIZE(result);
6417 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
6418 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6419 if(aopIdx(AOP(result),0) == 4) {
6420 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6421 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
6422 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6425 DEBUGpic14_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
6431 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6432 if(AOP_TYPE(right) == AOP_LIT) {
6433 lit = (unsigned long)pic14aopLiteral(AOP(right)->aopu.aop_lit, offset) & 0x0ff;
6435 if(know_W != (int)(lit&0xff))
6436 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
6438 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6440 emitpcode(POC_CLRF, popGet(AOP(result),offset));
6442 } else if (AOP_TYPE(right) == AOP_CRY) {
6443 emitpcode(POC_CLRF, popGet(AOP(result),offset));
6445 emitpcode(POC_BTFSS, popGet(AOP(right),0));
6446 emitpcode(POC_INCF, popGet(AOP(result),0));
6449 mov2w_op (right, offset);
6450 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6458 freeAsmop (right,NULL,ic,FALSE);
6459 freeAsmop (result,NULL,ic,TRUE);
6462 /*-----------------------------------------------------------------*/
6463 /* genJumpTab - genrates code for jump table */
6464 /*-----------------------------------------------------------------*/
6465 static void genJumpTab (iCode *ic)
6471 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6473 aopOp(IC_JTCOND(ic),ic,FALSE);
6474 /* get the condition into accumulator */
6475 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
6477 /* multiply by three */
6478 pic14_emitcode("add","a,acc");
6479 pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
6481 jtab = newiTempLabel(NULL);
6482 pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
6483 pic14_emitcode("jmp","@a+dptr");
6484 pic14_emitcode("","%05d_DS_:",jtab->key+100);
6486 emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
6487 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
6488 emitpcode(POC_MOVLW, popGetLabel(jtab->key));
6489 emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
6491 emitpcode(POC_INCF, popCopyReg(&pc_pclath));
6492 emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
6493 emitpLabel(jtab->key);
6495 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
6497 /* now generate the jump labels */
6498 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
6499 jtab = setNextItem(IC_JTLABELS(ic))) {
6500 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
6501 emitpcode(POC_GOTO,popGetLabel(jtab->key));
6507 /*-----------------------------------------------------------------*/
6508 /* genCast - gen code for casting */
6509 /*-----------------------------------------------------------------*/
6510 static void genCast (iCode *ic)
6512 operand *result = IC_RESULT(ic);
6513 sym_link *restype = operandType(result);
6514 sym_link *rtype = operandType(IC_RIGHT(ic));
6515 operand *right = IC_RIGHT(ic);
6519 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
6520 /* if they are equivalent then do nothing */
6521 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
6524 aopOp(right,ic,FALSE) ;
6525 aopOp(result,ic,FALSE);
6527 DEBUGpic14_AopType(__LINE__,NULL,right,result);
6529 /* if the result is a bit */
6530 if (AOP_TYPE(result) == AOP_CRY) {
6531 assert(!"assigning to bit variables is not supported");
6534 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
6536 size = AOP_SIZE(result);
6538 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
6540 emitpcode(POC_CLRF, popGet(AOP(result),0));
6541 emitpcode(POC_BTFSC, popGet(AOP(right),0));
6542 emitpcode(POC_INCF, popGet(AOP(result),0));
6545 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
6550 if (IS_PTR(restype))
6552 operand *result = IC_RESULT(ic);
6553 //operand *left = IC_LEFT(ic);
6554 operand *right = IC_RIGHT(ic);
6557 /* copy common part */
6558 int max, size = AOP_SIZE(result);
6559 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
6560 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
6562 /* warn if we discard generic opinter tag */
6563 if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
6565 //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
6571 mov2w_op (right, size);
6572 movwf (AOP(result), size);
6575 /* upcast into generic pointer type? */
6576 if (IS_GENPTR(restype)
6577 && (size < AOP_SIZE(result))
6578 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
6580 //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
6583 switch (DCL_TYPE(rtype))
6585 case POINTER: /* __data */
6586 case FPOINTER: /* __data */
6587 assert (AOP_SIZE(right) == 2);
6591 case CPOINTER: /* __code */
6592 assert (AOP_SIZE(right) == 2);
6596 case GPOINTER: /* unknown destination, __data or __code */
6597 /* assume __data space (address of immediate) */
6598 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
6599 if (AOP(right)->code)
6606 assert (!"unhandled pointer type");
6609 /* convert other values into pointers to __data space */
6613 assert (AOP_SIZE(result) == 3);
6615 emitpcode(POC_CLRF, popGet(AOP(result), 2));
6617 emitpcode(POC_MOVLW, popGetLit(tag));
6618 movwf(AOP(result), 2);
6621 addSign(result, max, 0);
6626 /* if they are the same size : or less */
6627 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
6629 /* if they are in the same place */
6630 if (pic14_sameRegs(AOP(right),AOP(result)))
6633 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
6634 if (IS_PTR_CONST(rtype))
6635 DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
6636 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
6637 DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
6639 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
6640 emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
6641 emitpcode(POC_MOVWF, popGet(AOP(result),0));
6642 emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
6643 emitpcode(POC_MOVWF, popGet(AOP(result),1));
6644 if(AOP_SIZE(result) <2)
6645 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
6649 /* if they in different places then copy */
6650 size = AOP_SIZE(result);
6653 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
6654 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6656 //aopPut(AOP(result),
6657 // aopGet(AOP(right),offset,FALSE,FALSE),
6666 /* so we now know that the size of destination is greater
6667 than the size of the source. */
6669 /* we move to result for the size of source */
6670 size = AOP_SIZE(right);
6673 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
6674 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6678 addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
6681 freeAsmop(right,NULL,ic,TRUE);
6682 freeAsmop(result,NULL,ic,TRUE);
6686 /*-----------------------------------------------------------------*/
6687 /* genDjnz - generate decrement & jump if not zero instrucion */
6688 /*-----------------------------------------------------------------*/
6689 static int genDjnz (iCode *ic, iCode *ifx)
6693 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6698 /* if the if condition has a false label
6699 then we cannot save */
6703 /* if the minus is not of the form
6705 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
6706 !IS_OP_LITERAL(IC_RIGHT(ic)))
6709 if (operandLitValue(IC_RIGHT(ic)) != 1)
6712 /* if the size of this greater than one then no
6714 if (getSize(operandType(IC_RESULT(ic))) > 1)
6717 /* otherwise we can save BIG */
6718 lbl = newiTempLabel(NULL);
6719 lbl1= newiTempLabel(NULL);
6721 aopOp(IC_RESULT(ic),ic,FALSE);
6723 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
6724 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
6726 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
6731 /*-----------------------------------------------------------------*/
6732 /* genReceive - generate code for a receive iCode */
6733 /*-----------------------------------------------------------------*/
6734 static void genReceive (iCode *ic)
6737 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6739 if (isOperandInFarSpace(IC_RESULT(ic)) &&
6740 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
6741 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
6743 int size = getSize(operandType(IC_RESULT(ic)));
6744 int offset = fReturnSizePic - size;
6746 pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
6747 fReturn[fReturnSizePic - offset - 1] : "acc"));
6750 aopOp(IC_RESULT(ic),ic,FALSE);
6751 size = AOP_SIZE(IC_RESULT(ic));
6754 pic14_emitcode ("pop","acc");
6755 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
6760 aopOp(IC_RESULT(ic),ic,FALSE);
6762 GpsuedoStkPtr = ic->parmBytes; // address used arg on stack
6763 assignResultValue(IC_RESULT(ic));
6766 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
6769 /*-----------------------------------------------------------------*/
6770 /* genDummyRead - generate code for dummy read of volatiles */
6771 /*-----------------------------------------------------------------*/
6773 genDummyRead (iCode * ic)
6776 pic14_emitcode ("; genDummyRead","");
6777 pic14_emitcode ("; not implemented","");
6782 /*-----------------------------------------------------------------*/
6783 /* genpic14Code - generate code for pic14 based controllers */
6784 /*-----------------------------------------------------------------*/
6786 * At this point, ralloc.c has gone through the iCode and attempted
6787 * to optimize in a way suitable for a PIC. Now we've got to generate
6788 * PIC instructions that correspond to the iCode.
6790 * Once the instructions are generated, we'll pass through both the
6791 * peep hole optimizer and the pCode optimizer.
6792 *-----------------------------------------------------------------*/
6794 void genpic14Code (iCode *lic)
6801 lineHead = lineCurr = NULL;
6803 pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
6806 /* if debug information required */
6807 if (options.debug && debugFile && currFunc) {
6808 debugFile->writeFunction (currFunc, lic);
6812 for (ic = lic ; ic ; ic = ic->next ) {
6814 //DEBUGpic14_emitcode(";ic","");
6815 //fprintf (stderr, "in ic loop\n");
6816 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
6817 //ic->lineno, printCLine(ic->filename, ic->lineno));
6819 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
6821 //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
6822 cline = printCLine (ic->filename, ic->lineno);
6823 if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
6824 addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
6825 //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
6828 if (options.iCodeInAsm) {
6829 const char *iLine = printILine(ic);
6830 emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
6833 /* if the result is marked as
6834 spilt and rematerializable or code for
6835 this has already been generated then
6837 if (resultRemat(ic) || ic->generated )
6840 /* depending on the operation */
6859 /* IPOP happens only when trying to restore a
6860 spilt live range, if there is an ifx statement
6861 following this pop then the if statement might
6862 be using some of the registers being popped which
6863 would destory the contents of the register so
6864 we need to check for this condition and handle it */
6866 ic->next->op == IFX &&
6867 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
6868 genIfx (ic->next,ic);
6886 genEndFunction (ic);
6906 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
6923 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
6927 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
6934 /* note these two are xlated by algebraic equivalence
6935 during parsing SDCC.y */
6936 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
6937 "got '>=' or '<=' shouldn't have come here");
6941 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
6953 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
6957 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
6961 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
6988 case GET_VALUE_AT_ADDRESS:
6993 if (POINTER_SET(ic))
7020 addSet(&_G.sendSet,ic);
7023 case DUMMY_READ_VOLATILE:
7028 fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
7035 /* now we are ready to call the
7036 peep hole optimizer */
7037 if (!options.nopeep) {
7038 peepHole (&lineHead);
7040 /* now do the actual printing */
7041 printLine (lineHead,codeOutBuf);
7044 DFPRINTF((stderr,"printing pBlock\n\n"));
7045 printpBlock(stdout,pb);
7051 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
7052 * (meaning: representing its own address) or not (referencing its contents).
7053 * This can only be decided based on the operand's type. */
7055 aop_isLitLike (asmop *aop)
7058 if (aop->type == AOP_LIT) return 1;
7059 if (aop->type == AOP_IMMD) return 1;
7060 if ((aop->type == AOP_PCODE) &&
7061 ((aop->aopu.pcop->type == PO_LITERAL)))
7063 /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
7064 * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
7071 op_isLitLike (operand *op)
7074 if (aop_isLitLike (AOP(op))) return 1;
7075 if (IS_SYMOP(op) && IS_FUNC(OP_SYM_TYPE(op))) return 1;
7076 if (IS_SYMOP(op) && IS_PTR(OP_SYM_TYPE(op))
7077 && (AOP_TYPE(op) == AOP_PCODE)
7078 && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {