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 /*-----------------------------------------------------------------*/
1620 static void genUminusFloat(operand *op,operand *result)
1622 int size ,offset =0 ;
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);
1638 movwf(AOP(result), size);
1642 /*-----------------------------------------------------------------*/
1643 /* genUminus - unary minus code generation */
1644 /*-----------------------------------------------------------------*/
1645 static void genUminus (iCode *ic)
1648 sym_link *optype, *rtype;
1652 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1654 aopOp(IC_LEFT(ic),ic,FALSE);
1655 aopOp(IC_RESULT(ic),ic,TRUE);
1657 /* if both in bit space then special
1659 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1660 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1662 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0));
1663 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
1664 emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0));
1669 optype = operandType(IC_LEFT(ic));
1670 rtype = operandType(IC_RESULT(ic));
1672 /* if float then do float stuff */
1673 if (IS_FLOAT(optype)) {
1674 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1678 /* otherwise subtract from zero by taking the 2's complement */
1679 size = AOP_SIZE(IC_LEFT(ic));
1681 for(i=0; i<size; i++) {
1682 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
1683 emitpcode(POC_COMF, popGet(AOP(IC_LEFT(ic)),i));
1685 emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
1686 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
1690 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0));
1691 for(i=1; i<size; i++) {
1693 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),i));
1697 /* release the aops */
1698 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1699 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1702 /*-----------------------------------------------------------------*/
1703 /* saverbank - saves an entire register bank on the stack */
1704 /*-----------------------------------------------------------------*/
1705 static void saverbank (int bank, iCode *ic, bool pushPsw)
1709 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
1715 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1716 if (options.useXstack) {
1719 r = getFreePtr(ic,&aop,FALSE);
1720 pic14_emitcode("mov","%s,_spx",r->name);
1724 for (i = 0 ; i < pic14_nRegs ;i++) {
1725 if (options.useXstack) {
1726 pic14_emitcode("inc","%s",r->name);
1727 //pic14_emitcode("mov","a,(%s+%d)",
1728 // regspic14[i].base,8*bank+regspic14[i].offset);
1729 pic14_emitcode("movx","@%s,a",r->name);
1731 pic14_emitcode("push","");// "(%s+%d)",
1732 //regspic14[i].base,8*bank+regspic14[i].offset);
1736 if (options.useXstack) {
1737 pic14_emitcode("mov","a,psw");
1738 pic14_emitcode("movx","@%s,a",r->name);
1739 pic14_emitcode("inc","%s",r->name);
1740 pic14_emitcode("mov","_spx,%s",r->name);
1741 freeAsmop (NULL,aop,ic,TRUE);
1744 pic14_emitcode("push","psw");
1746 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1752 /*-----------------------------------------------------------------*/
1753 /* saveRegisters - will look for a call and save the registers */
1754 /*-----------------------------------------------------------------*/
1755 static void saveRegisters(iCode *lic)
1763 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1765 for (ic = lic ; ic ; ic = ic->next)
1766 if (ic->op == CALL || ic->op == PCALL)
1770 fprintf(stderr,"found parameter push with no function call\n");
1774 /* if the registers have been saved already then
1776 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
1779 /* find the registers in use at this time
1780 and push them away to safety */
1781 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1786 //fprintf(stderr, "ERROR: saveRegisters did not do anything to save registers, please report this as a bug.\n");
1788 dtype = operandType(IC_LEFT(ic));
1789 if (currFunc && dtype &&
1790 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
1791 IFFUNC_ISISR(currFunc->type) &&
1794 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
1797 /*-----------------------------------------------------------------*/
1798 /* unsaveRegisters - pop the pushed registers */
1799 /*-----------------------------------------------------------------*/
1800 static void unsaveRegisters (iCode *ic)
1807 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1808 /* find the registers in use at this time
1809 and push them away to safety */
1810 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1813 if (options.useXstack) {
1814 pic14_emitcode("mov","r0,%s",spname);
1815 for (i = pic14_nRegs ; i >= 0 ; i--) {
1816 if (bitVectBitValue(rsave,i)) {
1817 pic14_emitcode("dec","r0");
1818 pic14_emitcode("movx","a,@r0");
1819 pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
1823 pic14_emitcode("mov","%s,r0",spname);
1825 //for (i = pic14_nRegs ; i >= 0 ; i--) {
1826 // if (bitVectBitValue(rsave,i))
1827 // pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
1833 /*-----------------------------------------------------------------*/
1835 /*-----------------------------------------------------------------*/
1836 static void pushSide(operand * oper, int size)
1840 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1842 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1843 if (AOP_TYPE(oper) != AOP_REG &&
1844 AOP_TYPE(oper) != AOP_DIR &&
1846 pic14_emitcode("mov","a,%s",l);
1847 pic14_emitcode("push","acc");
1849 pic14_emitcode("push","%s",l);
1854 /*-----------------------------------------------------------------*/
1855 /* assignResultValue - */
1856 /*-----------------------------------------------------------------*/
1857 static void assignResultValue(operand * oper)
1859 int size = AOP_SIZE(oper);
1864 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1866 DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
1868 /* assign MSB first (passed via WREG) */
1870 get_returnvalue (oper, size, offset + GpsuedoStkPtr);
1876 /*-----------------------------------------------------------------*/
1877 /* genIpush - genrate code for pushing this gets a little complex */
1878 /*-----------------------------------------------------------------*/
1879 static void genIpush (iCode *ic)
1883 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
1885 int size, offset = 0 ;
1889 /* if this is not a parm push : ie. it is spill push
1890 and spill push is always done on the local stack */
1891 if (!ic->parmPush) {
1893 /* and the item is spilt then do nothing */
1894 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1897 aopOp(IC_LEFT(ic),ic,FALSE);
1898 size = AOP_SIZE(IC_LEFT(ic));
1899 /* push it on the stack */
1901 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1906 pic14_emitcode("push","%s",l);
1911 /* this is a paramter push: in this case we call
1912 the routine to find the call and save those
1913 registers that need to be saved */
1916 /* then do the push */
1917 aopOp(IC_LEFT(ic),ic,FALSE);
1920 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1921 size = AOP_SIZE(IC_LEFT(ic));
1924 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1925 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1926 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1928 pic14_emitcode("mov","a,%s",l);
1929 pic14_emitcode("push","acc");
1931 pic14_emitcode("push","%s",l);
1934 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1938 /*-----------------------------------------------------------------*/
1939 /* genIpop - recover the registers: can happen only for spilling */
1940 /*-----------------------------------------------------------------*/
1941 static void genIpop (iCode *ic)
1945 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
1946 assert (!"genIpop -- unimplemented");
1951 /* if the temp was not pushed then */
1952 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1955 aopOp(IC_LEFT(ic),ic,FALSE);
1956 size = AOP_SIZE(IC_LEFT(ic));
1959 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1962 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1966 /*-----------------------------------------------------------------*/
1967 /* unsaverbank - restores the resgister bank from stack */
1968 /*-----------------------------------------------------------------*/
1969 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1973 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
1979 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1981 if (options.useXstack) {
1983 r = getFreePtr(ic,&aop,FALSE);
1986 pic14_emitcode("mov","%s,_spx",r->name);
1987 pic14_emitcode("movx","a,@%s",r->name);
1988 pic14_emitcode("mov","psw,a");
1989 pic14_emitcode("dec","%s",r->name);
1992 pic14_emitcode ("pop","psw");
1995 for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
1996 if (options.useXstack) {
1997 pic14_emitcode("movx","a,@%s",r->name);
1998 //pic14_emitcode("mov","(%s+%d),a",
1999 // regspic14[i].base,8*bank+regspic14[i].offset);
2000 pic14_emitcode("dec","%s",r->name);
2003 pic14_emitcode("pop",""); //"(%s+%d)",
2004 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2007 if (options.useXstack) {
2009 pic14_emitcode("mov","_spx,%s",r->name);
2010 freeAsmop(NULL,aop,ic,TRUE);
2016 /*-----------------------------------------------------------------*/
2017 /* genCall - generates a call statement */
2018 /*-----------------------------------------------------------------*/
2019 static void genCall (iCode *ic)
2028 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2030 /* if caller saves & we have not saved then */
2034 /* if we are calling a function that is not using
2035 the same register bank then we need to save the
2036 destination registers on the stack */
2037 dtype = operandType(IC_LEFT(ic));
2038 if (currFunc && dtype &&
2039 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2040 IFFUNC_ISISR(currFunc->type) &&
2043 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2045 /* if send set is not empty the assign */
2048 /* For the Pic port, there is no data stack.
2049 * So parameters passed to functions are stored
2050 * in registers. (The pCode optimizer will get
2051 * rid of most of these :).
2053 int psuedoStkPtr=-1;
2054 int firstTimeThruLoop = 1;
2056 _G.sendSet = reverseSet(_G.sendSet);
2058 /* First figure how many parameters are getting passed */
2059 for (sic = setFirstItem(_G.sendSet) ; sic ;
2060 sic = setNextItem(_G.sendSet)) {
2062 aopOp(IC_LEFT(sic),sic,FALSE);
2063 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2064 freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2067 for (sic = setFirstItem(_G.sendSet) ; sic ;
2068 sic = setNextItem(_G.sendSet)) {
2069 int size, offset = 0;
2071 aopOp(IC_LEFT(sic),sic,FALSE);
2072 size = AOP_SIZE(IC_LEFT(sic));
2075 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2076 AopType(AOP_TYPE(IC_LEFT(sic))));
2078 if(!firstTimeThruLoop) {
2079 /* If this is not the first time we've been through the loop
2080 * then we need to save the parameter in a temporary
2081 * register. The last byte of the last parameter is
2083 emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2086 firstTimeThruLoop=0;
2088 mov2w_op (IC_LEFT(sic), offset);
2091 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2096 sym = OP_SYMBOL(IC_LEFT(ic));
2097 name = sym->rname[0] ? sym->rname : sym->name;
2099 * As SDCC emits code as soon as it reaches the end of each
2100 * function's definition, prototyped functions that are implemented
2101 * after the current one are always considered EXTERN, which
2102 * introduces many unneccessary PAGESEL instructions.
2103 * XXX: Use a post pass to iterate over all `CALL _name' statements
2104 * and insert `PAGESEL _name' and `PAGESEL $' around the CALL
2105 * only iff there is no definition of the function in the whole
2106 * file (might include this in the PAGESEL pass).
2108 isExtern = IS_EXTERN(sym->etype) || pic14_inISR;
2110 /* Extern functions and ISRs maybe on a different page;
2111 * must call pagesel */
2112 emitpcode(POC_PAGESEL,popGetWithString(name,1));
2114 emitpcode(POC_CALL,popGetWithString(name,isExtern));
2116 /* May have returned from a different page;
2117 * must use pagesel to restore PCLATH before next
2118 * goto or call instruction */
2119 emitpcode(POC_PAGESEL,popGetWithString("$",0));
2122 /* if we need assign a result value */
2123 if ((IS_ITEMP(IC_RESULT(ic)) &&
2124 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2125 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2126 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2129 aopOp(IC_RESULT(ic),ic,FALSE);
2132 assignResultValue(IC_RESULT(ic));
2134 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2135 AopType(AOP_TYPE(IC_RESULT(ic))));
2137 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2140 /* if register bank was saved then pop them */
2142 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2144 /* if we hade saved some registers then unsave them */
2145 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2146 unsaveRegisters (ic);
2151 /*-----------------------------------------------------------------*/
2152 /* genPcall - generates a call by pointer statement */
2153 /*-----------------------------------------------------------------*/
2154 static void genPcall (iCode *ic)
2157 symbol *albl = newiTempLabel(NULL);
2158 symbol *blbl = newiTempLabel(NULL);
2165 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2166 /* if caller saves & we have not saved then */
2170 /* if we are calling a function that is not using
2171 the same register bank then we need to save the
2172 destination registers on the stack */
2173 dtype = operandType(IC_LEFT(ic));
2174 if (currFunc && dtype &&
2175 IFFUNC_ISISR(currFunc->type) &&
2176 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2177 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2180 aopOp(left,ic,FALSE);
2181 DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2183 poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2185 pushSide(IC_LEFT(ic), FPTRSIZE);
2187 /* if send set is not empty, assign parameters */
2190 DEBUGpic14_emitcode ("; ***","%s %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2191 /* no way to pass args - W always gets used to make the call */
2193 /* first idea - factor out a common helper function and call it.
2194 But don't know how to get it generated only once in its own block
2196 if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2199 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2200 DEBUGpic14_emitcode ("; ***","%s %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2201 buffer = Safe_calloc(1,strlen(rname)+16);
2202 sprintf(buffer, "%s_goto_helper", rname);
2203 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2207 emitpcode(POC_CALL,popGetLabel(albl->key));
2208 pcop = popGetLabel(blbl->key);
2209 emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
2210 emitpcode(POC_GOTO,pcop);
2211 emitpLabel(albl->key);
2213 emitpcode(poc,popGetAddr(AOP(left),1,0));
2214 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2215 emitpcode(poc,popGetAddr(AOP(left),0,0));
2216 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2218 emitpLabel(blbl->key);
2220 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2222 /* if we need to assign a result value */
2223 if ((IS_ITEMP(IC_RESULT(ic)) &&
2224 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2225 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2226 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2229 aopOp(IC_RESULT(ic),ic,FALSE);
2234 assignResultValue(IC_RESULT(ic));
2236 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2239 /* if register bank was saved then unsave them */
2240 if (currFunc && dtype &&
2241 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2242 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2244 /* if we hade saved some registers then
2247 unsaveRegisters (ic);
2251 /*-----------------------------------------------------------------*/
2252 /* resultRemat - result is rematerializable */
2253 /*-----------------------------------------------------------------*/
2254 static int resultRemat (iCode *ic)
2256 // DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2259 if (SKIP_IC(ic) || ic->op == IFX)
2262 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2263 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2264 if (sym->remat && !POINTER_SET(ic))
2271 /*-----------------------------------------------------------------*/
2272 /* genFunction - generated code for function entry */
2273 /*-----------------------------------------------------------------*/
2274 static void genFunction (iCode *ic)
2281 DEBUGpic14_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2283 labelOffset += (max_key+4);
2287 /* create the function header */
2288 pic14_emitcode(";","-----------------------------------------");
2289 pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2290 pic14_emitcode(";","-----------------------------------------");
2292 /* prevent this symbol from being emitted as 'extern' */
2293 pic14_stringInSet(sym->rname, &pic14_localFunctions, 1);
2295 pic14_emitcode("","%s:",sym->rname);
2296 addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2298 /* mark symbol as NOT extern (even if it was declared so previously) */
2299 assert(IS_SPEC(sym->etype));
2300 SPEC_EXTR(sym->etype) = 0;
2302 if (!SPEC_OCLS(sym->etype)) SPEC_OCLS(sym->etype) = code;
2303 addSetIfnotP(&SPEC_OCLS(sym->etype)->syms, sym);
2305 ftype = operandType(IC_LEFT(ic));
2307 /* if critical function then turn interrupts off */
2308 if (IFFUNC_ISCRITICAL(ftype))
2309 pic14_emitcode("clr","ea");
2311 /* here we need to generate the equates for the
2312 register bank if required */
2314 if (FUNC_REGBANK(ftype) != rbank) {
2317 rbank = FUNC_REGBANK(ftype);
2318 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2319 if (strcmp(regspic14[i].base,"0") == 0)
2320 pic14_emitcode("","%s = 0x%02x",
2322 8*rbank+regspic14[i].offset);
2324 pic14_emitcode ("","%s = %s + 0x%02x",
2327 8*rbank+regspic14[i].offset);
2332 /* if this is an interrupt service routine */
2334 if (IFFUNC_ISISR(sym->type)) {
2336 emitpcode(POC_MOVWF, popCopyReg(&pc_wsave));
2337 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2338 /* XXX: Why? Does this assume that ssave and psave reside
2339 * in a shared bank or bank0? We cannot guarantee the
2342 emitpcode(POC_CLRF, popCopyReg(&pc_status));
2343 emitpcode(POC_MOVWF, popCopyReg(&pc_ssave));
2344 //emitpcode(POC_MOVWF, popGetExternal("___sdcc_saved_status",1 ));
2345 emitpcode(POC_MOVFW, popCopyReg(&pc_pclath));
2346 /* during an interrupt PCLATH must be cleared before a goto or call statement */
2347 emitpcode(POC_CLRF, popCopyReg(&pc_pclath));
2348 emitpcode(POC_MOVWF, popCopyReg(&pc_psave));
2349 //emitpcode(POC_MOVWF, popGetExternal("___sdcc_saved_pclath", 1));
2350 emitpcode(POC_MOVFW, popCopyReg(&pc_fsr));
2351 emitpcode(POC_MOVWF, popGetExternal("___sdcc_saved_fsr", 1));
2353 pBlockConvert2ISR(pb);
2354 pic14_hasInterrupt = 1;
2356 /* if callee-save to be used for this function
2357 then save the registers being used in this function */
2358 if (IFFUNC_CALLEESAVES(sym->type)) {
2361 /* if any registers used */
2362 if (sym->regsUsed) {
2363 /* save the registers used */
2364 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2365 if (bitVectBitValue(sym->regsUsed,i)) {
2366 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2374 /* set the register bank to the desired value */
2375 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2376 pic14_emitcode("push","psw");
2377 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);
2380 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2382 if (options.useXstack) {
2383 pic14_emitcode("mov","r0,%s",spname);
2384 pic14_emitcode("mov","a,_bp");
2385 pic14_emitcode("movx","@r0,a");
2386 pic14_emitcode("inc","%s",spname);
2390 /* set up the stack */
2391 pic14_emitcode ("push","_bp"); /* save the callers stack */
2393 pic14_emitcode ("mov","_bp,%s",spname);
2396 /* adjust the stack for the function */
2401 werror(W_STACK_OVERFLOW,sym->name);
2403 if (i > 3 && sym->recvSize < 4) {
2405 pic14_emitcode ("mov","a,sp");
2406 pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2407 pic14_emitcode ("mov","sp,a");
2412 pic14_emitcode("inc","sp");
2417 pic14_emitcode ("mov","a,_spx");
2418 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2419 pic14_emitcode ("mov","_spx,a");
2424 /*-----------------------------------------------------------------*/
2425 /* genEndFunction - generates epilogue for functions */
2426 /*-----------------------------------------------------------------*/
2427 static void genEndFunction (iCode *ic)
2429 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2433 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2435 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2437 pic14_emitcode ("mov","%s,_bp",spname);
2440 /* if use external stack but some variables were
2441 added to the local stack then decrement the
2443 if (options.useXstack && sym->stack) {
2444 pic14_emitcode("mov","a,sp");
2445 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2446 pic14_emitcode("mov","sp,a");
2450 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2451 if (options.useXstack) {
2452 pic14_emitcode("mov","r0,%s",spname);
2453 pic14_emitcode("movx","a,@r0");
2454 pic14_emitcode("mov","_bp,a");
2455 pic14_emitcode("dec","%s",spname);
2459 pic14_emitcode ("pop","_bp");
2463 /* restore the register bank */
2464 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2465 pic14_emitcode ("pop","psw");
2467 if (IFFUNC_ISISR(sym->type)) {
2469 /* now we need to restore the registers */
2470 /* if this isr has no bank i.e. is going to
2471 run with bank 0 , then we need to save more
2473 if (!FUNC_REGBANK(sym->type)) {
2475 /* if this function does not call any other
2476 function then we can be economical and
2477 save only those registers that are used */
2478 if (! IFFUNC_HASFCALL(sym->type)) {
2481 /* if any registers used */
2482 if (sym->regsUsed) {
2483 /* save the registers used */
2484 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2485 if (bitVectBitValue(sym->regsUsed,i)) {
2486 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2492 /* this function has a function call; cannot
2493 determines register usage so we will have the
2495 unsaverbank(0,ic,FALSE);
2499 /* if debug then send end of function */
2500 if (options.debug && debugFile && currFunc) {
2501 debugFile->writeEndFunction (currFunc, ic, 1);
2504 emitpcode(POC_MOVFW, popGetExternal("___sdcc_saved_fsr", 1));
2505 emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
2506 //emitpcode(POC_MOVFW, popGetExternal("___sdcc_saved_pclath", 1));
2507 emitpcode(POC_MOVFW, popCopyReg(&pc_psave));
2508 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
2509 emitpcode(POC_CLRF, popCopyReg(&pc_status)); // see genFunction
2510 //emitpcode(POC_SWAPFW, popGetExternal("___sdcc_saved_status", 1));
2511 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
2512 emitpcode(POC_MOVWF, popCopyReg(&pc_status));
2513 emitpcode(POC_SWAPF, popCopyReg(&pc_wsave));
2514 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
2515 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
2516 emitpcodeNULLop(POC_RETFIE);
2519 if (IFFUNC_ISCRITICAL(sym->type))
2520 pic14_emitcode("setb","ea");
2522 if (IFFUNC_CALLEESAVES(sym->type)) {
2525 /* if any registers used */
2526 if (sym->regsUsed) {
2527 /* save the registers used */
2528 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2529 if (bitVectBitValue(sym->regsUsed,i)) {
2530 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2536 /* if debug then send end of function */
2537 if (options.debug && debugFile && currFunc) {
2538 debugFile->writeEndFunction (currFunc, ic, 1);
2541 pic14_emitcode ("return","");
2542 emitpcodeNULLop(POC_RETURN);
2544 /* Mark the end of a function */
2545 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
2550 /*-----------------------------------------------------------------*/
2551 /* genRet - generate code for return statement */
2552 /*-----------------------------------------------------------------*/
2553 static void genRet (iCode *ic)
2555 int size,offset = 0;
2559 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2560 /* if we have no return value then
2561 just generate the "ret" */
2565 /* we have something to return then
2566 move the return value into place */
2567 aopOp(IC_LEFT(ic),ic,FALSE);
2568 size = AOP_SIZE(IC_LEFT(ic));
2570 for (offset = 0; offset < size; offset++)
2572 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
2575 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2578 /* generate a jump to the return label
2579 if the next is not the return statement */
2580 if (!(ic->next && ic->next->op == LABEL &&
2581 IC_LABEL(ic->next) == returnLabel)) {
2583 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
2588 /*-----------------------------------------------------------------*/
2589 /* genLabel - generates a label */
2590 /*-----------------------------------------------------------------*/
2591 static void genLabel (iCode *ic)
2595 /* special case never generate */
2596 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2597 if (IC_LABEL(ic) == entryLabel)
2600 emitpLabel(IC_LABEL(ic)->key);
2601 pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
2604 /*-----------------------------------------------------------------*/
2605 /* genGoto - generates a goto */
2606 /*-----------------------------------------------------------------*/
2608 static void genGoto (iCode *ic)
2612 emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
2613 pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
2617 /*-----------------------------------------------------------------*/
2618 /* genMultbits :- multiplication of bits */
2619 /*-----------------------------------------------------------------*/
2620 static void genMultbits (operand *left,
2625 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2627 if(!pic14_sameRegs(AOP(result),AOP(right)))
2628 emitpcode(POC_BSF, popGet(AOP(result),0));
2630 emitpcode(POC_BTFSC,popGet(AOP(right),0));
2631 emitpcode(POC_BTFSS,popGet(AOP(left),0));
2632 emitpcode(POC_BCF, popGet(AOP(result),0));
2637 /*-----------------------------------------------------------------*/
2638 /* genMultOneByte : 8 bit multiplication & division */
2639 /*-----------------------------------------------------------------*/
2640 static void genMultOneByte (operand *left,
2644 char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
2652 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2653 DEBUGpic14_AopType(__LINE__,left,right,result);
2654 DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
2656 /* (if two literals, the value is computed before) */
2657 /* if one literal, literal on the right */
2658 if (AOP_TYPE(left) == AOP_LIT){
2664 assert (AOP_SIZE(left) == AOP_SIZE(right));
2666 size = min(AOP_SIZE(result),AOP_SIZE(left));
2667 offset = Gstack_base_addr - (2*size - 1);
2669 /* pass right operand as argument */
2670 for (i=0; i < size; i++)
2672 mov2w (AOP(right), i);
2673 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
2676 /* pass left operand as argument */
2677 for (i=0; i < size; i++)
2679 mov2w (AOP(left), i);
2680 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
2682 assert (offset == Gstack_base_addr);
2684 /* call library routine */
2685 assert (size > 0 && size <= 4);
2686 call_libraryfunc (func[size]);
2689 movwf (AOP(result), size-1);
2690 for (i=0; i < size - 1; i++)
2692 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
2693 movwf (AOP(result), size - 2 - i);
2696 /* now (zero-/sign) extend the result to its size */
2697 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2700 /*-----------------------------------------------------------------*/
2701 /* genMult - generates code for multiplication */
2702 /*-----------------------------------------------------------------*/
2703 static void genMult (iCode *ic)
2705 operand *left = IC_LEFT(ic);
2706 operand *right = IC_RIGHT(ic);
2707 operand *result= IC_RESULT(ic);
2711 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2712 /* assign the amsops */
2713 aopOp (left,ic,FALSE);
2714 aopOp (right,ic,FALSE);
2715 aopOp (result,ic,TRUE);
2717 DEBUGpic14_AopType(__LINE__,left,right,result);
2719 /* special cases first */
2721 if (AOP_TYPE(left) == AOP_CRY &&
2722 AOP_TYPE(right)== AOP_CRY) {
2723 genMultbits(left,right,result);
2727 /* if both are of size == 1 */
2728 if (AOP_SIZE(left) == 1 &&
2729 AOP_SIZE(right) == 1 ) {
2730 genMultOneByte(left,right,result);
2734 /* should have been converted to function call */
2738 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2739 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2740 freeAsmop(result,NULL,ic,TRUE);
2743 /*-----------------------------------------------------------------*/
2744 /* genDivbits :- division of bits */
2745 /*-----------------------------------------------------------------*/
2746 static void genDivbits (operand *left,
2755 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2756 /* the result must be bit */
2757 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
2758 l = aopGet(AOP(left),0,FALSE,FALSE);
2762 pic14_emitcode("div","ab");
2763 pic14_emitcode("rrc","a");
2764 aopPut(AOP(result),"c",0);
2767 /*-----------------------------------------------------------------*/
2768 /* genDivOneByte : 8 bit division */
2769 /*-----------------------------------------------------------------*/
2770 static void genDivOneByte (operand *left,
2778 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2780 assert (AOP_SIZE(right) == 1);
2781 assert (AOP_SIZE(left) == 1);
2783 size = min(AOP_SIZE(result),AOP_SIZE(left));
2784 sign = !(SPEC_USIGN(operandType(left))
2785 && SPEC_USIGN(operandType(right)));
2787 if (AOP_TYPE(right) == AOP_LIT)
2789 /* XXX: might add specialized code */
2794 /* unsigned division */
2796 mov2w(AOP(right),0);
2797 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
2799 call_libraryfunc("__divuchar");
2800 movwf(AOP(result),0);
2805 temp = popGetTempReg();
2806 lbl = newiTempLabel(NULL);
2808 /* XXX: improve this naive approach:
2809 [result] = [a] / [b]
2810 ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
2814 movwf temp // temp <-- left
2815 movf right,W // W <-- right
2819 subwf temp,F // temp <-- temp - W
2820 skipNC // subwf clears CARRY (i.e. sets BORROW) if temp < W
2822 decf result // we just subtract once too often
2825 /* XXX: This loops endlessly on DIVIDE BY ZERO */
2826 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
2829 emitpcode(POC_MOVWF, temp);
2830 mov2w(AOP(right),0);
2831 emitpcode(POC_CLRF, popGet(AOP(result),0));
2833 emitpLabel(lbl->key);
2834 emitpcode(POC_INCF, popGet(AOP(result),0));
2835 emitpcode(POC_SUBWF, temp);
2837 emitpcode(POC_GOTO, popGetLabel(lbl->key));
2838 emitpcode(POC_DECF, popGet(AOP(result),0));
2839 popReleaseTempReg(temp);
2844 /* signed division */
2845 mov2w(AOP(right),0);
2846 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
2848 call_libraryfunc("__divschar");
2849 movwf(AOP(result),0);
2852 /* now performed the signed/unsigned division -- extend result */
2853 addSign(result, 1, sign);
2856 /*-----------------------------------------------------------------*/
2857 /* genDiv - generates code for division */
2858 /*-----------------------------------------------------------------*/
2859 static void genDiv (iCode *ic)
2861 operand *left = IC_LEFT(ic);
2862 operand *right = IC_RIGHT(ic);
2863 operand *result= IC_RESULT(ic);
2866 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2867 /* assign the amsops */
2868 aopOp (left,ic,FALSE);
2869 aopOp (right,ic,FALSE);
2870 aopOp (result,ic,TRUE);
2872 /* special cases first */
2874 if (AOP_TYPE(left) == AOP_CRY &&
2875 AOP_TYPE(right)== AOP_CRY) {
2876 genDivbits(left,right,result);
2880 /* if both are of size == 1 */
2881 if (AOP_SIZE(left) == 1 &&
2882 AOP_SIZE(right) == 1 ) {
2883 genDivOneByte(left,right,result);
2887 /* should have been converted to function call */
2890 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2891 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2892 freeAsmop(result,NULL,ic,TRUE);
2895 /*-----------------------------------------------------------------*/
2896 /* genModOneByte : 8 bit modulus */
2897 /*-----------------------------------------------------------------*/
2898 static void genModOneByte (operand *left,
2906 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2908 assert (AOP_SIZE(right) == 1);
2909 assert (AOP_SIZE(left) == 1);
2911 size = min(AOP_SIZE(result),AOP_SIZE(left));
2912 sign = !(SPEC_USIGN(operandType(left))
2913 && SPEC_USIGN(operandType(right)));
2915 if (AOP_TYPE(right) == AOP_LIT)
2917 /* XXX: might add specialized code */
2922 /* unsigned division */
2924 mov2w(AOP(right),0);
2925 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
2927 call_libraryfunc("__moduchar");
2928 movwf(AOP(result),0);
2933 lbl = newiTempLabel(NULL);
2935 assert(!pic14_sameRegs(AOP(right),AOP(result)));
2937 /* XXX: improve this naive approach:
2938 [result] = [a] % [b]
2939 ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
2943 movwf result // result <-- left
2944 movf right,W // W <-- right
2946 subwf result,F // result <-- result - W
2947 skipNC // subwf clears CARRY (i.e. sets BORROW) if result < W
2949 addwf result, F // we just subtract once too often
2952 /* XXX: This loops endlessly on DIVIDE BY ZERO */
2953 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
2955 if (!pic14_sameRegs(AOP(left), AOP(result)))
2958 emitpcode(POC_MOVWF, popGet(AOP(result),0));
2960 mov2w(AOP(right),0);
2962 emitpLabel(lbl->key);
2963 emitpcode(POC_SUBWF, popGet(AOP(result),0));
2965 emitpcode(POC_GOTO, popGetLabel(lbl->key));
2966 emitpcode(POC_ADDWF, popGet(AOP(result),0));
2971 /* signed division */
2972 mov2w(AOP(right),0);
2973 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
2975 call_libraryfunc("__modschar");
2976 movwf(AOP(result),0);
2979 /* now we performed the signed/unsigned modulus -- extend result */
2980 addSign(result, 1, sign);
2983 /*-----------------------------------------------------------------*/
2984 /* genMod - generates code for division */
2985 /*-----------------------------------------------------------------*/
2986 static void genMod (iCode *ic)
2988 operand *left = IC_LEFT(ic);
2989 operand *right = IC_RIGHT(ic);
2990 operand *result= IC_RESULT(ic);
2993 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2994 /* assign the amsops */
2995 aopOp (left,ic,FALSE);
2996 aopOp (right,ic,FALSE);
2997 aopOp (result,ic,TRUE);
2999 /* if both are of size == 1 */
3000 if (AOP_SIZE(left) == 1 &&
3001 AOP_SIZE(right) == 1 ) {
3002 genModOneByte(left,right,result);
3006 /* should have been converted to function call */
3010 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3011 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3012 freeAsmop(result,NULL,ic,TRUE);
3015 /*-----------------------------------------------------------------*/
3016 /* genIfxJump :- will create a jump depending on the ifx */
3017 /*-----------------------------------------------------------------*/
3019 note: May need to add parameter to indicate when a variable is in bit space.
3021 static void genIfxJump (iCode *ic, char *jval)
3025 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3026 /* if true label then we jump if condition
3028 if ( IC_TRUE(ic) ) {
3030 if(strcmp(jval,"a") == 0)
3032 else if (strcmp(jval,"c") == 0)
3035 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3036 emitpcode(POC_BTFSC, newpCodeOpBit(jval,-1,1));
3039 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3040 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3044 /* false label is present */
3045 if(strcmp(jval,"a") == 0)
3047 else if (strcmp(jval,"c") == 0)
3050 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3051 emitpcode(POC_BTFSS, newpCodeOpBit(jval,-1,1));
3054 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3055 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3060 /* mark the icode as generated */
3064 /*-----------------------------------------------------------------*/
3066 /*-----------------------------------------------------------------*/
3067 static void genSkipc(resolvedIfx *rifx)
3078 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3079 emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3080 rifx->generated = 1;
3083 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3084 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
3085 #define DEBUGpc emitpComment
3087 /*-----------------------------------------------------------------*/
3088 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
3089 /* aop (if it's NOT a literal) or from lit (if */
3090 /* aop is a literal) */
3091 /*-----------------------------------------------------------------*/
3092 static void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset)
3094 if (aop->type == AOP_LIT) {
3095 emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3097 emitpcode (POC_MOVFW, popGet (aop, offset));
3101 /* genCmp performs a left < right comparison, stores
3102 * the outcome in result (if != NULL) and generates
3103 * control flow code for the ifx (if != NULL).
3105 * This version leaves in sequences like
3106 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3107 * which should be optmized by the peephole
3108 * optimizer - RN 2005-01-01 */
3109 static void genCmp (operand *left,operand *right,
3110 operand *result, iCode *ifx, int sign)
3120 int invert_result = 0;
3124 assert (AOP_SIZE(left) == AOP_SIZE(right));
3125 assert (left && right);
3127 size = AOP_SIZE(right) - 1;
3128 mask = (0x100UL << (size*8)) - 1;
3129 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3134 resolveIfx (&rIfx, ifx);
3136 /**********************************************************************
3137 * handle bits - bit compares are promoted to int compares seemingly! *
3138 **********************************************************************/
3140 // THIS IS COMPLETELY UNTESTED!
3141 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3142 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3143 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3144 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3147 // 1 < {0,1} is false --> clear C by skipping the next instruction
3148 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3149 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3150 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3151 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3152 emitCLRC; // only skipped for left=0 && right=1
3154 goto correct_result_in_carry;
3158 /*************************************************
3159 * make sure that left is register (or the like) *
3160 *************************************************/
3161 if (!isAOP_REGlike(left)) {
3162 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
3163 assert (isAOP_LIT(left));
3164 assert (isAOP_REGlike(right));
3165 // swap left and right
3166 // left < right <==> right > left <==> (right >= left + 1)
3167 lit = ulFromVal(AOP(left)->aopu.aop_lit);
3169 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
3170 // MAXVALUE < right? always false
3171 if (performedLt) emitCLRC; else emitSETC;
3172 goto correct_result_in_carry;
3175 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
3176 // that's why we handled it above.
3183 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
3184 } else if (isAOP_LIT(right)) {
3185 lit = ulFromVal(AOP(right)->aopu.aop_lit);
3188 assert (isAOP_REGlike(left)); // left must be register or the like
3189 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
3191 /*************************************************
3192 * special cases go here *
3193 *************************************************/
3195 if (isAOP_LIT(right)) {
3197 // unsigned comparison to a literal
3198 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
3200 // unsigned left < 0? always false
3201 if (performedLt) emitCLRC; else emitSETC;
3202 goto correct_result_in_carry;
3205 // signed comparison to a literal
3206 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
3207 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
3208 // signed left < 0x80000000? always false
3209 if (performedLt) emitCLRC; else emitSETC;
3210 goto correct_result_in_carry;
3211 } else if (lit == 0) {
3212 // compare left < 0; set CARRY if SIGNBIT(left) is set
3213 if (performedLt) emitSETC; else emitCLRC;
3214 emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
3215 if (performedLt) emitCLRC; else emitSETC;
3216 goto correct_result_in_carry;
3219 } // right is literal
3221 /*************************************************
3222 * perform a general case comparison *
3223 * make sure we get CARRY==1 <==> left >= right *
3224 *************************************************/
3225 // compare most significant bytes
3226 //DEBUGpc ("comparing bytes at offset %d", size);
3228 // unsigned comparison
3229 pic14_mov2w_regOrLit (AOP(right), lit, size);
3230 emitpcode (POC_SUBFW, popGet (AOP(left), size));
3232 // signed comparison
3233 // (add 2^n to both operands then perform an unsigned comparison)
3234 if (isAOP_LIT(right)) {
3235 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
3236 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
3238 if (litbyte == 0x80) {
3239 // left >= 0x80 -- always true, but more bytes to come
3240 mov2w (AOP(left), size);
3241 emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
3244 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
3245 mov2w (AOP(left), size);
3246 emitpcode (POC_ADDLW, popGetLit (0x80));
3247 emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
3250 pCodeOp *pctemp = popGetTempReg();
3251 mov2w (AOP(left), size);
3252 emitpcode (POC_ADDLW, popGetLit (0x80));
3253 emitpcode (POC_MOVWF, pctemp);
3254 mov2w (AOP(right), size);
3255 emitpcode (POC_ADDLW, popGetLit (0x80));
3256 emitpcode (POC_SUBFW, pctemp);
3257 popReleaseTempReg(pctemp);
3261 // compare remaining bytes (treat as unsigned case from above)
3262 templbl = newiTempLabel ( NULL );
3265 //DEBUGpc ("comparing bytes at offset %d", offs);
3267 emitpcode (POC_GOTO, popGetLabel (templbl->key));
3268 pic14_mov2w_regOrLit (AOP(right), lit, offs);
3269 emitpcode (POC_SUBFW, popGet (AOP(left), offs));
3271 emitpLabel (templbl->key);
3272 goto result_in_carry;
3276 /****************************************************
3277 * now CARRY contains the result of the comparison: *
3278 * SUBWF sets CARRY iff *
3279 * F-W >= 0 <==> F >= W <==> !(F < W) *
3280 * (F=left, W=right) *
3281 ****************************************************/
3285 // value will be used in the following genSkipc()
3286 rIfx.condition ^= 1;
3289 correct_result_in_carry:
3291 // assign result to variable (if neccessary)
3292 if (result && AOP_TYPE(result) != AOP_CRY) {
3293 //DEBUGpc ("assign result");
3294 size = AOP_SIZE(result);
3296 emitpcode (POC_CLRF, popGet (AOP(result), size));
3298 if (invert_result) {
3300 emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
3302 emitpcode (POC_RLF, popGet (AOP(result), 0));
3306 // perform conditional jump
3308 //DEBUGpc ("generate control flow");
3314 /*-----------------------------------------------------------------*/
3315 /* genCmpGt :- greater than comparison */
3316 /*-----------------------------------------------------------------*/
3317 static void genCmpGt (iCode *ic, iCode *ifx)
3319 operand *left, *right, *result;
3320 sym_link *letype , *retype;
3324 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3326 right= IC_RIGHT(ic);
3327 result = IC_RESULT(ic);
3329 letype = getSpec(operandType(left));
3330 retype =getSpec(operandType(right));
3331 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3332 /* assign the amsops */
3333 aopOp (left,ic,FALSE);
3334 aopOp (right,ic,FALSE);
3335 aopOp (result,ic,TRUE);
3337 genCmp(right, left, result, ifx, sign);
3339 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3340 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3341 freeAsmop(result,NULL,ic,TRUE);
3344 /*-----------------------------------------------------------------*/
3345 /* genCmpLt - less than comparisons */
3346 /*-----------------------------------------------------------------*/
3347 static void genCmpLt (iCode *ic, iCode *ifx)
3349 operand *left, *right, *result;
3350 sym_link *letype , *retype;
3354 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3356 right= IC_RIGHT(ic);
3357 result = IC_RESULT(ic);
3359 letype = getSpec(operandType(left));
3360 retype =getSpec(operandType(right));
3361 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3363 /* assign the amsops */
3364 aopOp (left,ic,FALSE);
3365 aopOp (right,ic,FALSE);
3366 aopOp (result,ic,TRUE);
3368 genCmp(left, right, result, ifx, sign);
3370 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3371 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3372 freeAsmop(result,NULL,ic,TRUE);
3375 /*-----------------------------------------------------------------*/
3376 /* genCmpEq - generates code for equal to */
3377 /*-----------------------------------------------------------------*/
3378 static void genCmpEq (iCode *ic, iCode *ifx)
3380 operand *left, *right, *result;
3382 symbol *false_label;
3385 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3388 DEBUGpic14_emitcode ("; ifx is non-null","");
3390 DEBUGpic14_emitcode ("; ifx is null","");
3392 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3393 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3394 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3396 DEBUGpic14_AopType(__LINE__,left,right,result);
3398 /* if literal, move literal to right */
3399 if (op_isLitLike (IC_LEFT(ic))) {
3400 operand *tmp = right ;
3406 if (ifx && !IC_TRUE(ifx))
3408 assert (IC_FALSE(ifx));
3409 false_label = IC_FALSE(ifx);
3412 size = min(AOP_SIZE(left),AOP_SIZE(right));
3413 assert(!pic14_sameRegs(AOP(result),AOP(left)));
3414 assert(!pic14_sameRegs(AOP(result),AOP(right)));
3416 /* assume left != right */
3419 for (i=0; i < AOP_SIZE(result); i++)
3421 emitpcode(POC_CLRF, popGet(AOP(result),i));
3425 if (AOP_TYPE(right) == AOP_LIT)
3427 unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit);
3429 size = AOP_SIZE(left);
3430 assert(!op_isLitLike(left));
3435 mov2w(AOP(left), 0);
3436 for (i=1; i < size; i++)
3437 emitpcode(POC_IORFW,popGet(AOP(left),i));
3438 /* now Z is set iff `left == right' */
3440 if (!false_label) false_label = newiTempLabel(NULL);
3441 emitpcode(POC_GOTO, popGetLabel(false_label->key));
3445 for (i=0; i < size; i++)
3448 emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
3449 /* now Z is cleared if `left != right' */
3451 if (!false_label) false_label = newiTempLabel(NULL);
3452 emitpcode(POC_GOTO, popGetLabel(false_label->key));
3459 /* right is no literal */
3462 for (i=0; i < size; i++)
3464 mov2w(AOP(right),i);
3465 emitpcode(POC_XORFW,popGet(AOP(left),i));
3466 /* now Z is cleared if `left != right' */
3468 if (!false_label) false_label = newiTempLabel(NULL);
3469 emitpcode(POC_GOTO, popGetLabel(false_label->key));
3473 /* if we reach here, left == right */
3475 if (AOP_SIZE(result) > 0)
3477 emitpcode(POC_INCF, popGet(AOP(result),0));
3480 if (ifx && IC_TRUE(ifx))
3482 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3485 if (false_label && (!ifx || IC_TRUE(ifx)))
3486 emitpLabel(false_label->key);
3488 if (ifx) ifx->generated = 1;
3490 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3491 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3492 freeAsmop(result,NULL,ic,TRUE);
3495 /*-----------------------------------------------------------------*/
3496 /* ifxForOp - returns the icode containing the ifx for operand */
3497 /*-----------------------------------------------------------------*/
3498 static iCode *ifxForOp ( operand *op, iCode *ic )
3501 /* if true symbol then needs to be assigned */
3502 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3503 if (IS_TRUE_SYMOP(op))
3506 /* if this has register type condition and
3507 the next instruction is ifx with the same operand
3508 and live to of the operand is upto the ifx only then */
3510 ic->next->op == IFX &&
3511 IC_COND(ic->next)->key == op->key &&
3512 OP_SYMBOL(op)->liveTo <= ic->next->seq )
3516 ic->next->op == IFX &&
3517 IC_COND(ic->next)->key == op->key) {
3518 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
3522 DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
3524 ic->next->op == IFX)
3525 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
3528 ic->next->op == IFX &&
3529 IC_COND(ic->next)->key == op->key) {
3530 DEBUGpic14_emitcode ("; "," key is okay");
3531 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
3532 OP_SYMBOL(op)->liveTo,
3539 /*-----------------------------------------------------------------*/
3540 /* genAndOp - for && operation */
3541 /*-----------------------------------------------------------------*/
3542 static void genAndOp (iCode *ic)
3544 operand *left,*right, *result;
3548 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3549 /* note here that && operations that are in an
3550 if statement are taken away by backPatchLabels
3551 only those used in arthmetic operations remain */
3552 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3553 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3554 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3556 DEBUGpic14_AopType(__LINE__,left,right,result);
3558 emitpcode(POC_MOVFW,popGet(AOP(left),0));
3559 emitpcode(POC_ANDFW,popGet(AOP(right),0));
3560 emitpcode(POC_MOVWF,popGet(AOP(result),0));
3562 /* if both are bit variables */
3563 /* if (AOP_TYPE(left) == AOP_CRY && */
3564 /* AOP_TYPE(right) == AOP_CRY ) { */
3565 /* pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
3566 /* pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
3567 /* pic14_outBitC(result); */
3569 /* tlbl = newiTempLabel(NULL); */
3570 /* pic14_toBoolean(left); */
3571 /* pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
3572 /* pic14_toBoolean(right); */
3573 /* pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
3574 /* pic14_outBitAcc(result); */
3577 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3578 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3579 freeAsmop(result,NULL,ic,TRUE);
3583 /*-----------------------------------------------------------------*/
3584 /* genOrOp - for || operation */
3585 /*-----------------------------------------------------------------*/
3588 modified this code, but it doesn't appear to ever get called
3591 static void genOrOp (iCode *ic)
3593 operand *left,*right, *result;
3597 /* note here that || operations that are in an
3598 if statement are taken away by backPatchLabels
3599 only those used in arthmetic operations remain */
3601 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3602 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3603 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3604 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3606 DEBUGpic14_AopType(__LINE__,left,right,result);
3608 for (i=0; i < AOP_SIZE(result); i++)
3610 emitpcode(POC_CLRF, popGet(AOP(result), i));
3613 tlbl = newiTempLabel(NULL);
3614 pic14_toBoolean(left);
3616 emitpcode(POC_GOTO, popGetLabel(tlbl->key));
3617 pic14_toBoolean(right);
3618 emitpLabel(tlbl->key);
3619 /* here Z is clear IFF `left || right' */
3621 emitpcode(POC_INCF, popGet(AOP(result), 0));
3623 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3624 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3625 freeAsmop(result,NULL,ic,TRUE);
3628 /*-----------------------------------------------------------------*/
3629 /* isLiteralBit - test if lit == 2^n */
3630 /*-----------------------------------------------------------------*/
3631 static int isLiteralBit(unsigned long lit)
3633 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
3634 0x100L,0x200L,0x400L,0x800L,
3635 0x1000L,0x2000L,0x4000L,0x8000L,
3636 0x10000L,0x20000L,0x40000L,0x80000L,
3637 0x100000L,0x200000L,0x400000L,0x800000L,
3638 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
3639 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
3643 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3644 for(idx = 0; idx < 32; idx++)
3650 /*-----------------------------------------------------------------*/
3651 /* continueIfTrue - */
3652 /*-----------------------------------------------------------------*/
3653 static void continueIfTrue (iCode *ic)
3656 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3660 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
3661 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
3666 /*-----------------------------------------------------------------*/
3668 /*-----------------------------------------------------------------*/
3669 static void jumpIfTrue (iCode *ic)
3672 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3676 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
3677 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
3682 /*-----------------------------------------------------------------*/
3683 /* jmpTrueOrFalse - */
3684 /*-----------------------------------------------------------------*/
3685 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
3688 // ugly but optimized by peephole
3689 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3691 symbol *nlbl = newiTempLabel(NULL);
3692 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);
3693 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
3694 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
3695 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
3698 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
3699 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
3704 /*-----------------------------------------------------------------*/
3705 /* genAnd - code for and */
3706 /*-----------------------------------------------------------------*/
3707 static void genAnd (iCode *ic, iCode *ifx)
3709 operand *left, *right, *result;
3711 unsigned long lit = 0L;
3716 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3717 aopOp((left = IC_LEFT(ic)),ic,FALSE);
3718 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
3719 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3721 resolveIfx(&rIfx,ifx);
3723 /* if left is a literal & right is not then exchange them */
3724 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3725 AOP_NEEDSACC(left)) {
3726 operand *tmp = right ;
3731 /* if result = right then exchange them */
3732 if(pic14_sameRegs(AOP(result),AOP(right))){
3733 operand *tmp = right ;
3738 /* if right is bit then exchange them */
3739 if (AOP_TYPE(right) == AOP_CRY &&
3740 AOP_TYPE(left) != AOP_CRY){
3741 operand *tmp = right ;
3745 if(AOP_TYPE(right) == AOP_LIT)
3746 lit = ulFromVal (AOP(right)->aopu.aop_lit);
3748 size = AOP_SIZE(result);
3750 DEBUGpic14_AopType(__LINE__,left,right,result);
3753 // result = bit & yy;
3754 if (AOP_TYPE(left) == AOP_CRY){
3755 // c = bit & literal;
3756 if(AOP_TYPE(right) == AOP_LIT){
3758 if(size && pic14_sameRegs(AOP(result),AOP(left)))
3761 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3764 if(size && (AOP_TYPE(result) == AOP_CRY)){
3765 pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
3768 if((AOP_TYPE(result) == AOP_CRY) && ifx){
3772 pic14_emitcode("clr","c");
3775 if (AOP_TYPE(right) == AOP_CRY){
3777 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3778 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3781 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
3783 pic14_emitcode("rrc","a");
3784 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3790 pic14_outBitC(result);
3792 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
3793 genIfxJump(ifx, "c");
3797 // if(val & 0xZZ) - size = 0, ifx != FALSE -
3798 // bit = val & 0xZZ - size = 1, ifx = FALSE -
3799 if((AOP_TYPE(right) == AOP_LIT) &&
3800 (AOP_TYPE(result) == AOP_CRY) &&
3801 (AOP_TYPE(left) != AOP_CRY)){
3802 int posbit = isLiteralBit(lit);
3806 //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
3809 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
3814 while (posbit > 7) {
3818 emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
3819 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
3820 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
3827 symbol *tlbl = newiTempLabel(NULL);
3828 int sizel = AOP_SIZE(left);
3830 pic14_emitcode("setb","c");
3832 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
3833 mov2w( AOP(left), offset);
3835 if((posbit = isLiteralBit(bytelit)) != 0) {
3836 emitpcode(rIfx.condition ? POC_BTFSC : POC_BTFSS, // XXX: or the other way round?
3837 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit - 1, 0));
3838 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
3841 emitpcode(POC_ANDLW, newpCodeOpLit(bytelit & 0x0ff));
3842 if (rIfx.condition) emitSKPZ;
3845 if(bytelit != 0x0FFL)
3847 pic14_emitcode("anl","a,%s",
3848 aopGet(AOP(right),offset,FALSE,TRUE));
3850 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
3853 emitpcode(POC_GOTO, popGetLabel(rIfx.lbl->key));
3859 // bit = left & literal
3861 pic14_emitcode("clr","c");
3862 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
3864 // if(left & literal)
3867 jmpTrueOrFalse(ifx, tlbl);
3871 pic14_outBitC(result);
3875 /* if left is same as result */
3876 if(pic14_sameRegs(AOP(result),AOP(left))){
3878 for(;size--; offset++,lit>>=8) {
3879 if(AOP_TYPE(right) == AOP_LIT){
3880 switch(lit & 0xff) {
3882 /* and'ing with 0 has clears the result */
3883 emitpcode(POC_CLRF,popGet(AOP(result),offset));
3886 /* and'ing with 0xff is a nop when the result and left are the same */
3891 int p = my_powof2( (~lit) & 0xff );
3893 /* only one bit is set in the literal, so use a bcf instruction */
3894 emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
3897 if(know_W != (int)(lit&0xff))
3898 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
3900 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
3905 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
3906 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
3911 // left & result in different registers
3912 if(AOP_TYPE(result) == AOP_CRY){
3914 // if(size), result in bit
3915 // if(!size && ifx), conditional oper: if(left & right)
3916 symbol *tlbl = newiTempLabel(NULL);
3917 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
3919 pic14_emitcode("setb","c");
3921 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3922 pic14_emitcode("anl","a,%s",
3923 aopGet(AOP(left),offset,FALSE,FALSE));
3924 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
3929 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
3930 pic14_outBitC(result);
3932 jmpTrueOrFalse(ifx, tlbl);
3934 for(;(size--);offset++) {
3936 // result = left & right
3937 if(AOP_TYPE(right) == AOP_LIT){
3938 int t = (lit >> (offset*8)) & 0x0FFL;
3941 emitpcode(POC_CLRF,popGet(AOP(result),offset));
3944 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
3945 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
3948 emitpcode(POC_MOVLW, popGetLit(t));
3949 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
3950 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
3955 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
3956 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
3957 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
3963 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3964 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3965 freeAsmop(result,NULL,ic,TRUE);
3968 /*-----------------------------------------------------------------*/
3969 /* genOr - code for or */
3970 /*-----------------------------------------------------------------*/
3971 static void genOr (iCode *ic, iCode *ifx)
3973 operand *left, *right, *result;
3975 unsigned long lit = 0L;
3978 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3980 aopOp((left = IC_LEFT(ic)),ic,FALSE);
3981 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
3982 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3984 DEBUGpic14_AopType(__LINE__,left,right,result);
3986 /* if left is a literal & right is not then exchange them */
3987 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3988 AOP_NEEDSACC(left)) {
3989 operand *tmp = right ;
3994 /* if result = right then exchange them */
3995 if(pic14_sameRegs(AOP(result),AOP(right))){
3996 operand *tmp = right ;
4001 /* if right is bit then exchange them */
4002 if (AOP_TYPE(right) == AOP_CRY &&
4003 AOP_TYPE(left) != AOP_CRY){
4004 operand *tmp = right ;
4009 DEBUGpic14_AopType(__LINE__,left,right,result);
4011 if(AOP_TYPE(right) == AOP_LIT)
4012 lit = ulFromVal (AOP(right)->aopu.aop_lit);
4014 size = AOP_SIZE(result);
4018 if (AOP_TYPE(left) == AOP_CRY){
4019 if(AOP_TYPE(right) == AOP_LIT){
4020 // c = bit & literal;
4022 // lit != 0 => result = 1
4023 if(AOP_TYPE(result) == AOP_CRY){
4025 emitpcode(POC_BSF, popGet(AOP(result),0));
4026 //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
4027 // AOP(result)->aopu.aop_dir,
4028 // AOP(result)->aopu.aop_dir);
4030 continueIfTrue(ifx);
4034 // lit == 0 => result = left
4035 if(size && pic14_sameRegs(AOP(result),AOP(left)))
4037 pic14_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
4040 if (AOP_TYPE(right) == AOP_CRY){
4041 if(pic14_sameRegs(AOP(result),AOP(left))){
4043 emitpcode(POC_BCF, popGet(AOP(result),0));
4044 emitpcode(POC_BTFSC, popGet(AOP(right),0));
4045 emitpcode(POC_BSF, popGet(AOP(result),0));
4047 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
4048 AOP(result)->aopu.aop_dir,
4049 AOP(result)->aopu.aop_dir);
4050 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
4051 AOP(right)->aopu.aop_dir,
4052 AOP(right)->aopu.aop_dir);
4053 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
4054 AOP(result)->aopu.aop_dir,
4055 AOP(result)->aopu.aop_dir);
4057 emitpcode(POC_BCF, popGet(AOP(result),0));
4058 emitpcode(POC_BTFSS, popGet(AOP(right),0));
4059 emitpcode(POC_BTFSC, popGet(AOP(left),0));
4060 emitpcode(POC_BSF, popGet(AOP(result),0));
4064 symbol *tlbl = newiTempLabel(NULL);
4065 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4068 emitpcode(POC_BCF, popGet(AOP(result),0));
4070 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4071 pic14_emitcode(";XXX setb","c");
4072 pic14_emitcode(";XXX jb","%s,%05d_DS_",
4073 AOP(left)->aopu.aop_dir,tlbl->key+100);
4074 pic14_toBoolean(right);
4075 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
4076 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4077 jmpTrueOrFalse(ifx, tlbl);
4081 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4088 pic14_outBitC(result);
4090 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4091 genIfxJump(ifx, "c");
4095 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4096 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4097 if((AOP_TYPE(right) == AOP_LIT) &&
4098 (AOP_TYPE(result) == AOP_CRY) &&
4099 (AOP_TYPE(left) != AOP_CRY)){
4101 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4104 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
4106 continueIfTrue(ifx);
4109 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4110 // lit = 0, result = boolean(left)
4112 pic14_emitcode(";XXX setb","c");
4113 pic14_toBoolean(right);
4115 symbol *tlbl = newiTempLabel(NULL);
4116 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
4118 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4120 genIfxJump (ifx,"a");
4124 pic14_outBitC(result);
4128 /* if left is same as result */
4129 if(pic14_sameRegs(AOP(result),AOP(left))){
4131 for(;size--; offset++,lit>>=8) {
4132 if(AOP_TYPE(right) == AOP_LIT){
4133 if((lit & 0xff) == 0)
4134 /* or'ing with 0 has no effect */
4137 int p = my_powof2(lit & 0xff);
4139 /* only one bit is set in the literal, so use a bsf instruction */
4141 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
4143 if(know_W != (int)(lit & 0xff))
4144 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
4145 know_W = lit & 0xff;
4146 emitpcode(POC_IORWF, popGet(AOP(left),offset));
4151 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
4152 emitpcode(POC_IORWF, popGet(AOP(left),offset));
4156 // left & result in different registers
4157 if(AOP_TYPE(result) == AOP_CRY){
4159 // if(size), result in bit
4160 // if(!size && ifx), conditional oper: if(left | right)
4161 symbol *tlbl = newiTempLabel(NULL);
4162 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4163 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4167 pic14_emitcode(";XXX setb","c");
4169 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4170 pic14_emitcode(";XXX orl","a,%s",
4171 aopGet(AOP(left),offset,FALSE,FALSE));
4172 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
4177 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4178 pic14_outBitC(result);
4180 jmpTrueOrFalse(ifx, tlbl);
4181 } else for(;(size--);offset++){
4183 // result = left | right
4184 if(AOP_TYPE(right) == AOP_LIT){
4185 int t = (lit >> (offset*8)) & 0x0FFL;
4188 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
4189 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
4193 emitpcode(POC_MOVLW, popGetLit(t));
4194 emitpcode(POC_IORFW, popGet(AOP(left),offset));
4195 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
4200 // faster than result <- left, anl result,right
4201 // and better if result is SFR
4202 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
4203 emitpcode(POC_IORFW,popGet(AOP(left),offset));
4204 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
4209 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4210 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4211 freeAsmop(result,NULL,ic,TRUE);
4214 /*-----------------------------------------------------------------*/
4215 /* genXor - code for xclusive or */
4216 /*-----------------------------------------------------------------*/
4217 static void genXor (iCode *ic, iCode *ifx)
4219 operand *left, *right, *result;
4221 unsigned long lit = 0L;
4224 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4226 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4227 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4228 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4230 /* if left is a literal & right is not ||
4231 if left needs acc & right does not */
4232 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4233 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4234 operand *tmp = right ;
4239 /* if result = right then exchange them */
4240 if(pic14_sameRegs(AOP(result),AOP(right))){
4241 operand *tmp = right ;
4246 /* if right is bit then exchange them */
4247 if (AOP_TYPE(right) == AOP_CRY &&
4248 AOP_TYPE(left) != AOP_CRY){
4249 operand *tmp = right ;
4253 if(AOP_TYPE(right) == AOP_LIT)
4254 lit = ulFromVal (AOP(right)->aopu.aop_lit);
4256 size = AOP_SIZE(result);
4260 if (AOP_TYPE(left) == AOP_CRY){
4261 if(AOP_TYPE(right) == AOP_LIT){
4262 // c = bit & literal;
4264 // lit>>1 != 0 => result = 1
4265 if(AOP_TYPE(result) == AOP_CRY){
4267 {emitpcode(POC_BSF, popGet(AOP(result),offset));
4268 pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
4270 continueIfTrue(ifx);
4273 pic14_emitcode("setb","c");
4277 // lit == 0, result = left
4278 if(size && pic14_sameRegs(AOP(result),AOP(left)))
4280 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4282 // lit == 1, result = not(left)
4283 if(size && pic14_sameRegs(AOP(result),AOP(left))){
4284 emitpcode(POC_MOVLW, popGet(AOP(result),offset));
4285 emitpcode(POC_XORWF, popGet(AOP(result),offset));
4286 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4289 assert ( !"incomplete genXor" );
4290 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4291 pic14_emitcode("cpl","c");
4298 symbol *tlbl = newiTempLabel(NULL);
4299 if (AOP_TYPE(right) == AOP_CRY){
4301 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4304 int sizer = AOP_SIZE(right);
4306 // if val>>1 != 0, result = 1
4307 pic14_emitcode("setb","c");
4309 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
4311 // test the msb of the lsb
4312 pic14_emitcode("anl","a,#0xfe");
4313 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
4317 pic14_emitcode("rrc","a");
4319 pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4320 pic14_emitcode("cpl","c");
4321 pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
4326 pic14_outBitC(result);
4328 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4329 genIfxJump(ifx, "c");
4333 if(pic14_sameRegs(AOP(result),AOP(left))){
4334 /* if left is same as result */
4335 for(;size--; offset++) {
4336 if(AOP_TYPE(right) == AOP_LIT){
4337 int t = (lit >> (offset*8)) & 0x0FFL;
4341 emitpcode(POC_MOVLW, popGetLit(t));
4342 emitpcode(POC_XORWF,popGet(AOP(left),offset));
4345 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
4346 emitpcode(POC_XORWF,popGet(AOP(left),offset));
4350 // left & result in different registers
4351 if(AOP_TYPE(result) == AOP_CRY){
4353 // if(size), result in bit
4354 // if(!size && ifx), conditional oper: if(left ^ right)
4355 symbol *tlbl = newiTempLabel(NULL);
4356 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4358 pic14_emitcode("setb","c");
4360 if((AOP_TYPE(right) == AOP_LIT) &&
4361 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4362 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4364 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4365 pic14_emitcode("xrl","a,%s",
4366 aopGet(AOP(left),offset,FALSE,FALSE));
4368 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
4373 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4374 pic14_outBitC(result);
4376 jmpTrueOrFalse(ifx, tlbl);
4377 } else for(;(size--);offset++){
4379 // result = left & right
4380 if(AOP_TYPE(right) == AOP_LIT){
4381 int t = (lit >> (offset*8)) & 0x0FFL;
4384 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4385 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
4388 emitpcode(POC_COMFW,popGet(AOP(left),offset));
4389 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
4392 emitpcode(POC_MOVLW, popGetLit(t));
4393 emitpcode(POC_XORFW,popGet(AOP(left),offset));
4394 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
4399 // faster than result <- left, anl result,right
4400 // and better if result is SFR
4401 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
4402 emitpcode(POC_XORFW,popGet(AOP(left),offset));
4403 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
4408 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4409 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4410 freeAsmop(result,NULL,ic,TRUE);
4413 /*-----------------------------------------------------------------*/
4414 /* genInline - write the inline code out */
4415 /*-----------------------------------------------------------------*/
4416 static void genInline (iCode *ic)
4418 char *buffer, *bp, *bp1;
4419 bool inComment = FALSE;
4422 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4424 _G.inLine += (!options.asmpeep);
4426 buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
4441 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
4446 /* Add \n for labels, not dirs such as c:\mydir */
4447 if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
4452 /* print label, use this special format with NULL directive
4453 * to denote that the argument should not be indented with tab */
4454 addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
4462 if ((bp1 != bp) && *bp1)
4463 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
4467 _G.inLine -= (!options.asmpeep);
4470 /*-----------------------------------------------------------------*/
4471 /* genRRC - rotate right with carry */
4472 /*-----------------------------------------------------------------*/
4473 static void genRRC (iCode *ic)
4475 operand *left , *result ;
4476 int size, offset = 0, same;
4479 /* rotate right with carry */
4481 result=IC_RESULT(ic);
4482 aopOp (left,ic,FALSE);
4483 aopOp (result,ic,FALSE);
4485 DEBUGpic14_AopType(__LINE__,left,NULL,result);
4487 same = pic14_sameRegs(AOP(result),AOP(left));
4489 size = AOP_SIZE(result);
4491 /* get the lsb and put it into the carry */
4492 emitpcode(POC_RRFW, popGet(AOP(left),size-1));
4499 emitpcode(POC_RRF, popGet(AOP(left),offset));
4501 emitpcode(POC_RRFW, popGet(AOP(left),offset));
4502 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
4508 freeAsmop(left,NULL,ic,TRUE);
4509 freeAsmop(result,NULL,ic,TRUE);
4512 /*-----------------------------------------------------------------*/
4513 /* genRLC - generate code for rotate left with carry */
4514 /*-----------------------------------------------------------------*/
4515 static void genRLC (iCode *ic)
4517 operand *left , *result ;
4518 int size, offset = 0;
4522 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4523 /* rotate right with carry */
4525 result=IC_RESULT(ic);
4526 aopOp (left,ic,FALSE);
4527 aopOp (result,ic,FALSE);
4529 DEBUGpic14_AopType(__LINE__,left,NULL,result);
4531 same = pic14_sameRegs(AOP(result),AOP(left));
4533 /* move it to the result */
4534 size = AOP_SIZE(result);
4536 /* get the msb and put it into the carry */
4537 emitpcode(POC_RLFW, popGet(AOP(left),size-1));
4544 emitpcode(POC_RLF, popGet(AOP(left),offset));
4546 emitpcode(POC_RLFW, popGet(AOP(left),offset));
4547 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
4554 freeAsmop(left,NULL,ic,TRUE);
4555 freeAsmop(result,NULL,ic,TRUE);
4558 /*-----------------------------------------------------------------*/
4559 /* genGetHbit - generates code get highest order bit */
4560 /*-----------------------------------------------------------------*/
4561 static void genGetHbit (iCode *ic)
4563 operand *left, *result;
4565 result=IC_RESULT(ic);
4566 aopOp (left,ic,FALSE);
4567 aopOp (result,ic,FALSE);
4570 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4571 /* get the highest order byte into a */
4572 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
4573 if(AOP_TYPE(result) == AOP_CRY){
4574 pic14_emitcode("rlc","a");
4575 pic14_outBitC(result);
4578 pic14_emitcode("rl","a");
4579 pic14_emitcode("anl","a,#0x01");
4580 pic14_outAcc(result);
4584 freeAsmop(left,NULL,ic,TRUE);
4585 freeAsmop(result,NULL,ic,TRUE);
4588 /*-----------------------------------------------------------------*/
4589 /* AccLsh - shift left accumulator by known count */
4590 /* MARK: pic14 always rotates through CARRY! */
4591 /*-----------------------------------------------------------------*/
4592 static void AccLsh (pCodeOp *pcop,int shCount)
4595 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4596 shCount &= 0x0007; // shCount : 0..7
4603 emitpcode(POC_RLF,pcop);
4607 emitpcode(POC_RLF,pcop);
4608 emitpcode(POC_RLF,pcop);
4611 emitpcode(POC_RLF,pcop);
4612 emitpcode(POC_RLF,pcop);
4613 emitpcode(POC_RLF,pcop);
4616 emitpcode(POC_SWAPF,pcop);
4619 emitpcode(POC_SWAPF,pcop);
4620 emitpcode(POC_RLF,pcop);
4623 emitpcode(POC_SWAPF,pcop);
4624 emitpcode(POC_RLF,pcop);
4625 emitpcode(POC_RLF,pcop);
4628 emitpcode(POC_RRFW,pcop);
4629 emitpcode(POC_RRF,pcop);
4632 /* clear invalid bits */
4633 emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
4634 emitpcode(POC_ANDWF, pcop);
4637 /*-----------------------------------------------------------------*/
4638 /* AccRsh - shift right accumulator by known count */
4639 /* MARK: pic14 always rotates through CARRY! */
4640 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
4641 /* 1: mask out invalid bits (zero-extend) */
4642 /* 2: sign-extend result (pretty slow) */
4643 /*-----------------------------------------------------------------*/
4644 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
4647 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4648 shCount &= 0x0007; // shCount : 0..7
4654 /* load sign if needed */
4655 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
4656 else if (mask_mode == 1) emitCLRC;
4657 emitpcode(POC_RRF,pcop);
4661 /* load sign if needed */
4662 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
4663 emitpcode(POC_RRF,pcop);
4664 /* load sign if needed */
4665 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
4666 emitpcode(POC_RRF,pcop);
4667 if (mask_mode == 2) return;
4670 /* load sign if needed */
4671 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
4672 emitpcode(POC_RRF,pcop);
4673 /* load sign if needed */
4674 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
4675 emitpcode(POC_RRF,pcop);
4676 /* load sign if needed */
4677 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
4678 emitpcode(POC_RRF,pcop);
4679 if (mask_mode == 2) return;
4682 emitpcode(POC_SWAPF,pcop);
4685 emitpcode(POC_SWAPF,pcop);
4686 emitpcode(POC_RRF,pcop);
4689 emitpcode(POC_SWAPF,pcop);
4690 emitpcode(POC_RRF,pcop);
4691 emitpcode(POC_RRF,pcop);
4697 emitpcode(POC_RLFW,pcop);
4698 emitpcode(POC_CLRF,pcop);
4700 emitpcode(POC_COMF,pcop);
4703 emitpcode(POC_RLFW,pcop);
4704 emitpcode(POC_RLF,pcop);
4711 /* leave invalid bits undefined */
4715 /* clear invalid bits -- zero-extend */
4716 emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
4717 emitpcode(POC_ANDWF, pcop);
4719 if (mask_mode == 2) {
4721 emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
4722 emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
4723 emitpcode(POC_IORWF, pcop);
4727 /*-----------------------------------------------------------------*/
4728 /* movLeft2Result - move byte from left to result */
4729 /*-----------------------------------------------------------------*/
4730 static void movLeft2Result (operand *left, int offl,
4731 operand *result, int offr)
4734 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4735 if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
4736 aopGet(AOP(left),offl,FALSE,FALSE);
4738 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
4739 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
4743 /*-----------------------------------------------------------------*/
4744 /* shiftLeft_Left2ResultLit - shift left by known count */
4745 /*-----------------------------------------------------------------*/
4747 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
4749 int size, same, offr, i;
4751 size = AOP_SIZE(left);
4752 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
4754 same = pic14_sameRegs (AOP(left), AOP(result));
4757 shCount = shCount & 0x07;
4763 case 0: /* takes 0 or 2N cycles (for offr==0) */
4764 if (!same || offr) {
4765 for (i=size-1; i >= 0; i--)
4766 movLeft2Result (left, i, result, offr + i);
4770 case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
4772 shiftLeft_Left2ResultLit (left, result, 8 * offr);
4773 shiftLeft_Left2ResultLit (result, result, shCount);
4774 return; /* prevent clearing result again */
4777 for (i=0; i < size; i++) {
4778 if (same && !offr) {
4779 emitpcode (POC_RLF, popGet (AOP(left), i));
4781 emitpcode (POC_RLFW, popGet (AOP(left), i));
4782 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
4788 case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
4789 /* works in-place/with offr as well */
4790 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
4791 emitpcode (POC_ANDLW, popGetLit (0xF0));
4792 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
4794 for (i = size - 2; i >= 0; i--)
4796 emitpcode (POC_SWAPFW, popGet (AOP(left), i));
4797 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
4798 emitpcode (POC_ANDLW, popGetLit (0x0F));
4799 emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
4800 emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
4804 case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
4805 /* works in-place/with offr as well */
4806 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
4807 for (i = size-2; i >= 0; i--) {
4808 emitpcode (POC_RRFW, popGet (AOP(left), i));
4809 emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
4811 emitpcode (POC_CLRF, popGet (AOP(result), offr));
4812 emitpcode (POC_RRF, popGet (AOP(result), offr));
4816 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
4817 shiftLeft_Left2ResultLit (result, result, 1);
4818 return; /* prevent clearing result again */
4824 emitpcode (POC_CLRF, popGet (AOP(result), offr));
4828 /*-----------------------------------------------------------------*/
4829 /* shiftRight_Left2ResultLit - shift right by known count */
4830 /*-----------------------------------------------------------------*/
4832 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
4834 int size, same, offr, i;
4836 size = AOP_SIZE(left);
4837 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
4839 same = pic14_sameRegs (AOP(left), AOP(result));
4842 shCount = shCount & 0x07;
4850 case 0: /* takes 0 or 2N cycles (for offr==0) */
4851 if (!same || offr) {
4852 for (i=0; i < size; i++)
4853 movLeft2Result (left, i + offr, result, i);
4857 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
4858 emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
4860 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
4861 shiftRight_Left2ResultLit (result, result, shCount, sign);
4862 return; /* prevent sign-extending result again */
4866 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
4869 for (i = size-1; i >= 0; i--) {
4870 if (same && !offr) {
4871 emitpcode (POC_RRF, popGet (AOP(left), i));
4873 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
4874 emitpcode (POC_MOVWF, popGet (AOP(result), i));
4880 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
4881 /* works in-place/with offr as well */
4882 emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
4883 emitpcode (POC_ANDLW, popGetLit (0x0F));
4884 emitpcode (POC_MOVWF, popGet(AOP(result), 0));
4886 for (i = 1; i < size; i++)
4888 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
4889 emitpcode (POC_MOVWF, popGet (AOP(result), i));
4890 emitpcode (POC_ANDLW, popGetLit (0xF0));
4891 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
4892 emitpcode (POC_XORWF, popGet (AOP(result), i));
4897 emitpcode (POC_MOVLW, popGetLit (0xF0));
4898 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
4899 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
4903 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
4904 /* works in-place/with offr as well */
4905 emitpcode (POC_RLFW, popGet (AOP(left), offr));
4906 for (i = 0; i < size-1; i++) {
4907 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
4908 emitpcode (POC_MOVWF, popGet (AOP(result), i));
4910 emitpcode (POC_CLRF, popGet (AOP(result), size-1));
4912 emitpcode (POC_RLF, popGet (AOP(result), size-1));
4915 emitpcode (POC_DECF, popGet (AOP(result), size-1));
4920 shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
4921 shiftRight_Left2ResultLit (result, result, 1, sign);
4922 return; /* prevent sign extending result again */
4927 addSign (result, size, sign);
4930 /*-----------------------------------------------------------------*
4931 * genMultiAsm - repeat assembly instruction for size of register.
4932 * if endian == 1, then the high byte (i.e base address + size of
4933 * register) is used first else the low byte is used first;
4934 *-----------------------------------------------------------------*/
4935 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
4941 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4954 emitpcode(poc, popGet(AOP(reg),offset));
4960 /*-----------------------------------------------------------------*/
4961 /* loadSignToC - load the operand's sign bit into CARRY */
4962 /*-----------------------------------------------------------------*/
4964 static void loadSignToC (operand *op)
4967 assert (op && AOP(op) && AOP_SIZE(op));
4970 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
4974 /*-----------------------------------------------------------------*/
4975 /* genRightShift - generate code for right shifting */
4976 /*-----------------------------------------------------------------*/
4977 static void genGenericShift (iCode *ic, int shiftRight)
4979 operand *right, *left, *result;
4982 symbol *tlbl, *tlbl1, *inverselbl;
4985 /* if signed then we do it the hard way preserve the
4986 sign bit moving it inwards */
4987 retype = getSpec(operandType(IC_RESULT(ic)));
4988 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4990 /* signed & unsigned types are treated the same : i.e. the
4991 signed is NOT propagated inwards : quoting from the
4992 ANSI - standard : "for E1 >> E2, is equivalent to division
4993 by 2**E2 if unsigned or if it has a non-negative value,
4994 otherwise the result is implementation defined ", MY definition
4995 is that the sign does not get propagated */
4997 right = IC_RIGHT(ic);
4999 result = IC_RESULT(ic);
5001 aopOp(right,ic,FALSE);
5002 aopOp(left,ic,FALSE);
5003 aopOp(result,ic,FALSE);
5005 /* if the shift count is known then do it
5006 as efficiently as possible */
5007 if (AOP_TYPE(right) == AOP_LIT) {
5008 int lit = (int) ulFromVal (AOP(right)->aopu.aop_lit);
5012 shiftRight = !shiftRight;
5016 shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
5018 shiftLeft_Left2ResultLit (left, result, lit);
5019 //genRightShiftLiteral (left,right,result,ic, 0);
5023 /* shift count is unknown then we have to form
5024 a loop get the loop count in B : Note: we take
5025 only the lower order byte since shifting
5026 more that 32 bits make no sense anyway, ( the
5027 largest size of an object can be only 32 bits ) */
5029 /* we must not overwrite the shift counter */
5030 assert (!pic14_sameRegs(AOP(right),AOP(result)));
5032 /* now move the left to the result if they are not the
5034 if (!pic14_sameRegs(AOP(left),AOP(result)))
5036 size = min(AOP_SIZE(result), AOP_SIZE(left));
5038 mov2w(AOP(left), size);
5039 movwf(AOP(result), size);
5041 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
5044 tlbl = newiTempLabel(NULL);
5045 tlbl1= newiTempLabel(NULL);
5047 size = AOP_SIZE(result);
5049 mov2w(AOP(right),0);
5050 if (!SPEC_USIGN(operandType(right)))
5052 inverselbl = newiTempLabel(NULL);
5053 /* signed shift count -- invert shift direction for c<0 */
5054 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
5055 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
5057 emitpcode(POC_SUBLW, popGetLit(0)); /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
5058 /* check for `a = b >> c' with `-c == 0' */
5060 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
5061 emitpLabel(tlbl->key);
5062 /* propagate the sign bit inwards for SIGNED result */
5063 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
5064 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
5065 emitpcode(POC_ADDLW, popGetLit(1)); /* clears CARRY (unless W==0 afterwards) */
5067 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
5069 if (!SPEC_USIGN(operandType(right)))
5071 symbol *inv_loop = newiTempLabel(NULL);
5073 shiftRight = !shiftRight; /* invert shift direction */
5075 /* we came here from the code above -- we are done */
5076 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
5078 /* emit code for shifting N<0 steps, count is already in W */
5079 emitpLabel(inverselbl->key);
5080 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
5081 emitpLabel(inv_loop->key);
5082 /* propagate the sign bit inwards for SIGNED result */
5083 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
5084 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
5085 emitpcode(POC_ADDLW, popGetLit(1));
5087 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
5090 emitpLabel(tlbl1->key);
5092 freeAsmop(left,NULL,ic,TRUE);
5093 freeAsmop (right,NULL,ic,TRUE);
5094 freeAsmop(result,NULL,ic,TRUE);
5097 static void genRightShift (iCode *ic)
5099 genGenericShift(ic, 1);
5102 static void genLeftShift (iCode *ic)
5104 genGenericShift(ic, 0);
5107 /*-----------------------------------------------------------------*/
5108 /* SetIrp - Set IRP bit */
5109 /*-----------------------------------------------------------------*/
5110 static void SetIrp(operand *result)
5113 if (AOP_TYPE(result) == AOP_LIT) {
5114 unsigned lit = (unsigned) double2ul (operandLitValue(result));
5120 if ((AOP_TYPE(result) == AOP_PCODE)
5121 && (AOP(result)->aopu.pcop->type == PO_LITERAL))
5123 int addrs = PCOL(AOP(result)->aopu.pcop)->lit;
5129 emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
5130 if(AOP_SIZE(result) > 1) {
5131 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
5139 setup_fsr (operand *ptr)
5142 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
5144 /* also setup-up IRP */
5148 /*-----------------------------------------------------------------*/
5149 /* emitPtrByteGet - emits code to get a byte into WREG from an */
5150 /* arbitrary pointer (__code, __data, generic) */
5151 /*-----------------------------------------------------------------*/
5153 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
5160 if (!alreadyAddressed) setup_fsr (src);
5161 emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
5165 assert( AOP_SIZE(src) == 2 );
5167 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
5169 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
5170 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
5171 call_libraryfunc ("__gptrget1");
5175 assert( AOP_SIZE(src) == 3 );
5177 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
5179 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
5181 call_libraryfunc ("__gptrget1");
5185 assert( !"unhandled pointer type" );
5190 /*-----------------------------------------------------------------*/
5191 /* emitPtrByteSet - emits code to set a byte from src through a */
5192 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR). */
5193 /*-----------------------------------------------------------------*/
5195 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
5202 if (!alreadyAddressed) setup_fsr (dst);
5203 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
5207 assert( !"trying to assign to __code pointer" );
5211 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
5213 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
5215 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
5217 call_libraryfunc ("__gptrput1");
5221 assert( !"unhandled pointer type" );
5226 /*-----------------------------------------------------------------*/
5227 /* genUnpackBits - generates code for unpacking bits */
5228 /*-----------------------------------------------------------------*/
5229 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
5231 int rsize; /* result size */
5232 sym_link *etype; /* bitfield type information */
5233 int blen; /* bitfield length */
5234 int bstr; /* bitfield starting bit within byte */
5237 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5238 etype = getSpec(operandType(result));
5239 rsize = getSize (operandType (result));
5240 blen = SPEC_BLEN (etype);
5241 bstr = SPEC_BSTR (etype);
5243 /* single bit field case */
5245 if (ifx) { /* that is for an if statement */
5248 resolveIfx(&rIfx,ifx);
5249 if (ptype == -1) /* direct */
5250 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
5252 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
5253 emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
5254 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5258 assert (!pic14_sameRegs (AOP(result), AOP(left)));
5259 for (i=0; i < AOP_SIZE(result); i++)
5260 emitpcode (POC_CLRF, popGet (AOP(result), i));
5265 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
5266 /* adjust result below */
5273 emitPtrByteGet (left, ptype, FALSE);
5274 emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
5276 /* adjust result below */
5280 assert( !"unhandled pointer type" );
5283 /* move sign-/zero extended bit to result */
5284 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
5285 emitpcode (POC_INCF, popGet (AOP(result), 0));
5287 emitpcode (POC_DECF, popGet (AOP(result), 0));
5289 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
5293 else if (blen <= 8 && ((blen + bstr) <= 8))
5298 for (i=0; i < AOP_SIZE(result); i++)
5299 emitpcode (POC_CLRF, popGet (AOP(result), i));
5304 mov2w(AOP(left), 0);
5311 emitPtrByteGet (left, ptype, FALSE);
5315 assert( !"unhandled pointer type" );
5319 emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
5320 movwf(AOP(result), 0);
5321 AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
5323 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
5325 /* signed bitfield */
5326 assert (bstr + blen > 0);
5327 emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
5328 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
5329 emitpcode(POC_IORWF, popGet(AOP(result),0));
5331 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
5335 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
5339 /*-----------------------------------------------------------------*/
5340 /* genDataPointerGet - generates code when ptr offset is known */
5341 /*-----------------------------------------------------------------*/
5342 static void genDataPointerGet (operand *left,
5346 int size , offset = 0;
5349 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5352 /* optimization - most of the time, left and result are the same
5353 * address, but different types. for the pic code, we could omit
5356 aopOp(result,ic,TRUE);
5358 if (pic14_sameRegs (AOP(left), AOP(result)))
5361 DEBUGpic14_AopType(__LINE__,left,NULL,result);
5363 //emitpcode(POC_MOVFW, popGet(AOP(left),0));
5365 size = AOP_SIZE(result);
5366 if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
5370 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
5371 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5375 freeAsmop(left,NULL,ic,TRUE);
5376 freeAsmop(result,NULL,ic,TRUE);
5380 /*-----------------------------------------------------------------*/
5381 /* genNearPointerGet - pic14_emitcode for near pointer fetch */
5382 /*-----------------------------------------------------------------*/
5383 static void genNearPointerGet (operand *left,
5388 sym_link *ltype = operandType(left);
5389 sym_link *rtype = operandType(result);
5390 sym_link *retype= getSpec(rtype); /* bitfield type information */
5394 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5397 aopOp(left,ic,FALSE);
5399 /* if left is rematerialisable and
5400 result is not bit variable type and
5401 the left is pointer to data space i.e
5402 lower 128 bytes of space */
5403 if (AOP_TYPE(left) == AOP_PCODE && //AOP_TYPE(left) == AOP_IMMD &&
5404 !IS_BITVAR(retype) &&
5405 PIC_IS_DATA_PTR(ltype)) {
5406 genDataPointerGet (left,result,ic);
5410 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5411 aopOp (result,ic,FALSE);
5413 /* Check if can access directly instead of via a pointer */
5414 if ((AOP_TYPE(left) == AOP_PCODE)
5415 && (AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
5416 && (AOP_SIZE(result) == 1))
5421 if (IS_BITFIELD(getSpec(operandType(result))))
5423 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
5427 /* If the pointer value is not in a the FSR then need to put it in */
5428 /* Must set/reset IRP bit for use with FSR. */
5433 /* if bitfield then unpack the bits */
5435 /* we have can just get the values */
5436 int size = AOP_SIZE(result);
5439 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5443 emitpcode(POC_MOVWF,popGet(AOP(left),0));
5445 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
5446 if (AOP_TYPE(result) == AOP_LIT) {
5447 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
5449 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5451 if (size && !direct)
5452 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
5457 /* now some housekeeping stuff */
5459 /* we had to allocate for this iCode */
5460 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5461 freeAsmop(NULL,aop,ic,TRUE);
5463 /* we did not allocate which means left
5464 already in a pointer register, then
5465 if size > 0 && this could be used again
5466 we have to point it back to where it
5468 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5469 if (AOP_SIZE(result) > 1 &&
5470 !OP_SYMBOL(left)->remat &&
5471 ( OP_SYMBOL(left)->liveTo > ic->seq ||
5473 int size = AOP_SIZE(result) - 1;
5475 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
5481 freeAsmop(left,NULL,ic,TRUE);
5482 freeAsmop(result,NULL,ic,TRUE);
5486 /*-----------------------------------------------------------------*/
5487 /* genGenPointerGet - gget value from generic pointer space */
5488 /*-----------------------------------------------------------------*/
5489 static void genGenPointerGet (operand *left,
5490 operand *result, iCode *ic)
5493 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5494 aopOp(left,ic,FALSE);
5495 aopOp(result,ic,FALSE);
5498 DEBUGpic14_AopType(__LINE__,left,NULL,result);
5500 if (IS_BITFIELD(getSpec(operandType(result))))
5502 genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
5507 /* emit call to __gptrget */
5508 char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
5509 int size = AOP_SIZE(result);
5512 assert (size > 0 && size <= 4);
5514 /* pass arguments */
5515 assert (AOP_SIZE(left) == 3);
5516 mov2w(AOP(left), 0);
5517 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
5518 mov2w(AOP(left), 1);
5519 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
5520 mov2w(AOP(left), 2);
5521 call_libraryfunc (func[size]);
5524 movwf (AOP(result), --size);
5526 emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
5527 movwf (AOP(result), size);
5531 freeAsmop(left,NULL,ic,TRUE);
5532 freeAsmop(result,NULL,ic,TRUE);
5536 /*-----------------------------------------------------------------*/
5537 /* genConstPointerGet - get value from const generic pointer space */
5538 /*-----------------------------------------------------------------*/
5539 static void genConstPointerGet (operand *left,
5540 operand *result, iCode *ic)
5542 //sym_link *retype = getSpec(operandType(result));
5544 symbol *albl, *blbl;//, *clbl;
5551 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5552 aopOp(left,ic,FALSE);
5553 aopOp(result,ic,FALSE);
5555 size = AOP_SIZE(result);
5557 DEBUGpic14_AopType(__LINE__,left,NULL,result);
5559 DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
5561 lit = op_isLitLike (left);
5562 poc = lit ? POC_MOVLW : POC_MOVFW;
5564 if (IS_BITFIELD(getSpec(operandType(result))))
5566 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
5571 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
5572 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
5573 assert (size > 0 && size <= 4);
5576 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
5578 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
5579 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
5580 call_libraryfunc (func[size]);
5582 movwf(AOP(result),size-1);
5583 for (i = 1; i < size; i++)
5585 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
5586 movwf(AOP(result),size - 1 - i);
5591 freeAsmop(left,NULL,ic,TRUE);
5592 freeAsmop(result,NULL,ic,TRUE);
5595 /*-----------------------------------------------------------------*/
5596 /* genPointerGet - generate code for pointer get */
5597 /*-----------------------------------------------------------------*/
5598 static void genPointerGet (iCode *ic)
5600 operand *left, *result ;
5601 sym_link *type, *etype;
5605 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5608 result = IC_RESULT(ic) ;
5610 /* depending on the type of pointer we need to
5611 move it to the correct pointer register */
5612 type = operandType(left);
5613 etype = getSpec(type);
5615 if (IS_PTR_CONST(type))
5616 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
5618 /* if left is of type of pointer then it is simple */
5619 if (IS_PTR(type) && !IS_FUNC(type->next))
5620 p_type = DCL_TYPE(type);
5622 /* we have to go by the storage class */
5623 p_type = PTR_TYPE(SPEC_OCLS(etype));
5625 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
5627 if (SPEC_OCLS(etype)->codesp ) {
5628 DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
5629 //p_type = CPOINTER ;
5632 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
5633 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
5634 /*p_type = FPOINTER ;*/
5636 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
5637 DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
5638 /* p_type = PPOINTER; */
5640 if (SPEC_OCLS(etype) == idata )
5641 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
5642 /* p_type = IPOINTER; */
5644 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
5645 /* p_type = POINTER ; */
5648 /* now that we have the pointer type we assign
5649 the pointer values */
5655 genNearPointerGet (left,result,ic);
5659 genPagedPointerGet(left,result,ic);
5663 genFarPointerGet (left,result,ic);
5667 genConstPointerGet (left,result,ic);
5671 genGenPointerGet (left,result,ic);
5674 assert ( !"unhandled pointer type" );
5680 /*-----------------------------------------------------------------*/
5681 /* genPackBits - generates code for packed bit storage */
5682 /*-----------------------------------------------------------------*/
5683 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
5685 int blen; /* bitfield length */
5686 int bstr; /* bitfield starting bit within byte */
5687 int litval; /* source literal value (if AOP_LIT) */
5688 unsigned char mask; /* bitmask within current byte */
5691 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5693 blen = SPEC_BLEN (etype);
5694 bstr = SPEC_BSTR (etype);
5696 /* If the bitfield length is less than a byte and does not cross byte boundaries */
5697 if ((blen <= 8) && ((bstr + blen) <= 8))
5699 mask = ((unsigned char) (0xFF << (blen + bstr)) |
5700 (unsigned char) (0xFF >> (8 - bstr)));
5702 if (AOP_TYPE (right) == AOP_LIT)
5704 /* Case with a bitfield length <8 and literal source */
5705 int lit = (int) ulFromVal (AOP (right)->aopu.aop_lit);
5712 if (AOP(result)->type == AOP_PCODE)
5713 pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
5715 pcop = popGet(AOP(result),0);
5716 emitpcode(lit?POC_BSF:POC_BCF,pcop);
5722 emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
5726 assert( !"trying to assign to bitfield via pointer to __code space" );
5730 emitPtrByteGet(result, p_type, FALSE);
5732 emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
5734 emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
5736 emitPtrByteSet(result, p_type, TRUE);
5740 assert( !"unhandled pointer type" );
5742 } // switch (p_type)
5745 litval = lit << bstr;
5746 litval &= (~mask) & 0x00ff;
5751 mov2w (AOP(result), 0);
5752 if ((litval|mask) != 0x00ff)
5753 emitpcode(POC_ANDLW, popGetLit (mask));
5755 emitpcode(POC_IORLW, popGetLit (litval));
5756 movwf (AOP(result), 0);
5762 emitPtrByteGet(result, p_type, FALSE);
5763 if ((litval|mask) != 0x00ff)
5764 emitpcode(POC_ANDLW, popGetLit (mask));
5766 emitpcode(POC_IORLW, popGetLit (litval));
5767 emitPtrByteSet(result, p_type, TRUE);
5771 assert( !"trying to assign to bitfield via pointer to __code space" );
5775 assert( !"unhandled pointer type" );
5782 /* right is no literal */
5787 /* Note more efficient code, of pre clearing bit then only setting it if required,
5788 * can only be done if it is known that the result is not a SFR */
5789 emitpcode(POC_RRFW,popGet(AOP(right),0));
5791 emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
5793 emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
5799 emitPtrByteGet (result, p_type, FALSE);
5800 emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
5801 emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
5802 emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
5803 emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
5804 emitPtrByteSet (result, p_type, TRUE);
5808 assert( !"trying to assign to bitfield via pointer to __code space" );
5812 assert( !"unhandled pointer type" );
5817 /* Case with a bitfield 1 < length <= 8 and arbitrary source */
5818 pCodeOp *temp = popGetTempReg ();
5820 mov2w (AOP(right), 0);
5822 emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
5824 emitpcode(POC_MOVWF, temp);
5826 AccLsh (temp, bstr);
5832 mov2w (AOP(result), 0);
5833 emitpcode(POC_ANDLW, popGetLit (mask));
5834 emitpcode(POC_IORFW, temp);
5835 movwf (AOP(result), 0);
5841 emitPtrByteGet (result, p_type, FALSE);
5842 emitpcode(POC_ANDLW, popGetLit (mask));
5843 emitpcode(POC_IORFW, temp);
5844 emitPtrByteSet (result, p_type, TRUE);
5848 assert( !"trying to assign to bitfield via pointer to __code space" );
5852 assert( !"unhandled pointer type" );
5856 popReleaseTempReg (temp);
5858 } // if (AOP(right)->type != AOP_LIT)
5860 } // if (blen <= 8 && ((blen + bstr) <= 8))
5862 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
5865 /*-----------------------------------------------------------------*/
5866 /* genDataPointerSet - remat pointer to data space */
5867 /*-----------------------------------------------------------------*/
5868 static void genDataPointerSet(operand *right,
5872 int size, offset = 0 ;
5876 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5877 aopOp(right,ic,FALSE);
5878 aopOp(result,ic,FALSE);
5880 assert (IS_SYMOP(result));
5881 assert (IS_PTR(OP_SYM_TYPE(result)));
5883 if (AOP_TYPE(right) == AOP_LIT)
5886 size = AOP_SIZE(right);
5887 ressize = getSize(OP_SYM_ETYPE(result));
5888 if (size > ressize) size = ressize;
5889 //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
5891 //assert( !"what's going on here?" );
5894 if ( AOP_TYPE(result) == AOP_PCODE) {
5895 fprintf(stderr,"genDataPointerSet %s, %d\n",
5896 AOP(result)->aopu.pcop->name,
5897 PCOI(AOP(result)->aopu.pcop)->offset);
5901 // tsd, was l+1 - the underline `_' prefix was being stripped
5903 emitpComment ("%s:%u: size=%d/%d, offset=%d, AOP_TYPE(res)=%d", __FILE__,__LINE__, size, ressize, offset, AOP_TYPE(result));
5905 if (AOP_TYPE(right) == AOP_LIT) {
5906 unsigned int lit = pic14aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
5907 //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
5909 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
5910 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
5912 emitpcode(POC_CLRF, popGet(AOP(result), offset));
5915 //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
5916 emitpcode(POC_MOVFW, popGet(AOP(right), offset));
5917 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
5923 freeAsmop(right,NULL,ic,TRUE);
5924 freeAsmop(result,NULL,ic,TRUE);
5927 /*-----------------------------------------------------------------*/
5928 /* genNearPointerSet - pic14_emitcode for near pointer put */
5929 /*-----------------------------------------------------------------*/
5930 static void genNearPointerSet (operand *right,
5935 sym_link *ptype = operandType(result);
5936 sym_link *retype = getSpec(operandType(right));
5937 sym_link *letype = getSpec(ptype);
5942 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5943 aopOp(result,ic,FALSE);
5946 /* if the result is rematerializable &
5947 in data space & not a bit variable */
5948 //if (AOP_TYPE(result) == AOP_IMMD &&
5949 if (AOP_TYPE(result) == AOP_PCODE &&
5950 PIC_IS_DATA_PTR(ptype) &&
5951 !IS_BITVAR (retype) &&
5952 !IS_BITVAR (letype)) {
5953 genDataPointerSet (right,result,ic);
5954 freeAsmop(result,NULL,ic,TRUE);
5959 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5960 aopOp(right,ic,FALSE);
5961 DEBUGpic14_AopType(__LINE__,NULL,right,result);
5963 /* Check if can access directly instead of via a pointer */
5964 if ((AOP_TYPE(result) == AOP_PCODE)
5965 && (AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
5966 && (AOP_SIZE(right) == 1))
5971 if (IS_BITFIELD (letype))
5973 genPackBits (letype, result, right, direct?-1:POINTER);
5977 /* If the pointer value is not in a the FSR then need to put it in */
5978 /* Must set/reset IRP bit for use with FSR. */
5979 /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
5984 /* we have can just get the values */
5985 int size = AOP_SIZE(right);
5988 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5990 char *l = aopGet(AOP(right),offset,FALSE,TRUE);
5992 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
5994 if (AOP_TYPE(right) == AOP_LIT) {
5995 emitpcode(POC_MOVLW,popGet(AOP(right),offset));
5997 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6000 emitpcode(POC_MOVWF,popGet(AOP(result),0));
6002 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
6004 if (size && !direct)
6005 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
6010 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6011 /* now some housekeeping stuff */
6013 /* we had to allocate for this iCode */
6014 freeAsmop(NULL,aop,ic,TRUE);
6016 /* we did not allocate which means left
6017 already in a pointer register, then
6018 if size > 0 && this could be used again
6019 we have to point it back to where it
6021 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6022 if (AOP_SIZE(right) > 1 &&
6023 !OP_SYMBOL(result)->remat &&
6024 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6026 int size = AOP_SIZE(right) - 1;
6028 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
6032 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6035 freeAsmop(right,NULL,ic,TRUE);
6036 freeAsmop(result,NULL,ic,TRUE);
6039 /*-----------------------------------------------------------------*/
6040 /* genGenPointerSet - set value from generic pointer space */
6041 /*-----------------------------------------------------------------*/
6042 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
6044 sym_link *retype = getSpec(operandType(result));
6047 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6048 aopOp(right,ic,FALSE);
6049 aopOp(result,ic,FALSE);
6052 DEBUGpic14_AopType(__LINE__,right,NULL,result);
6054 if (IS_BITFIELD(retype))
6056 genPackBits (retype, result, right, GPOINTER);
6061 /* emit call to __gptrput */
6062 char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
6063 int size = AOP_SIZE(right);
6066 /* The following assertion fails for
6067 * struct foo { char a; char b; } bar;
6068 * void demo(struct foo *dst, char c) { dst->b = c; }
6069 * as size will be 1 (sizeof(c)), whereas dst->b will be accessed
6070 * using (((char *)dst)+1), whose OP_SYM_ETYPE still is struct foo
6072 * The frontend seems to guarantee that IC_LEFT has the correct size,
6073 * it works fine both for larger and smaller types of `char c'.
6075 //assert (size == getSize(OP_SYM_ETYPE(result)));
6076 assert (size > 0 && size <= 4);
6078 /* pass arguments */
6079 /* - value (MSB in Gstack_base_addr-2, growing downwards) */
6085 mov2w_op (right, off);
6086 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
6091 assert (AOP_SIZE(result) == 3);
6092 mov2w(AOP(result), 0);
6093 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
6094 mov2w(AOP(result), 1);
6095 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
6096 mov2w(AOP(result), 2);
6097 call_libraryfunc (func[size]);
6100 freeAsmop(right,NULL,ic,TRUE);
6101 freeAsmop(result,NULL,ic,TRUE);
6104 /*-----------------------------------------------------------------*/
6105 /* genPointerSet - stores the value into a pointer location */
6106 /*-----------------------------------------------------------------*/
6107 static void genPointerSet (iCode *ic)
6109 operand *right, *result ;
6110 sym_link *type, *etype;
6114 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6116 right = IC_RIGHT(ic);
6117 result = IC_RESULT(ic) ;
6119 /* depending on the type of pointer we need to
6120 move it to the correct pointer register */
6121 type = operandType(result);
6122 etype = getSpec(type);
6123 /* if left is of type of pointer then it is simple */
6124 if (IS_PTR(type) && !IS_FUNC(type->next)) {
6125 p_type = DCL_TYPE(type);
6128 /* we have to go by the storage class */
6129 p_type = PTR_TYPE(SPEC_OCLS(etype));
6131 /* if (SPEC_OCLS(etype)->codesp ) { */
6132 /* p_type = CPOINTER ; */
6135 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6136 /* p_type = FPOINTER ; */
6138 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6139 /* p_type = PPOINTER ; */
6141 /* if (SPEC_OCLS(etype) == idata ) */
6142 /* p_type = IPOINTER ; */
6144 /* p_type = POINTER ; */
6147 /* now that we have the pointer type we assign
6148 the pointer values */
6154 genNearPointerSet (right,result,ic);
6158 genPagedPointerSet (right,result,ic);
6162 genFarPointerSet (right,result,ic);
6166 genGenPointerSet (right,result,ic);
6170 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6171 "genPointerSet: illegal pointer type");
6175 /*-----------------------------------------------------------------*/
6176 /* genIfx - generate code for Ifx statement */
6177 /*-----------------------------------------------------------------*/
6178 static void genIfx (iCode *ic, iCode *popIc)
6180 operand *cond = IC_COND(ic);
6184 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6186 aopOp(cond,ic,FALSE);
6188 /* get the value into acc */
6189 if (AOP_TYPE(cond) != AOP_CRY)
6190 pic14_toBoolean(cond);
6194 /* if there was something to be popped then do it */
6200 /* This assumes that CARRY is set iff cond is true */
6203 assert (!IC_FALSE(ic));
6204 emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
6206 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
6208 assert (IC_FALSE(ic));
6209 emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
6211 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
6215 static int hasWarned = 0;
6218 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
6225 /* now Z is set iff !cond */
6228 assert (!IC_FALSE(ic));
6230 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
6233 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
6239 /* the result is now in the accumulator */
6240 freeAsmop(cond,NULL,ic,TRUE);
6243 /*-----------------------------------------------------------------*/
6244 /* genAddrOf - generates code for address of */
6245 /*-----------------------------------------------------------------*/
6246 static void genAddrOf (iCode *ic)
6248 operand *right, *result, *left;
6252 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6255 //aopOp(IC_RESULT(ic),ic,FALSE);
6257 aopOp((left=IC_LEFT(ic)),ic,FALSE);
6258 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6259 aopOp((result=IC_RESULT(ic)),ic,TRUE);
6261 DEBUGpic14_AopType(__LINE__,left,right,result);
6262 assert (IS_SYMOP (left));
6264 /* sanity check: generic pointers to code space are not yet supported,
6265 * pionters to codespace must not be assigned addresses of __data values. */
6267 fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
6268 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)));
6269 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)));
6270 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)));
6271 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)));
6274 if (IS_SYMOP(result) && IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
6275 fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
6276 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
6277 OP_SYMBOL(left)->name);
6278 } else if (IS_SYMOP(result) && !IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
6279 fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
6280 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
6281 OP_SYMBOL(left)->name);
6284 size = AOP_SIZE(IC_RESULT(ic));
6285 if (IS_SYMOP(result) && IS_GENPTR(OP_SYM_TYPE(result))) {
6287 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
6292 /* fixing bug #863624, reported from (errolv) */
6293 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
6294 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
6297 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
6298 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6303 if (IS_SYMOP(result) && IS_GENPTR(OP_SYM_TYPE(result)))
6305 /* provide correct tag */
6306 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
6307 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
6308 movwf (AOP(result), 2);
6311 freeAsmop(left,NULL,ic,FALSE);
6312 freeAsmop(result,NULL,ic,TRUE);
6316 /*-----------------------------------------------------------------*/
6317 /* genAssign - generate code for assignment */
6318 /*-----------------------------------------------------------------*/
6319 static void genAssign (iCode *ic)
6321 operand *result, *right;
6322 int size, offset,know_W;
6323 unsigned long lit = 0L;
6325 result = IC_RESULT(ic);
6326 right = IC_RIGHT(ic) ;
6329 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6331 /* if they are the same */
6332 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
6335 aopOp(right,ic,FALSE);
6336 aopOp(result,ic,TRUE);
6338 DEBUGpic14_AopType(__LINE__,NULL,right,result);
6340 /* if they are the same registers */
6341 if (pic14_sameRegs(AOP(right),AOP(result)))
6344 /* special case: assign from __code */
6345 if (!IS_ITEMP(right) /* --> iTemps never reside in __code */
6346 && IS_SYMOP (right) /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
6347 && !IS_FUNC(OP_SYM_TYPE(right)) /* --> we would want its address instead of the first instruction */
6348 && !IS_CODEPTR(OP_SYM_TYPE(right)) /* --> get symbols address instread */
6349 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
6351 emitpComment ("genAssign from CODESPACE");
6352 genConstPointerGet (right, result, ic);
6356 /* just for symmetry reasons... */
6357 if (!IS_ITEMP(result)
6358 && IS_SYMOP (result)
6359 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
6361 assert ( !"cannot write to CODESPACE" );
6364 /* if the result is a bit */
6365 if (AOP_TYPE(result) == AOP_CRY) {
6367 /* if the right size is a literal then
6368 we know what the value is */
6369 if (AOP_TYPE(right) == AOP_LIT) {
6371 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
6372 popGet(AOP(result),0));
6374 if (((int) operandLitValue(right)))
6375 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
6376 AOP(result)->aopu.aop_dir,
6377 AOP(result)->aopu.aop_dir);
6379 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
6380 AOP(result)->aopu.aop_dir,
6381 AOP(result)->aopu.aop_dir);
6385 /* the right is also a bit variable */
6386 if (AOP_TYPE(right) == AOP_CRY) {
6387 emitpcode(POC_BCF, popGet(AOP(result),0));
6388 emitpcode(POC_BTFSC, popGet(AOP(right),0));
6389 emitpcode(POC_BSF, popGet(AOP(result),0));
6391 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
6392 AOP(result)->aopu.aop_dir,
6393 AOP(result)->aopu.aop_dir);
6394 pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
6395 AOP(right)->aopu.aop_dir,
6396 AOP(right)->aopu.aop_dir);
6397 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
6398 AOP(result)->aopu.aop_dir,
6399 AOP(result)->aopu.aop_dir);
6404 emitpcode(POC_BCF, popGet(AOP(result),0));
6405 pic14_toBoolean(right);
6407 emitpcode(POC_BSF, popGet(AOP(result),0));
6408 //aopPut(AOP(result),"a",0);
6412 /* bit variables done */
6414 size = AOP_SIZE(result);
6416 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
6417 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6418 if(aopIdx(AOP(result),0) == 4) {
6419 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6420 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
6421 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6424 DEBUGpic14_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
6430 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6431 if(AOP_TYPE(right) == AOP_LIT) {
6432 lit = (unsigned long)pic14aopLiteral(AOP(right)->aopu.aop_lit, offset) & 0x0ff;
6434 if(know_W != (int)(lit&0xff))
6435 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
6437 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6439 emitpcode(POC_CLRF, popGet(AOP(result),offset));
6441 } else if (AOP_TYPE(right) == AOP_CRY) {
6442 emitpcode(POC_CLRF, popGet(AOP(result),offset));
6444 emitpcode(POC_BTFSS, popGet(AOP(right),0));
6445 emitpcode(POC_INCF, popGet(AOP(result),0));
6448 mov2w_op (right, offset);
6449 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6457 freeAsmop (right,NULL,ic,FALSE);
6458 freeAsmop (result,NULL,ic,TRUE);
6461 /*-----------------------------------------------------------------*/
6462 /* genJumpTab - genrates code for jump table */
6463 /*-----------------------------------------------------------------*/
6464 static void genJumpTab (iCode *ic)
6470 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6472 aopOp(IC_JTCOND(ic),ic,FALSE);
6473 /* get the condition into accumulator */
6474 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
6476 /* multiply by three */
6477 pic14_emitcode("add","a,acc");
6478 pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
6480 jtab = newiTempLabel(NULL);
6481 pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
6482 pic14_emitcode("jmp","@a+dptr");
6483 pic14_emitcode("","%05d_DS_:",jtab->key+100);
6485 emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
6486 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
6487 emitpcode(POC_MOVLW, popGetLabel(jtab->key));
6488 emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
6490 emitpcode(POC_INCF, popCopyReg(&pc_pclath));
6491 emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
6492 emitpLabel(jtab->key);
6494 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
6496 /* now generate the jump labels */
6497 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
6498 jtab = setNextItem(IC_JTLABELS(ic))) {
6499 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
6500 emitpcode(POC_GOTO,popGetLabel(jtab->key));
6506 /*-----------------------------------------------------------------*/
6507 /* genCast - gen code for casting */
6508 /*-----------------------------------------------------------------*/
6509 static void genCast (iCode *ic)
6511 operand *result = IC_RESULT(ic);
6512 sym_link *restype = operandType(result);
6513 sym_link *rtype = operandType(IC_RIGHT(ic));
6514 operand *right = IC_RIGHT(ic);
6518 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
6519 /* if they are equivalent then do nothing */
6520 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
6523 aopOp(right,ic,FALSE) ;
6524 aopOp(result,ic,FALSE);
6526 DEBUGpic14_AopType(__LINE__,NULL,right,result);
6528 /* if the result is a bit */
6529 if (AOP_TYPE(result) == AOP_CRY) {
6530 assert(!"assigning to bit variables is not supported");
6533 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
6535 size = AOP_SIZE(result);
6537 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
6539 emitpcode(POC_CLRF, popGet(AOP(result),0));
6540 emitpcode(POC_BTFSC, popGet(AOP(right),0));
6541 emitpcode(POC_INCF, popGet(AOP(result),0));
6544 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
6549 if (IS_PTR(restype))
6551 operand *result = IC_RESULT(ic);
6552 //operand *left = IC_LEFT(ic);
6553 operand *right = IC_RIGHT(ic);
6556 /* copy common part */
6557 int max, size = AOP_SIZE(result);
6558 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
6559 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
6561 /* warn if we discard generic opinter tag */
6562 if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
6564 //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
6570 mov2w_op (right, size);
6571 movwf (AOP(result), size);
6574 /* upcast into generic pointer type? */
6575 if (IS_GENPTR(restype)
6576 && (size < AOP_SIZE(result))
6577 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
6579 //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
6582 switch (DCL_TYPE(rtype))
6584 case POINTER: /* __data */
6585 case FPOINTER: /* __data */
6586 assert (AOP_SIZE(right) == 2);
6590 case CPOINTER: /* __code */
6591 assert (AOP_SIZE(right) == 2);
6595 case GPOINTER: /* unknown destination, __data or __code */
6596 /* assume __data space (address of immediate) */
6597 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
6598 if (AOP(right)->code)
6605 assert (!"unhandled pointer type");
6608 /* convert other values into pointers to __data space */
6612 assert (AOP_SIZE(result) == 3);
6614 emitpcode(POC_CLRF, popGet(AOP(result), 2));
6616 emitpcode(POC_MOVLW, popGetLit(tag));
6617 movwf(AOP(result), 2);
6620 addSign(result, max, 0);
6625 /* if they are the same size : or less */
6626 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
6628 /* if they are in the same place */
6629 if (pic14_sameRegs(AOP(right),AOP(result)))
6632 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
6633 if (IS_PTR_CONST(rtype))
6634 DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
6635 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
6636 DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
6638 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
6639 emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
6640 emitpcode(POC_MOVWF, popGet(AOP(result),0));
6641 emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
6642 emitpcode(POC_MOVWF, popGet(AOP(result),1));
6643 if(AOP_SIZE(result) <2)
6644 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
6648 /* if they in different places then copy */
6649 size = AOP_SIZE(result);
6652 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
6653 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6655 //aopPut(AOP(result),
6656 // aopGet(AOP(right),offset,FALSE,FALSE),
6665 /* so we now know that the size of destination is greater
6666 than the size of the source. */
6668 /* we move to result for the size of source */
6669 size = AOP_SIZE(right);
6672 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
6673 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6677 addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
6680 freeAsmop(right,NULL,ic,TRUE);
6681 freeAsmop(result,NULL,ic,TRUE);
6685 /*-----------------------------------------------------------------*/
6686 /* genDjnz - generate decrement & jump if not zero instrucion */
6687 /*-----------------------------------------------------------------*/
6688 static int genDjnz (iCode *ic, iCode *ifx)
6692 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6697 /* if the if condition has a false label
6698 then we cannot save */
6702 /* if the minus is not of the form
6704 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
6705 !IS_OP_LITERAL(IC_RIGHT(ic)))
6708 if (operandLitValue(IC_RIGHT(ic)) != 1)
6711 /* if the size of this greater than one then no
6713 if (getSize(operandType(IC_RESULT(ic))) > 1)
6716 /* otherwise we can save BIG */
6717 lbl = newiTempLabel(NULL);
6718 lbl1= newiTempLabel(NULL);
6720 aopOp(IC_RESULT(ic),ic,FALSE);
6722 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
6723 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
6725 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
6730 /*-----------------------------------------------------------------*/
6731 /* genReceive - generate code for a receive iCode */
6732 /*-----------------------------------------------------------------*/
6733 static void genReceive (iCode *ic)
6736 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6738 if (isOperandInFarSpace(IC_RESULT(ic)) &&
6739 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
6740 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
6742 int size = getSize(operandType(IC_RESULT(ic)));
6743 int offset = fReturnSizePic - size;
6745 pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
6746 fReturn[fReturnSizePic - offset - 1] : "acc"));
6749 aopOp(IC_RESULT(ic),ic,FALSE);
6750 size = AOP_SIZE(IC_RESULT(ic));
6753 pic14_emitcode ("pop","acc");
6754 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
6759 aopOp(IC_RESULT(ic),ic,FALSE);
6761 GpsuedoStkPtr = ic->parmBytes; // address used arg on stack
6762 assignResultValue(IC_RESULT(ic));
6765 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
6768 /*-----------------------------------------------------------------*/
6769 /* genDummyRead - generate code for dummy read of volatiles */
6770 /*-----------------------------------------------------------------*/
6772 genDummyRead (iCode * ic)
6775 pic14_emitcode ("; genDummyRead","");
6776 pic14_emitcode ("; not implemented","");
6781 /*-----------------------------------------------------------------*/
6782 /* genpic14Code - generate code for pic14 based controllers */
6783 /*-----------------------------------------------------------------*/
6785 * At this point, ralloc.c has gone through the iCode and attempted
6786 * to optimize in a way suitable for a PIC. Now we've got to generate
6787 * PIC instructions that correspond to the iCode.
6789 * Once the instructions are generated, we'll pass through both the
6790 * peep hole optimizer and the pCode optimizer.
6791 *-----------------------------------------------------------------*/
6793 void genpic14Code (iCode *lic)
6800 lineHead = lineCurr = NULL;
6802 pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
6805 /* if debug information required */
6806 if (options.debug && debugFile && currFunc) {
6807 debugFile->writeFunction (currFunc, lic);
6811 for (ic = lic ; ic ; ic = ic->next ) {
6813 //DEBUGpic14_emitcode(";ic","");
6814 //fprintf (stderr, "in ic loop\n");
6815 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
6816 //ic->lineno, printCLine(ic->filename, ic->lineno));
6818 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
6820 //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
6821 cline = printCLine (ic->filename, ic->lineno);
6822 if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
6823 addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
6824 //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
6827 if (options.iCodeInAsm) {
6828 const char *iLine = printILine(ic);
6829 emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
6832 /* if the result is marked as
6833 spilt and rematerializable or code for
6834 this has already been generated then
6836 if (resultRemat(ic) || ic->generated )
6839 /* depending on the operation */
6858 /* IPOP happens only when trying to restore a
6859 spilt live range, if there is an ifx statement
6860 following this pop then the if statement might
6861 be using some of the registers being popped which
6862 would destory the contents of the register so
6863 we need to check for this condition and handle it */
6865 ic->next->op == IFX &&
6866 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
6867 genIfx (ic->next,ic);
6885 genEndFunction (ic);
6905 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
6922 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
6926 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
6933 /* note these two are xlated by algebraic equivalence
6934 during parsing SDCC.y */
6935 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
6936 "got '>=' or '<=' shouldn't have come here");
6940 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
6952 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
6956 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
6960 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
6987 case GET_VALUE_AT_ADDRESS:
6992 if (POINTER_SET(ic))
7019 addSet(&_G.sendSet,ic);
7022 case DUMMY_READ_VOLATILE:
7027 fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
7034 /* now we are ready to call the
7035 peep hole optimizer */
7036 if (!options.nopeep) {
7037 peepHole (&lineHead);
7039 /* now do the actual printing */
7040 printLine (lineHead,codeOutBuf);
7043 DFPRINTF((stderr,"printing pBlock\n\n"));
7044 printpBlock(stdout,pb);
7050 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
7051 * (meaning: representing its own address) or not (referencing its contents).
7052 * This can only be decided based on the operand's type. */
7054 aop_isLitLike (asmop *aop)
7057 if (aop->type == AOP_LIT) return 1;
7058 if (aop->type == AOP_IMMD) return 1;
7059 if ((aop->type == AOP_PCODE) &&
7060 ((aop->aopu.pcop->type == PO_LITERAL)))
7062 /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
7063 * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
7070 op_isLitLike (operand *op)
7073 if (aop_isLitLike (AOP(op))) return 1;
7074 if (IS_SYMOP(op) && IS_FUNC(OP_SYM_TYPE(op))) return 1;
7075 if (IS_SYMOP(op) && IS_PTR(OP_SYM_TYPE(op))
7076 && (AOP_TYPE(op) == AOP_PCODE)
7077 && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {