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;
1631 l = aopGet(AOP(op),3,FALSE,FALSE);
1635 pic14_emitcode("cpl","acc.7");
1636 aopPut(AOP(result),"a",3);
1640 aopGet(AOP(op),offset,FALSE,FALSE),
1646 /*-----------------------------------------------------------------*/
1647 /* genUminus - unary minus code generation */
1648 /*-----------------------------------------------------------------*/
1649 static void genUminus (iCode *ic)
1652 sym_link *optype, *rtype;
1656 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1658 aopOp(IC_LEFT(ic),ic,FALSE);
1659 aopOp(IC_RESULT(ic),ic,TRUE);
1661 /* if both in bit space then special
1663 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1664 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1666 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0));
1667 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
1668 emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0));
1673 optype = operandType(IC_LEFT(ic));
1674 rtype = operandType(IC_RESULT(ic));
1676 /* if float then do float stuff */
1677 if (IS_FLOAT(optype)) {
1678 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1682 /* otherwise subtract from zero by taking the 2's complement */
1683 size = AOP_SIZE(IC_LEFT(ic));
1685 for(i=0; i<size; i++) {
1686 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
1687 emitpcode(POC_COMF, popGet(AOP(IC_LEFT(ic)),i));
1689 emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
1690 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
1694 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0));
1695 for(i=1; i<size; i++) {
1697 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),i));
1701 /* release the aops */
1702 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1703 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1706 /*-----------------------------------------------------------------*/
1707 /* saverbank - saves an entire register bank on the stack */
1708 /*-----------------------------------------------------------------*/
1709 static void saverbank (int bank, iCode *ic, bool pushPsw)
1713 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
1719 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1720 if (options.useXstack) {
1723 r = getFreePtr(ic,&aop,FALSE);
1724 pic14_emitcode("mov","%s,_spx",r->name);
1728 for (i = 0 ; i < pic14_nRegs ;i++) {
1729 if (options.useXstack) {
1730 pic14_emitcode("inc","%s",r->name);
1731 //pic14_emitcode("mov","a,(%s+%d)",
1732 // regspic14[i].base,8*bank+regspic14[i].offset);
1733 pic14_emitcode("movx","@%s,a",r->name);
1735 pic14_emitcode("push","");// "(%s+%d)",
1736 //regspic14[i].base,8*bank+regspic14[i].offset);
1740 if (options.useXstack) {
1741 pic14_emitcode("mov","a,psw");
1742 pic14_emitcode("movx","@%s,a",r->name);
1743 pic14_emitcode("inc","%s",r->name);
1744 pic14_emitcode("mov","_spx,%s",r->name);
1745 freeAsmop (NULL,aop,ic,TRUE);
1748 pic14_emitcode("push","psw");
1750 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1756 /*-----------------------------------------------------------------*/
1757 /* saveRegisters - will look for a call and save the registers */
1758 /*-----------------------------------------------------------------*/
1759 static void saveRegisters(iCode *lic)
1767 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1769 for (ic = lic ; ic ; ic = ic->next)
1770 if (ic->op == CALL || ic->op == PCALL)
1774 fprintf(stderr,"found parameter push with no function call\n");
1778 /* if the registers have been saved already then
1780 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
1783 /* find the registers in use at this time
1784 and push them away to safety */
1785 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1790 //fprintf(stderr, "ERROR: saveRegisters did not do anything to save registers, please report this as a bug.\n");
1792 dtype = operandType(IC_LEFT(ic));
1793 if (currFunc && dtype &&
1794 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
1795 IFFUNC_ISISR(currFunc->type) &&
1798 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
1801 /*-----------------------------------------------------------------*/
1802 /* unsaveRegisters - pop the pushed registers */
1803 /*-----------------------------------------------------------------*/
1804 static void unsaveRegisters (iCode *ic)
1811 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1812 /* find the registers in use at this time
1813 and push them away to safety */
1814 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1817 if (options.useXstack) {
1818 pic14_emitcode("mov","r0,%s",spname);
1819 for (i = pic14_nRegs ; i >= 0 ; i--) {
1820 if (bitVectBitValue(rsave,i)) {
1821 pic14_emitcode("dec","r0");
1822 pic14_emitcode("movx","a,@r0");
1823 pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
1827 pic14_emitcode("mov","%s,r0",spname);
1829 //for (i = pic14_nRegs ; i >= 0 ; i--) {
1830 // if (bitVectBitValue(rsave,i))
1831 // pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
1837 /*-----------------------------------------------------------------*/
1839 /*-----------------------------------------------------------------*/
1840 static void pushSide(operand * oper, int size)
1844 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1846 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1847 if (AOP_TYPE(oper) != AOP_REG &&
1848 AOP_TYPE(oper) != AOP_DIR &&
1850 pic14_emitcode("mov","a,%s",l);
1851 pic14_emitcode("push","acc");
1853 pic14_emitcode("push","%s",l);
1858 /*-----------------------------------------------------------------*/
1859 /* assignResultValue - */
1860 /*-----------------------------------------------------------------*/
1861 static void assignResultValue(operand * oper)
1863 int size = AOP_SIZE(oper);
1868 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1870 DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
1872 /* assign MSB first (passed via WREG) */
1874 get_returnvalue (oper, size, offset + GpsuedoStkPtr);
1880 /*-----------------------------------------------------------------*/
1881 /* genIpush - genrate code for pushing this gets a little complex */
1882 /*-----------------------------------------------------------------*/
1883 static void genIpush (iCode *ic)
1887 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
1889 int size, offset = 0 ;
1893 /* if this is not a parm push : ie. it is spill push
1894 and spill push is always done on the local stack */
1895 if (!ic->parmPush) {
1897 /* and the item is spilt then do nothing */
1898 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1901 aopOp(IC_LEFT(ic),ic,FALSE);
1902 size = AOP_SIZE(IC_LEFT(ic));
1903 /* push it on the stack */
1905 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1910 pic14_emitcode("push","%s",l);
1915 /* this is a paramter push: in this case we call
1916 the routine to find the call and save those
1917 registers that need to be saved */
1920 /* then do the push */
1921 aopOp(IC_LEFT(ic),ic,FALSE);
1924 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1925 size = AOP_SIZE(IC_LEFT(ic));
1928 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1929 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1930 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1932 pic14_emitcode("mov","a,%s",l);
1933 pic14_emitcode("push","acc");
1935 pic14_emitcode("push","%s",l);
1938 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1942 /*-----------------------------------------------------------------*/
1943 /* genIpop - recover the registers: can happen only for spilling */
1944 /*-----------------------------------------------------------------*/
1945 static void genIpop (iCode *ic)
1949 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
1950 assert (!"genIpop -- unimplemented");
1955 /* if the temp was not pushed then */
1956 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1959 aopOp(IC_LEFT(ic),ic,FALSE);
1960 size = AOP_SIZE(IC_LEFT(ic));
1963 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1966 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1970 /*-----------------------------------------------------------------*/
1971 /* unsaverbank - restores the resgister bank from stack */
1972 /*-----------------------------------------------------------------*/
1973 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1977 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
1983 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1985 if (options.useXstack) {
1987 r = getFreePtr(ic,&aop,FALSE);
1990 pic14_emitcode("mov","%s,_spx",r->name);
1991 pic14_emitcode("movx","a,@%s",r->name);
1992 pic14_emitcode("mov","psw,a");
1993 pic14_emitcode("dec","%s",r->name);
1996 pic14_emitcode ("pop","psw");
1999 for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2000 if (options.useXstack) {
2001 pic14_emitcode("movx","a,@%s",r->name);
2002 //pic14_emitcode("mov","(%s+%d),a",
2003 // regspic14[i].base,8*bank+regspic14[i].offset);
2004 pic14_emitcode("dec","%s",r->name);
2007 pic14_emitcode("pop",""); //"(%s+%d)",
2008 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2011 if (options.useXstack) {
2013 pic14_emitcode("mov","_spx,%s",r->name);
2014 freeAsmop(NULL,aop,ic,TRUE);
2020 /*-----------------------------------------------------------------*/
2021 /* genCall - generates a call statement */
2022 /*-----------------------------------------------------------------*/
2023 static void genCall (iCode *ic)
2032 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2034 /* if caller saves & we have not saved then */
2038 /* if we are calling a function that is not using
2039 the same register bank then we need to save the
2040 destination registers on the stack */
2041 dtype = operandType(IC_LEFT(ic));
2042 if (currFunc && dtype &&
2043 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2044 IFFUNC_ISISR(currFunc->type) &&
2047 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2049 /* if send set is not empty the assign */
2052 /* For the Pic port, there is no data stack.
2053 * So parameters passed to functions are stored
2054 * in registers. (The pCode optimizer will get
2055 * rid of most of these :).
2057 int psuedoStkPtr=-1;
2058 int firstTimeThruLoop = 1;
2060 _G.sendSet = reverseSet(_G.sendSet);
2062 /* First figure how many parameters are getting passed */
2063 for (sic = setFirstItem(_G.sendSet) ; sic ;
2064 sic = setNextItem(_G.sendSet)) {
2066 aopOp(IC_LEFT(sic),sic,FALSE);
2067 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2068 freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2071 for (sic = setFirstItem(_G.sendSet) ; sic ;
2072 sic = setNextItem(_G.sendSet)) {
2073 int size, offset = 0;
2075 aopOp(IC_LEFT(sic),sic,FALSE);
2076 size = AOP_SIZE(IC_LEFT(sic));
2079 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2080 AopType(AOP_TYPE(IC_LEFT(sic))));
2082 if(!firstTimeThruLoop) {
2083 /* If this is not the first time we've been through the loop
2084 * then we need to save the parameter in a temporary
2085 * register. The last byte of the last parameter is
2087 emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2090 firstTimeThruLoop=0;
2092 mov2w_op (IC_LEFT(sic), offset);
2095 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2100 sym = OP_SYMBOL(IC_LEFT(ic));
2101 name = sym->rname[0] ? sym->rname : sym->name;
2103 * As SDCC emits code as soon as it reaches the end of each
2104 * function's definition, prototyped functions that are implemented
2105 * after the current one are always considered EXTERN, which
2106 * introduces many unneccessary PAGESEL instructions.
2107 * XXX: Use a post pass to iterate over all `CALL _name' statements
2108 * and insert `PAGESEL _name' and `PAGESEL $' around the CALL
2109 * only iff there is no definition of the function in the whole
2110 * file (might include this in the PAGESEL pass).
2112 isExtern = IS_EXTERN(sym->etype) || pic14_inISR;
2114 /* Extern functions and ISRs maybe on a different page;
2115 * must call pagesel */
2116 emitpcode(POC_PAGESEL,popGetWithString(name,1));
2118 emitpcode(POC_CALL,popGetWithString(name,isExtern));
2120 /* May have returned from a different page;
2121 * must use pagesel to restore PCLATH before next
2122 * goto or call instruction */
2123 emitpcode(POC_PAGESEL,popGetWithString("$",0));
2126 /* if we need assign a result value */
2127 if ((IS_ITEMP(IC_RESULT(ic)) &&
2128 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2129 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2130 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2133 aopOp(IC_RESULT(ic),ic,FALSE);
2136 assignResultValue(IC_RESULT(ic));
2138 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2139 AopType(AOP_TYPE(IC_RESULT(ic))));
2141 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2144 /* if register bank was saved then pop them */
2146 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2148 /* if we hade saved some registers then unsave them */
2149 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2150 unsaveRegisters (ic);
2155 /*-----------------------------------------------------------------*/
2156 /* genPcall - generates a call by pointer statement */
2157 /*-----------------------------------------------------------------*/
2158 static void genPcall (iCode *ic)
2161 symbol *albl = newiTempLabel(NULL);
2162 symbol *blbl = newiTempLabel(NULL);
2169 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2170 /* if caller saves & we have not saved then */
2174 /* if we are calling a function that is not using
2175 the same register bank then we need to save the
2176 destination registers on the stack */
2177 dtype = operandType(IC_LEFT(ic));
2178 if (currFunc && dtype &&
2179 IFFUNC_ISISR(currFunc->type) &&
2180 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2181 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2184 aopOp(left,ic,FALSE);
2185 DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2187 poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2189 pushSide(IC_LEFT(ic), FPTRSIZE);
2191 /* if send set is not empty, assign parameters */
2194 DEBUGpic14_emitcode ("; ***","%s %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2195 /* no way to pass args - W always gets used to make the call */
2197 /* first idea - factor out a common helper function and call it.
2198 But don't know how to get it generated only once in its own block
2200 if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2203 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2204 DEBUGpic14_emitcode ("; ***","%s %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2205 buffer = Safe_calloc(1,strlen(rname)+16);
2206 sprintf(buffer, "%s_goto_helper", rname);
2207 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2211 emitpcode(POC_CALL,popGetLabel(albl->key));
2212 pcop = popGetLabel(blbl->key);
2213 emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
2214 emitpcode(POC_GOTO,pcop);
2215 emitpLabel(albl->key);
2217 emitpcode(poc,popGetAddr(AOP(left),1,0));
2218 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2219 emitpcode(poc,popGetAddr(AOP(left),0,0));
2220 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2222 emitpLabel(blbl->key);
2224 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2226 /* if we need to assign a result value */
2227 if ((IS_ITEMP(IC_RESULT(ic)) &&
2228 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2229 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2230 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2233 aopOp(IC_RESULT(ic),ic,FALSE);
2238 assignResultValue(IC_RESULT(ic));
2240 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2243 /* if register bank was saved then unsave them */
2244 if (currFunc && dtype &&
2245 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2246 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2248 /* if we hade saved some registers then
2251 unsaveRegisters (ic);
2255 /*-----------------------------------------------------------------*/
2256 /* resultRemat - result is rematerializable */
2257 /*-----------------------------------------------------------------*/
2258 static int resultRemat (iCode *ic)
2260 // DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2263 if (SKIP_IC(ic) || ic->op == IFX)
2266 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2267 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2268 if (sym->remat && !POINTER_SET(ic))
2275 /*-----------------------------------------------------------------*/
2276 /* genFunction - generated code for function entry */
2277 /*-----------------------------------------------------------------*/
2278 static void genFunction (iCode *ic)
2285 DEBUGpic14_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2287 labelOffset += (max_key+4);
2291 /* create the function header */
2292 pic14_emitcode(";","-----------------------------------------");
2293 pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2294 pic14_emitcode(";","-----------------------------------------");
2296 /* prevent this symbol from being emitted as 'extern' */
2297 pic14_stringInSet(sym->rname, &pic14_localFunctions, 1);
2299 pic14_emitcode("","%s:",sym->rname);
2300 addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2302 /* mark symbol as NOT extern (even if it was declared so previously) */
2303 assert(IS_SPEC(sym->etype));
2304 SPEC_EXTR(sym->etype) = 0;
2306 if (!SPEC_OCLS(sym->etype)) SPEC_OCLS(sym->etype) = code;
2307 addSetIfnotP(&SPEC_OCLS(sym->etype)->syms, sym);
2309 ftype = operandType(IC_LEFT(ic));
2311 /* if critical function then turn interrupts off */
2312 if (IFFUNC_ISCRITICAL(ftype))
2313 pic14_emitcode("clr","ea");
2315 /* here we need to generate the equates for the
2316 register bank if required */
2318 if (FUNC_REGBANK(ftype) != rbank) {
2321 rbank = FUNC_REGBANK(ftype);
2322 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2323 if (strcmp(regspic14[i].base,"0") == 0)
2324 pic14_emitcode("","%s = 0x%02x",
2326 8*rbank+regspic14[i].offset);
2328 pic14_emitcode ("","%s = %s + 0x%02x",
2331 8*rbank+regspic14[i].offset);
2336 /* if this is an interrupt service routine */
2338 if (IFFUNC_ISISR(sym->type)) {
2340 emitpcode(POC_MOVWF, popCopyReg(&pc_wsave));
2341 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2342 /* XXX: Why? Does this assume that ssave and psave reside
2343 * in a shared bank or bank0? We cannot guarantee the
2346 emitpcode(POC_CLRF, popCopyReg(&pc_status));
2347 emitpcode(POC_MOVWF, popCopyReg(&pc_ssave));
2348 //emitpcode(POC_MOVWF, popGetExternal("___sdcc_saved_status",1 ));
2349 emitpcode(POC_MOVFW, popCopyReg(&pc_pclath));
2350 /* during an interrupt PCLATH must be cleared before a goto or call statement */
2351 emitpcode(POC_CLRF, popCopyReg(&pc_pclath));
2352 emitpcode(POC_MOVWF, popCopyReg(&pc_psave));
2353 //emitpcode(POC_MOVWF, popGetExternal("___sdcc_saved_pclath", 1));
2354 emitpcode(POC_MOVFW, popCopyReg(&pc_fsr));
2355 emitpcode(POC_MOVWF, popGetExternal("___sdcc_saved_fsr", 1));
2357 pBlockConvert2ISR(pb);
2358 pic14_hasInterrupt = 1;
2360 /* if callee-save to be used for this function
2361 then save the registers being used in this function */
2362 if (IFFUNC_CALLEESAVES(sym->type)) {
2365 /* if any registers used */
2366 if (sym->regsUsed) {
2367 /* save the registers used */
2368 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2369 if (bitVectBitValue(sym->regsUsed,i)) {
2370 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2378 /* set the register bank to the desired value */
2379 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2380 pic14_emitcode("push","psw");
2381 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);
2384 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2386 if (options.useXstack) {
2387 pic14_emitcode("mov","r0,%s",spname);
2388 pic14_emitcode("mov","a,_bp");
2389 pic14_emitcode("movx","@r0,a");
2390 pic14_emitcode("inc","%s",spname);
2394 /* set up the stack */
2395 pic14_emitcode ("push","_bp"); /* save the callers stack */
2397 pic14_emitcode ("mov","_bp,%s",spname);
2400 /* adjust the stack for the function */
2405 werror(W_STACK_OVERFLOW,sym->name);
2407 if (i > 3 && sym->recvSize < 4) {
2409 pic14_emitcode ("mov","a,sp");
2410 pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2411 pic14_emitcode ("mov","sp,a");
2416 pic14_emitcode("inc","sp");
2421 pic14_emitcode ("mov","a,_spx");
2422 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2423 pic14_emitcode ("mov","_spx,a");
2428 /*-----------------------------------------------------------------*/
2429 /* genEndFunction - generates epilogue for functions */
2430 /*-----------------------------------------------------------------*/
2431 static void genEndFunction (iCode *ic)
2433 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2437 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2439 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2441 pic14_emitcode ("mov","%s,_bp",spname);
2444 /* if use external stack but some variables were
2445 added to the local stack then decrement the
2447 if (options.useXstack && sym->stack) {
2448 pic14_emitcode("mov","a,sp");
2449 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2450 pic14_emitcode("mov","sp,a");
2454 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2455 if (options.useXstack) {
2456 pic14_emitcode("mov","r0,%s",spname);
2457 pic14_emitcode("movx","a,@r0");
2458 pic14_emitcode("mov","_bp,a");
2459 pic14_emitcode("dec","%s",spname);
2463 pic14_emitcode ("pop","_bp");
2467 /* restore the register bank */
2468 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2469 pic14_emitcode ("pop","psw");
2471 if (IFFUNC_ISISR(sym->type)) {
2473 /* now we need to restore the registers */
2474 /* if this isr has no bank i.e. is going to
2475 run with bank 0 , then we need to save more
2477 if (!FUNC_REGBANK(sym->type)) {
2479 /* if this function does not call any other
2480 function then we can be economical and
2481 save only those registers that are used */
2482 if (! IFFUNC_HASFCALL(sym->type)) {
2485 /* if any registers used */
2486 if (sym->regsUsed) {
2487 /* save the registers used */
2488 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2489 if (bitVectBitValue(sym->regsUsed,i)) {
2490 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2496 /* this function has a function call; cannot
2497 determines register usage so we will have the
2499 unsaverbank(0,ic,FALSE);
2503 /* if debug then send end of function */
2504 if (options.debug && debugFile && currFunc) {
2505 debugFile->writeEndFunction (currFunc, ic, 1);
2508 emitpcode(POC_MOVFW, popGetExternal("___sdcc_saved_fsr", 1));
2509 emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
2510 //emitpcode(POC_MOVFW, popGetExternal("___sdcc_saved_pclath", 1));
2511 emitpcode(POC_MOVFW, popCopyReg(&pc_psave));
2512 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
2513 emitpcode(POC_CLRF, popCopyReg(&pc_status)); // see genFunction
2514 //emitpcode(POC_SWAPFW, popGetExternal("___sdcc_saved_status", 1));
2515 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
2516 emitpcode(POC_MOVWF, popCopyReg(&pc_status));
2517 emitpcode(POC_SWAPF, popCopyReg(&pc_wsave));
2518 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
2519 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
2520 emitpcodeNULLop(POC_RETFIE);
2523 if (IFFUNC_ISCRITICAL(sym->type))
2524 pic14_emitcode("setb","ea");
2526 if (IFFUNC_CALLEESAVES(sym->type)) {
2529 /* if any registers used */
2530 if (sym->regsUsed) {
2531 /* save the registers used */
2532 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2533 if (bitVectBitValue(sym->regsUsed,i)) {
2534 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2540 /* if debug then send end of function */
2541 if (options.debug && debugFile && currFunc) {
2542 debugFile->writeEndFunction (currFunc, ic, 1);
2545 pic14_emitcode ("return","");
2546 emitpcodeNULLop(POC_RETURN);
2548 /* Mark the end of a function */
2549 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
2554 /*-----------------------------------------------------------------*/
2555 /* genRet - generate code for return statement */
2556 /*-----------------------------------------------------------------*/
2557 static void genRet (iCode *ic)
2559 int size,offset = 0;
2563 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2564 /* if we have no return value then
2565 just generate the "ret" */
2569 /* we have something to return then
2570 move the return value into place */
2571 aopOp(IC_LEFT(ic),ic,FALSE);
2572 size = AOP_SIZE(IC_LEFT(ic));
2574 for (offset = 0; offset < size; offset++)
2576 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
2579 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2582 /* generate a jump to the return label
2583 if the next is not the return statement */
2584 if (!(ic->next && ic->next->op == LABEL &&
2585 IC_LABEL(ic->next) == returnLabel)) {
2587 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
2592 /*-----------------------------------------------------------------*/
2593 /* genLabel - generates a label */
2594 /*-----------------------------------------------------------------*/
2595 static void genLabel (iCode *ic)
2599 /* special case never generate */
2600 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2601 if (IC_LABEL(ic) == entryLabel)
2604 emitpLabel(IC_LABEL(ic)->key);
2605 pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
2608 /*-----------------------------------------------------------------*/
2609 /* genGoto - generates a goto */
2610 /*-----------------------------------------------------------------*/
2612 static void genGoto (iCode *ic)
2616 emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
2617 pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
2621 /*-----------------------------------------------------------------*/
2622 /* genMultbits :- multiplication of bits */
2623 /*-----------------------------------------------------------------*/
2624 static void genMultbits (operand *left,
2629 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2631 if(!pic14_sameRegs(AOP(result),AOP(right)))
2632 emitpcode(POC_BSF, popGet(AOP(result),0));
2634 emitpcode(POC_BTFSC,popGet(AOP(right),0));
2635 emitpcode(POC_BTFSS,popGet(AOP(left),0));
2636 emitpcode(POC_BCF, popGet(AOP(result),0));
2641 /*-----------------------------------------------------------------*/
2642 /* genMultOneByte : 8 bit multiplication & division */
2643 /*-----------------------------------------------------------------*/
2644 static void genMultOneByte (operand *left,
2648 char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
2656 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2657 DEBUGpic14_AopType(__LINE__,left,right,result);
2658 DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
2660 /* (if two literals, the value is computed before) */
2661 /* if one literal, literal on the right */
2662 if (AOP_TYPE(left) == AOP_LIT){
2668 assert (AOP_SIZE(left) == AOP_SIZE(right));
2670 size = min(AOP_SIZE(result),AOP_SIZE(left));
2671 offset = Gstack_base_addr - (2*size - 1);
2673 /* pass right operand as argument */
2674 for (i=0; i < size; i++)
2676 mov2w (AOP(right), i);
2677 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
2680 /* pass left operand as argument */
2681 for (i=0; i < size; i++)
2683 mov2w (AOP(left), i);
2684 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
2686 assert (offset == Gstack_base_addr);
2688 /* call library routine */
2689 assert (size > 0 && size <= 4);
2690 call_libraryfunc (func[size]);
2693 movwf (AOP(result), size-1);
2694 for (i=0; i < size - 1; i++)
2696 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
2697 movwf (AOP(result), size - 2 - i);
2700 /* now (zero-/sign) extend the result to its size */
2701 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2704 /*-----------------------------------------------------------------*/
2705 /* genMult - generates code for multiplication */
2706 /*-----------------------------------------------------------------*/
2707 static void genMult (iCode *ic)
2709 operand *left = IC_LEFT(ic);
2710 operand *right = IC_RIGHT(ic);
2711 operand *result= IC_RESULT(ic);
2715 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2716 /* assign the amsops */
2717 aopOp (left,ic,FALSE);
2718 aopOp (right,ic,FALSE);
2719 aopOp (result,ic,TRUE);
2721 DEBUGpic14_AopType(__LINE__,left,right,result);
2723 /* special cases first */
2725 if (AOP_TYPE(left) == AOP_CRY &&
2726 AOP_TYPE(right)== AOP_CRY) {
2727 genMultbits(left,right,result);
2731 /* if both are of size == 1 */
2732 if (AOP_SIZE(left) == 1 &&
2733 AOP_SIZE(right) == 1 ) {
2734 genMultOneByte(left,right,result);
2738 /* should have been converted to function call */
2742 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2743 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2744 freeAsmop(result,NULL,ic,TRUE);
2747 /*-----------------------------------------------------------------*/
2748 /* genDivbits :- division of bits */
2749 /*-----------------------------------------------------------------*/
2750 static void genDivbits (operand *left,
2759 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2760 /* the result must be bit */
2761 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
2762 l = aopGet(AOP(left),0,FALSE,FALSE);
2766 pic14_emitcode("div","ab");
2767 pic14_emitcode("rrc","a");
2768 aopPut(AOP(result),"c",0);
2771 /*-----------------------------------------------------------------*/
2772 /* genDivOneByte : 8 bit division */
2773 /*-----------------------------------------------------------------*/
2774 static void genDivOneByte (operand *left,
2782 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2784 assert (AOP_SIZE(right) == 1);
2785 assert (AOP_SIZE(left) == 1);
2787 size = min(AOP_SIZE(result),AOP_SIZE(left));
2788 sign = !(SPEC_USIGN(operandType(left))
2789 && SPEC_USIGN(operandType(right)));
2791 if (AOP_TYPE(right) == AOP_LIT)
2793 /* XXX: might add specialized code */
2798 /* unsigned division */
2800 mov2w(AOP(right),0);
2801 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
2803 call_libraryfunc("__divuchar");
2804 movwf(AOP(result),0);
2809 temp = popGetTempReg();
2810 lbl = newiTempLabel(NULL);
2812 /* XXX: improve this naive approach:
2813 [result] = [a] / [b]
2814 ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
2818 movwf temp // temp <-- left
2819 movf right,W // W <-- right
2823 subwf temp,F // temp <-- temp - W
2824 skipNC // subwf clears CARRY (i.e. sets BORROW) if temp < W
2826 decf result // we just subtract once too often
2829 /* XXX: This loops endlessly on DIVIDE BY ZERO */
2830 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
2833 emitpcode(POC_MOVWF, temp);
2834 mov2w(AOP(right),0);
2835 emitpcode(POC_CLRF, popGet(AOP(result),0));
2837 emitpLabel(lbl->key);
2838 emitpcode(POC_INCF, popGet(AOP(result),0));
2839 emitpcode(POC_SUBWF, temp);
2841 emitpcode(POC_GOTO, popGetLabel(lbl->key));
2842 emitpcode(POC_DECF, popGet(AOP(result),0));
2843 popReleaseTempReg(temp);
2848 /* signed division */
2849 mov2w(AOP(right),0);
2850 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
2852 call_libraryfunc("__divschar");
2853 movwf(AOP(result),0);
2856 /* now performed the signed/unsigned division -- extend result */
2857 addSign(result, 1, sign);
2860 /*-----------------------------------------------------------------*/
2861 /* genDiv - generates code for division */
2862 /*-----------------------------------------------------------------*/
2863 static void genDiv (iCode *ic)
2865 operand *left = IC_LEFT(ic);
2866 operand *right = IC_RIGHT(ic);
2867 operand *result= IC_RESULT(ic);
2870 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2871 /* assign the amsops */
2872 aopOp (left,ic,FALSE);
2873 aopOp (right,ic,FALSE);
2874 aopOp (result,ic,TRUE);
2876 /* special cases first */
2878 if (AOP_TYPE(left) == AOP_CRY &&
2879 AOP_TYPE(right)== AOP_CRY) {
2880 genDivbits(left,right,result);
2884 /* if both are of size == 1 */
2885 if (AOP_SIZE(left) == 1 &&
2886 AOP_SIZE(right) == 1 ) {
2887 genDivOneByte(left,right,result);
2891 /* should have been converted to function call */
2894 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2895 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2896 freeAsmop(result,NULL,ic,TRUE);
2899 /*-----------------------------------------------------------------*/
2900 /* genModOneByte : 8 bit modulus */
2901 /*-----------------------------------------------------------------*/
2902 static void genModOneByte (operand *left,
2910 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2912 assert (AOP_SIZE(right) == 1);
2913 assert (AOP_SIZE(left) == 1);
2915 size = min(AOP_SIZE(result),AOP_SIZE(left));
2916 sign = !(SPEC_USIGN(operandType(left))
2917 && SPEC_USIGN(operandType(right)));
2919 if (AOP_TYPE(right) == AOP_LIT)
2921 /* XXX: might add specialized code */
2926 /* unsigned division */
2928 mov2w(AOP(right),0);
2929 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
2931 call_libraryfunc("__moduchar");
2932 movwf(AOP(result),0);
2937 lbl = newiTempLabel(NULL);
2939 assert(!pic14_sameRegs(AOP(right),AOP(result)));
2941 /* XXX: improve this naive approach:
2942 [result] = [a] % [b]
2943 ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
2947 movwf result // result <-- left
2948 movf right,W // W <-- right
2950 subwf result,F // result <-- result - W
2951 skipNC // subwf clears CARRY (i.e. sets BORROW) if result < W
2953 addwf result, F // we just subtract once too often
2956 /* XXX: This loops endlessly on DIVIDE BY ZERO */
2957 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
2959 if (!pic14_sameRegs(AOP(left), AOP(result)))
2962 emitpcode(POC_MOVWF, popGet(AOP(result),0));
2964 mov2w(AOP(right),0);
2966 emitpLabel(lbl->key);
2967 emitpcode(POC_SUBWF, popGet(AOP(result),0));
2969 emitpcode(POC_GOTO, popGetLabel(lbl->key));
2970 emitpcode(POC_ADDWF, popGet(AOP(result),0));
2975 /* signed division */
2976 mov2w(AOP(right),0);
2977 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
2979 call_libraryfunc("__modschar");
2980 movwf(AOP(result),0);
2983 /* now we performed the signed/unsigned modulus -- extend result */
2984 addSign(result, 1, sign);
2987 /*-----------------------------------------------------------------*/
2988 /* genMod - generates code for division */
2989 /*-----------------------------------------------------------------*/
2990 static void genMod (iCode *ic)
2992 operand *left = IC_LEFT(ic);
2993 operand *right = IC_RIGHT(ic);
2994 operand *result= IC_RESULT(ic);
2997 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2998 /* assign the amsops */
2999 aopOp (left,ic,FALSE);
3000 aopOp (right,ic,FALSE);
3001 aopOp (result,ic,TRUE);
3003 /* if both are of size == 1 */
3004 if (AOP_SIZE(left) == 1 &&
3005 AOP_SIZE(right) == 1 ) {
3006 genModOneByte(left,right,result);
3010 /* should have been converted to function call */
3014 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3015 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3016 freeAsmop(result,NULL,ic,TRUE);
3019 /*-----------------------------------------------------------------*/
3020 /* genIfxJump :- will create a jump depending on the ifx */
3021 /*-----------------------------------------------------------------*/
3023 note: May need to add parameter to indicate when a variable is in bit space.
3025 static void genIfxJump (iCode *ic, char *jval)
3029 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3030 /* if true label then we jump if condition
3032 if ( IC_TRUE(ic) ) {
3034 if(strcmp(jval,"a") == 0)
3036 else if (strcmp(jval,"c") == 0)
3039 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3040 emitpcode(POC_BTFSC, newpCodeOpBit(jval,-1,1));
3043 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3044 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3048 /* false label is present */
3049 if(strcmp(jval,"a") == 0)
3051 else if (strcmp(jval,"c") == 0)
3054 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3055 emitpcode(POC_BTFSS, newpCodeOpBit(jval,-1,1));
3058 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3059 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3064 /* mark the icode as generated */
3068 /*-----------------------------------------------------------------*/
3070 /*-----------------------------------------------------------------*/
3071 static void genSkipc(resolvedIfx *rifx)
3082 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3083 emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3084 rifx->generated = 1;
3087 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3088 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
3089 #define DEBUGpc emitpComment
3091 /*-----------------------------------------------------------------*/
3092 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
3093 /* aop (if it's NOT a literal) or from lit (if */
3094 /* aop is a literal) */
3095 /*-----------------------------------------------------------------*/
3096 static void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset)
3098 if (aop->type == AOP_LIT) {
3099 emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3101 emitpcode (POC_MOVFW, popGet (aop, offset));
3105 /* genCmp performs a left < right comparison, stores
3106 * the outcome in result (if != NULL) and generates
3107 * control flow code for the ifx (if != NULL).
3109 * This version leaves in sequences like
3110 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3111 * which should be optmized by the peephole
3112 * optimizer - RN 2005-01-01 */
3113 static void genCmp (operand *left,operand *right,
3114 operand *result, iCode *ifx, int sign)
3124 int invert_result = 0;
3128 assert (AOP_SIZE(left) == AOP_SIZE(right));
3129 assert (left && right);
3131 size = AOP_SIZE(right) - 1;
3132 mask = (0x100UL << (size*8)) - 1;
3133 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3138 resolveIfx (&rIfx, ifx);
3140 /**********************************************************************
3141 * handle bits - bit compares are promoted to int compares seemingly! *
3142 **********************************************************************/
3144 // THIS IS COMPLETELY UNTESTED!
3145 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3146 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3147 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3148 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3151 // 1 < {0,1} is false --> clear C by skipping the next instruction
3152 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3153 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3154 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3155 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3156 emitCLRC; // only skipped for left=0 && right=1
3158 goto correct_result_in_carry;
3162 /*************************************************
3163 * make sure that left is register (or the like) *
3164 *************************************************/
3165 if (!isAOP_REGlike(left)) {
3166 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
3167 assert (isAOP_LIT(left));
3168 assert (isAOP_REGlike(right));
3169 // swap left and right
3170 // left < right <==> right > left <==> (right >= left + 1)
3171 lit = ulFromVal(AOP(left)->aopu.aop_lit);
3173 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
3174 // MAXVALUE < right? always false
3175 if (performedLt) emitCLRC; else emitSETC;
3176 goto correct_result_in_carry;
3179 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
3180 // that's why we handled it above.
3187 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
3188 } else if (isAOP_LIT(right)) {
3189 lit = ulFromVal(AOP(right)->aopu.aop_lit);
3192 assert (isAOP_REGlike(left)); // left must be register or the like
3193 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
3195 /*************************************************
3196 * special cases go here *
3197 *************************************************/
3199 if (isAOP_LIT(right)) {
3201 // unsigned comparison to a literal
3202 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
3204 // unsigned left < 0? always false
3205 if (performedLt) emitCLRC; else emitSETC;
3206 goto correct_result_in_carry;
3209 // signed comparison to a literal
3210 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
3211 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
3212 // signed left < 0x80000000? always false
3213 if (performedLt) emitCLRC; else emitSETC;
3214 goto correct_result_in_carry;
3215 } else if (lit == 0) {
3216 // compare left < 0; set CARRY if SIGNBIT(left) is set
3217 if (performedLt) emitSETC; else emitCLRC;
3218 emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
3219 if (performedLt) emitCLRC; else emitSETC;
3220 goto correct_result_in_carry;
3223 } // right is literal
3225 /*************************************************
3226 * perform a general case comparison *
3227 * make sure we get CARRY==1 <==> left >= right *
3228 *************************************************/
3229 // compare most significant bytes
3230 //DEBUGpc ("comparing bytes at offset %d", size);
3232 // unsigned comparison
3233 pic14_mov2w_regOrLit (AOP(right), lit, size);
3234 emitpcode (POC_SUBFW, popGet (AOP(left), size));
3236 // signed comparison
3237 // (add 2^n to both operands then perform an unsigned comparison)
3238 if (isAOP_LIT(right)) {
3239 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
3240 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
3242 if (litbyte == 0x80) {
3243 // left >= 0x80 -- always true, but more bytes to come
3244 mov2w (AOP(left), size);
3245 emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
3248 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
3249 mov2w (AOP(left), size);
3250 emitpcode (POC_ADDLW, popGetLit (0x80));
3251 emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
3254 pCodeOp *pctemp = popGetTempReg();
3255 mov2w (AOP(left), size);
3256 emitpcode (POC_ADDLW, popGetLit (0x80));
3257 emitpcode (POC_MOVWF, pctemp);
3258 mov2w (AOP(right), size);
3259 emitpcode (POC_ADDLW, popGetLit (0x80));
3260 emitpcode (POC_SUBFW, pctemp);
3261 popReleaseTempReg(pctemp);
3265 // compare remaining bytes (treat as unsigned case from above)
3266 templbl = newiTempLabel ( NULL );
3269 //DEBUGpc ("comparing bytes at offset %d", offs);
3271 emitpcode (POC_GOTO, popGetLabel (templbl->key));
3272 pic14_mov2w_regOrLit (AOP(right), lit, offs);
3273 emitpcode (POC_SUBFW, popGet (AOP(left), offs));
3275 emitpLabel (templbl->key);
3276 goto result_in_carry;
3280 /****************************************************
3281 * now CARRY contains the result of the comparison: *
3282 * SUBWF sets CARRY iff *
3283 * F-W >= 0 <==> F >= W <==> !(F < W) *
3284 * (F=left, W=right) *
3285 ****************************************************/
3289 // value will be used in the following genSkipc()
3290 rIfx.condition ^= 1;
3293 correct_result_in_carry:
3295 // assign result to variable (if neccessary)
3296 if (result && AOP_TYPE(result) != AOP_CRY) {
3297 //DEBUGpc ("assign result");
3298 size = AOP_SIZE(result);
3300 emitpcode (POC_CLRF, popGet (AOP(result), size));
3302 if (invert_result) {
3304 emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
3306 emitpcode (POC_RLF, popGet (AOP(result), 0));
3310 // perform conditional jump
3312 //DEBUGpc ("generate control flow");
3318 /*-----------------------------------------------------------------*/
3319 /* genCmpGt :- greater than comparison */
3320 /*-----------------------------------------------------------------*/
3321 static void genCmpGt (iCode *ic, iCode *ifx)
3323 operand *left, *right, *result;
3324 sym_link *letype , *retype;
3328 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3330 right= IC_RIGHT(ic);
3331 result = IC_RESULT(ic);
3333 letype = getSpec(operandType(left));
3334 retype =getSpec(operandType(right));
3335 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3336 /* assign the amsops */
3337 aopOp (left,ic,FALSE);
3338 aopOp (right,ic,FALSE);
3339 aopOp (result,ic,TRUE);
3341 genCmp(right, left, result, ifx, sign);
3343 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3344 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3345 freeAsmop(result,NULL,ic,TRUE);
3348 /*-----------------------------------------------------------------*/
3349 /* genCmpLt - less than comparisons */
3350 /*-----------------------------------------------------------------*/
3351 static void genCmpLt (iCode *ic, iCode *ifx)
3353 operand *left, *right, *result;
3354 sym_link *letype , *retype;
3358 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3360 right= IC_RIGHT(ic);
3361 result = IC_RESULT(ic);
3363 letype = getSpec(operandType(left));
3364 retype =getSpec(operandType(right));
3365 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3367 /* assign the amsops */
3368 aopOp (left,ic,FALSE);
3369 aopOp (right,ic,FALSE);
3370 aopOp (result,ic,TRUE);
3372 genCmp(left, right, result, ifx, sign);
3374 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3375 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3376 freeAsmop(result,NULL,ic,TRUE);
3379 /*-----------------------------------------------------------------*/
3380 /* genCmpEq - generates code for equal to */
3381 /*-----------------------------------------------------------------*/
3382 static void genCmpEq (iCode *ic, iCode *ifx)
3384 operand *left, *right, *result;
3386 symbol *false_label;
3389 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3392 DEBUGpic14_emitcode ("; ifx is non-null","");
3394 DEBUGpic14_emitcode ("; ifx is null","");
3396 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3397 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3398 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3400 DEBUGpic14_AopType(__LINE__,left,right,result);
3402 /* if literal, move literal to right */
3403 if (op_isLitLike (IC_LEFT(ic))) {
3404 operand *tmp = right ;
3410 if (ifx && !IC_TRUE(ifx))
3412 assert (IC_FALSE(ifx));
3413 false_label = IC_FALSE(ifx);
3416 size = min(AOP_SIZE(left),AOP_SIZE(right));
3417 assert(!pic14_sameRegs(AOP(result),AOP(left)));
3418 assert(!pic14_sameRegs(AOP(result),AOP(right)));
3420 /* assume left != right */
3423 for (i=0; i < AOP_SIZE(result); i++)
3425 emitpcode(POC_CLRF, popGet(AOP(result),i));
3429 if (AOP_TYPE(right) == AOP_LIT)
3431 unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit);
3433 size = AOP_SIZE(left);
3434 assert(!op_isLitLike(left));
3439 mov2w(AOP(left), 0);
3440 for (i=1; i < size; i++)
3441 emitpcode(POC_IORFW,popGet(AOP(left),i));
3442 /* now Z is set iff `left == right' */
3444 if (!false_label) false_label = newiTempLabel(NULL);
3445 emitpcode(POC_GOTO, popGetLabel(false_label->key));
3449 for (i=0; i < size; i++)
3452 emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
3453 /* now Z is cleared if `left != right' */
3455 if (!false_label) false_label = newiTempLabel(NULL);
3456 emitpcode(POC_GOTO, popGetLabel(false_label->key));
3463 /* right is no literal */
3466 for (i=0; i < size; i++)
3468 mov2w(AOP(right),i);
3469 emitpcode(POC_XORFW,popGet(AOP(left),i));
3470 /* now Z is cleared if `left != right' */
3472 if (!false_label) false_label = newiTempLabel(NULL);
3473 emitpcode(POC_GOTO, popGetLabel(false_label->key));
3477 /* if we reach here, left == right */
3479 if (AOP_SIZE(result) > 0)
3481 emitpcode(POC_INCF, popGet(AOP(result),0));
3484 if (ifx && IC_TRUE(ifx))
3486 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3489 if (false_label && (!ifx || IC_TRUE(ifx)))
3490 emitpLabel(false_label->key);
3492 if (ifx) ifx->generated = 1;
3494 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3495 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3496 freeAsmop(result,NULL,ic,TRUE);
3499 /*-----------------------------------------------------------------*/
3500 /* ifxForOp - returns the icode containing the ifx for operand */
3501 /*-----------------------------------------------------------------*/
3502 static iCode *ifxForOp ( operand *op, iCode *ic )
3505 /* if true symbol then needs to be assigned */
3506 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3507 if (IS_TRUE_SYMOP(op))
3510 /* if this has register type condition and
3511 the next instruction is ifx with the same operand
3512 and live to of the operand is upto the ifx only then */
3514 ic->next->op == IFX &&
3515 IC_COND(ic->next)->key == op->key &&
3516 OP_SYMBOL(op)->liveTo <= ic->next->seq )
3520 ic->next->op == IFX &&
3521 IC_COND(ic->next)->key == op->key) {
3522 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
3526 DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
3528 ic->next->op == IFX)
3529 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
3532 ic->next->op == IFX &&
3533 IC_COND(ic->next)->key == op->key) {
3534 DEBUGpic14_emitcode ("; "," key is okay");
3535 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
3536 OP_SYMBOL(op)->liveTo,
3543 /*-----------------------------------------------------------------*/
3544 /* genAndOp - for && operation */
3545 /*-----------------------------------------------------------------*/
3546 static void genAndOp (iCode *ic)
3548 operand *left,*right, *result;
3552 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3553 /* note here that && operations that are in an
3554 if statement are taken away by backPatchLabels
3555 only those used in arthmetic operations remain */
3556 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3557 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3558 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3560 DEBUGpic14_AopType(__LINE__,left,right,result);
3562 emitpcode(POC_MOVFW,popGet(AOP(left),0));
3563 emitpcode(POC_ANDFW,popGet(AOP(right),0));
3564 emitpcode(POC_MOVWF,popGet(AOP(result),0));
3566 /* if both are bit variables */
3567 /* if (AOP_TYPE(left) == AOP_CRY && */
3568 /* AOP_TYPE(right) == AOP_CRY ) { */
3569 /* pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
3570 /* pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
3571 /* pic14_outBitC(result); */
3573 /* tlbl = newiTempLabel(NULL); */
3574 /* pic14_toBoolean(left); */
3575 /* pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
3576 /* pic14_toBoolean(right); */
3577 /* pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
3578 /* pic14_outBitAcc(result); */
3581 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3582 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3583 freeAsmop(result,NULL,ic,TRUE);
3587 /*-----------------------------------------------------------------*/
3588 /* genOrOp - for || operation */
3589 /*-----------------------------------------------------------------*/
3592 modified this code, but it doesn't appear to ever get called
3595 static void genOrOp (iCode *ic)
3597 operand *left,*right, *result;
3601 /* note here that || operations that are in an
3602 if statement are taken away by backPatchLabels
3603 only those used in arthmetic operations remain */
3605 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3606 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3607 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3608 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3610 DEBUGpic14_AopType(__LINE__,left,right,result);
3612 for (i=0; i < AOP_SIZE(result); i++)
3614 emitpcode(POC_CLRF, popGet(AOP(result), i));
3617 tlbl = newiTempLabel(NULL);
3618 pic14_toBoolean(left);
3620 emitpcode(POC_GOTO, popGetLabel(tlbl->key));
3621 pic14_toBoolean(right);
3622 emitpLabel(tlbl->key);
3623 /* here Z is clear IFF `left || right' */
3625 emitpcode(POC_INCF, popGet(AOP(result), 0));
3627 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3628 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3629 freeAsmop(result,NULL,ic,TRUE);
3632 /*-----------------------------------------------------------------*/
3633 /* isLiteralBit - test if lit == 2^n */
3634 /*-----------------------------------------------------------------*/
3635 static int isLiteralBit(unsigned long lit)
3637 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
3638 0x100L,0x200L,0x400L,0x800L,
3639 0x1000L,0x2000L,0x4000L,0x8000L,
3640 0x10000L,0x20000L,0x40000L,0x80000L,
3641 0x100000L,0x200000L,0x400000L,0x800000L,
3642 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
3643 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
3647 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3648 for(idx = 0; idx < 32; idx++)
3654 /*-----------------------------------------------------------------*/
3655 /* continueIfTrue - */
3656 /*-----------------------------------------------------------------*/
3657 static void continueIfTrue (iCode *ic)
3660 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3664 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
3665 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
3670 /*-----------------------------------------------------------------*/
3672 /*-----------------------------------------------------------------*/
3673 static void jumpIfTrue (iCode *ic)
3676 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3680 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
3681 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
3686 /*-----------------------------------------------------------------*/
3687 /* jmpTrueOrFalse - */
3688 /*-----------------------------------------------------------------*/
3689 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
3692 // ugly but optimized by peephole
3693 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3695 symbol *nlbl = newiTempLabel(NULL);
3696 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);
3697 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
3698 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
3699 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
3702 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
3703 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
3708 /*-----------------------------------------------------------------*/
3709 /* genAnd - code for and */
3710 /*-----------------------------------------------------------------*/
3711 static void genAnd (iCode *ic, iCode *ifx)
3713 operand *left, *right, *result;
3715 unsigned long lit = 0L;
3720 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3721 aopOp((left = IC_LEFT(ic)),ic,FALSE);
3722 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
3723 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3725 resolveIfx(&rIfx,ifx);
3727 /* if left is a literal & right is not then exchange them */
3728 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3729 AOP_NEEDSACC(left)) {
3730 operand *tmp = right ;
3735 /* if result = right then exchange them */
3736 if(pic14_sameRegs(AOP(result),AOP(right))){
3737 operand *tmp = right ;
3742 /* if right is bit then exchange them */
3743 if (AOP_TYPE(right) == AOP_CRY &&
3744 AOP_TYPE(left) != AOP_CRY){
3745 operand *tmp = right ;
3749 if(AOP_TYPE(right) == AOP_LIT)
3750 lit = ulFromVal (AOP(right)->aopu.aop_lit);
3752 size = AOP_SIZE(result);
3754 DEBUGpic14_AopType(__LINE__,left,right,result);
3757 // result = bit & yy;
3758 if (AOP_TYPE(left) == AOP_CRY){
3759 // c = bit & literal;
3760 if(AOP_TYPE(right) == AOP_LIT){
3762 if(size && pic14_sameRegs(AOP(result),AOP(left)))
3765 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3768 if(size && (AOP_TYPE(result) == AOP_CRY)){
3769 pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
3772 if((AOP_TYPE(result) == AOP_CRY) && ifx){
3776 pic14_emitcode("clr","c");
3779 if (AOP_TYPE(right) == AOP_CRY){
3781 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3782 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3785 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
3787 pic14_emitcode("rrc","a");
3788 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3794 pic14_outBitC(result);
3796 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
3797 genIfxJump(ifx, "c");
3801 // if(val & 0xZZ) - size = 0, ifx != FALSE -
3802 // bit = val & 0xZZ - size = 1, ifx = FALSE -
3803 if((AOP_TYPE(right) == AOP_LIT) &&
3804 (AOP_TYPE(result) == AOP_CRY) &&
3805 (AOP_TYPE(left) != AOP_CRY)){
3806 int posbit = isLiteralBit(lit);
3810 //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
3813 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
3818 while (posbit > 7) {
3822 emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
3823 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
3824 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
3831 symbol *tlbl = newiTempLabel(NULL);
3832 int sizel = AOP_SIZE(left);
3834 pic14_emitcode("setb","c");
3836 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
3837 mov2w( AOP(left), offset);
3839 if((posbit = isLiteralBit(bytelit)) != 0) {
3840 emitpcode(rIfx.condition ? POC_BTFSC : POC_BTFSS, // XXX: or the other way round?
3841 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit - 1, 0));
3842 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
3845 emitpcode(POC_ANDLW, newpCodeOpLit(bytelit & 0x0ff));
3846 if (rIfx.condition) emitSKPZ;
3849 if(bytelit != 0x0FFL)
3851 pic14_emitcode("anl","a,%s",
3852 aopGet(AOP(right),offset,FALSE,TRUE));
3854 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
3857 emitpcode(POC_GOTO, popGetLabel(rIfx.lbl->key));
3863 // bit = left & literal
3865 pic14_emitcode("clr","c");
3866 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
3868 // if(left & literal)
3871 jmpTrueOrFalse(ifx, tlbl);
3875 pic14_outBitC(result);
3879 /* if left is same as result */
3880 if(pic14_sameRegs(AOP(result),AOP(left))){
3882 for(;size--; offset++,lit>>=8) {
3883 if(AOP_TYPE(right) == AOP_LIT){
3884 switch(lit & 0xff) {
3886 /* and'ing with 0 has clears the result */
3887 emitpcode(POC_CLRF,popGet(AOP(result),offset));
3890 /* and'ing with 0xff is a nop when the result and left are the same */
3895 int p = my_powof2( (~lit) & 0xff );
3897 /* only one bit is set in the literal, so use a bcf instruction */
3898 emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
3901 if(know_W != (int)(lit&0xff))
3902 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
3904 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
3909 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
3910 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
3915 // left & result in different registers
3916 if(AOP_TYPE(result) == AOP_CRY){
3918 // if(size), result in bit
3919 // if(!size && ifx), conditional oper: if(left & right)
3920 symbol *tlbl = newiTempLabel(NULL);
3921 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
3923 pic14_emitcode("setb","c");
3925 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3926 pic14_emitcode("anl","a,%s",
3927 aopGet(AOP(left),offset,FALSE,FALSE));
3928 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
3933 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
3934 pic14_outBitC(result);
3936 jmpTrueOrFalse(ifx, tlbl);
3938 for(;(size--);offset++) {
3940 // result = left & right
3941 if(AOP_TYPE(right) == AOP_LIT){
3942 int t = (lit >> (offset*8)) & 0x0FFL;
3945 emitpcode(POC_CLRF,popGet(AOP(result),offset));
3948 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
3949 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
3952 emitpcode(POC_MOVLW, popGetLit(t));
3953 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
3954 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
3959 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
3960 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
3961 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
3967 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3968 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3969 freeAsmop(result,NULL,ic,TRUE);
3972 /*-----------------------------------------------------------------*/
3973 /* genOr - code for or */
3974 /*-----------------------------------------------------------------*/
3975 static void genOr (iCode *ic, iCode *ifx)
3977 operand *left, *right, *result;
3979 unsigned long lit = 0L;
3982 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3984 aopOp((left = IC_LEFT(ic)),ic,FALSE);
3985 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
3986 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3988 DEBUGpic14_AopType(__LINE__,left,right,result);
3990 /* if left is a literal & right is not then exchange them */
3991 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3992 AOP_NEEDSACC(left)) {
3993 operand *tmp = right ;
3998 /* if result = right then exchange them */
3999 if(pic14_sameRegs(AOP(result),AOP(right))){
4000 operand *tmp = right ;
4005 /* if right is bit then exchange them */
4006 if (AOP_TYPE(right) == AOP_CRY &&
4007 AOP_TYPE(left) != AOP_CRY){
4008 operand *tmp = right ;
4013 DEBUGpic14_AopType(__LINE__,left,right,result);
4015 if(AOP_TYPE(right) == AOP_LIT)
4016 lit = ulFromVal (AOP(right)->aopu.aop_lit);
4018 size = AOP_SIZE(result);
4022 if (AOP_TYPE(left) == AOP_CRY){
4023 if(AOP_TYPE(right) == AOP_LIT){
4024 // c = bit & literal;
4026 // lit != 0 => result = 1
4027 if(AOP_TYPE(result) == AOP_CRY){
4029 emitpcode(POC_BSF, popGet(AOP(result),0));
4030 //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
4031 // AOP(result)->aopu.aop_dir,
4032 // AOP(result)->aopu.aop_dir);
4034 continueIfTrue(ifx);
4038 // lit == 0 => result = left
4039 if(size && pic14_sameRegs(AOP(result),AOP(left)))
4041 pic14_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
4044 if (AOP_TYPE(right) == AOP_CRY){
4045 if(pic14_sameRegs(AOP(result),AOP(left))){
4047 emitpcode(POC_BCF, popGet(AOP(result),0));
4048 emitpcode(POC_BTFSC, popGet(AOP(right),0));
4049 emitpcode(POC_BSF, popGet(AOP(result),0));
4051 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
4052 AOP(result)->aopu.aop_dir,
4053 AOP(result)->aopu.aop_dir);
4054 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
4055 AOP(right)->aopu.aop_dir,
4056 AOP(right)->aopu.aop_dir);
4057 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
4058 AOP(result)->aopu.aop_dir,
4059 AOP(result)->aopu.aop_dir);
4061 emitpcode(POC_BCF, popGet(AOP(result),0));
4062 emitpcode(POC_BTFSS, popGet(AOP(right),0));
4063 emitpcode(POC_BTFSC, popGet(AOP(left),0));
4064 emitpcode(POC_BSF, popGet(AOP(result),0));
4068 symbol *tlbl = newiTempLabel(NULL);
4069 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4072 emitpcode(POC_BCF, popGet(AOP(result),0));
4074 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4075 pic14_emitcode(";XXX setb","c");
4076 pic14_emitcode(";XXX jb","%s,%05d_DS_",
4077 AOP(left)->aopu.aop_dir,tlbl->key+100);
4078 pic14_toBoolean(right);
4079 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
4080 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4081 jmpTrueOrFalse(ifx, tlbl);
4085 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4092 pic14_outBitC(result);
4094 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4095 genIfxJump(ifx, "c");
4099 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4100 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4101 if((AOP_TYPE(right) == AOP_LIT) &&
4102 (AOP_TYPE(result) == AOP_CRY) &&
4103 (AOP_TYPE(left) != AOP_CRY)){
4105 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4108 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
4110 continueIfTrue(ifx);
4113 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4114 // lit = 0, result = boolean(left)
4116 pic14_emitcode(";XXX setb","c");
4117 pic14_toBoolean(right);
4119 symbol *tlbl = newiTempLabel(NULL);
4120 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
4122 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4124 genIfxJump (ifx,"a");
4128 pic14_outBitC(result);
4132 /* if left is same as result */
4133 if(pic14_sameRegs(AOP(result),AOP(left))){
4135 for(;size--; offset++,lit>>=8) {
4136 if(AOP_TYPE(right) == AOP_LIT){
4137 if((lit & 0xff) == 0)
4138 /* or'ing with 0 has no effect */
4141 int p = my_powof2(lit & 0xff);
4143 /* only one bit is set in the literal, so use a bsf instruction */
4145 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
4147 if(know_W != (int)(lit & 0xff))
4148 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
4149 know_W = lit & 0xff;
4150 emitpcode(POC_IORWF, popGet(AOP(left),offset));
4155 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
4156 emitpcode(POC_IORWF, popGet(AOP(left),offset));
4160 // left & result in different registers
4161 if(AOP_TYPE(result) == AOP_CRY){
4163 // if(size), result in bit
4164 // if(!size && ifx), conditional oper: if(left | right)
4165 symbol *tlbl = newiTempLabel(NULL);
4166 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4167 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4171 pic14_emitcode(";XXX setb","c");
4173 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4174 pic14_emitcode(";XXX orl","a,%s",
4175 aopGet(AOP(left),offset,FALSE,FALSE));
4176 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
4181 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4182 pic14_outBitC(result);
4184 jmpTrueOrFalse(ifx, tlbl);
4185 } else for(;(size--);offset++){
4187 // result = left | right
4188 if(AOP_TYPE(right) == AOP_LIT){
4189 int t = (lit >> (offset*8)) & 0x0FFL;
4192 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
4193 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
4197 emitpcode(POC_MOVLW, popGetLit(t));
4198 emitpcode(POC_IORFW, popGet(AOP(left),offset));
4199 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
4204 // faster than result <- left, anl result,right
4205 // and better if result is SFR
4206 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
4207 emitpcode(POC_IORFW,popGet(AOP(left),offset));
4208 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
4213 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4214 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4215 freeAsmop(result,NULL,ic,TRUE);
4218 /*-----------------------------------------------------------------*/
4219 /* genXor - code for xclusive or */
4220 /*-----------------------------------------------------------------*/
4221 static void genXor (iCode *ic, iCode *ifx)
4223 operand *left, *right, *result;
4225 unsigned long lit = 0L;
4228 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4230 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4231 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4232 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4234 /* if left is a literal & right is not ||
4235 if left needs acc & right does not */
4236 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4237 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4238 operand *tmp = right ;
4243 /* if result = right then exchange them */
4244 if(pic14_sameRegs(AOP(result),AOP(right))){
4245 operand *tmp = right ;
4250 /* if right is bit then exchange them */
4251 if (AOP_TYPE(right) == AOP_CRY &&
4252 AOP_TYPE(left) != AOP_CRY){
4253 operand *tmp = right ;
4257 if(AOP_TYPE(right) == AOP_LIT)
4258 lit = ulFromVal (AOP(right)->aopu.aop_lit);
4260 size = AOP_SIZE(result);
4264 if (AOP_TYPE(left) == AOP_CRY){
4265 if(AOP_TYPE(right) == AOP_LIT){
4266 // c = bit & literal;
4268 // lit>>1 != 0 => result = 1
4269 if(AOP_TYPE(result) == AOP_CRY){
4271 {emitpcode(POC_BSF, popGet(AOP(result),offset));
4272 pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
4274 continueIfTrue(ifx);
4277 pic14_emitcode("setb","c");
4281 // lit == 0, result = left
4282 if(size && pic14_sameRegs(AOP(result),AOP(left)))
4284 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4286 // lit == 1, result = not(left)
4287 if(size && pic14_sameRegs(AOP(result),AOP(left))){
4288 emitpcode(POC_MOVLW, popGet(AOP(result),offset));
4289 emitpcode(POC_XORWF, popGet(AOP(result),offset));
4290 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4293 assert ( !"incomplete genXor" );
4294 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4295 pic14_emitcode("cpl","c");
4302 symbol *tlbl = newiTempLabel(NULL);
4303 if (AOP_TYPE(right) == AOP_CRY){
4305 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4308 int sizer = AOP_SIZE(right);
4310 // if val>>1 != 0, result = 1
4311 pic14_emitcode("setb","c");
4313 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
4315 // test the msb of the lsb
4316 pic14_emitcode("anl","a,#0xfe");
4317 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
4321 pic14_emitcode("rrc","a");
4323 pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4324 pic14_emitcode("cpl","c");
4325 pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
4330 pic14_outBitC(result);
4332 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4333 genIfxJump(ifx, "c");
4337 if(pic14_sameRegs(AOP(result),AOP(left))){
4338 /* if left is same as result */
4339 for(;size--; offset++) {
4340 if(AOP_TYPE(right) == AOP_LIT){
4341 int t = (lit >> (offset*8)) & 0x0FFL;
4345 emitpcode(POC_MOVLW, popGetLit(t));
4346 emitpcode(POC_XORWF,popGet(AOP(left),offset));
4349 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
4350 emitpcode(POC_XORWF,popGet(AOP(left),offset));
4354 // left & result in different registers
4355 if(AOP_TYPE(result) == AOP_CRY){
4357 // if(size), result in bit
4358 // if(!size && ifx), conditional oper: if(left ^ right)
4359 symbol *tlbl = newiTempLabel(NULL);
4360 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4362 pic14_emitcode("setb","c");
4364 if((AOP_TYPE(right) == AOP_LIT) &&
4365 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4366 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4368 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4369 pic14_emitcode("xrl","a,%s",
4370 aopGet(AOP(left),offset,FALSE,FALSE));
4372 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
4377 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4378 pic14_outBitC(result);
4380 jmpTrueOrFalse(ifx, tlbl);
4381 } else for(;(size--);offset++){
4383 // result = left & right
4384 if(AOP_TYPE(right) == AOP_LIT){
4385 int t = (lit >> (offset*8)) & 0x0FFL;
4388 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4389 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
4392 emitpcode(POC_COMFW,popGet(AOP(left),offset));
4393 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
4396 emitpcode(POC_MOVLW, popGetLit(t));
4397 emitpcode(POC_XORFW,popGet(AOP(left),offset));
4398 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
4403 // faster than result <- left, anl result,right
4404 // and better if result is SFR
4405 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
4406 emitpcode(POC_XORFW,popGet(AOP(left),offset));
4407 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
4412 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4413 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4414 freeAsmop(result,NULL,ic,TRUE);
4417 /*-----------------------------------------------------------------*/
4418 /* genInline - write the inline code out */
4419 /*-----------------------------------------------------------------*/
4420 static void genInline (iCode *ic)
4422 char *buffer, *bp, *bp1;
4423 bool inComment = FALSE;
4426 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4428 _G.inLine += (!options.asmpeep);
4430 buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
4445 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
4450 /* Add \n for labels, not dirs such as c:\mydir */
4451 if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
4456 /* print label, use this special format with NULL directive
4457 * to denote that the argument should not be indented with tab */
4458 addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
4466 if ((bp1 != bp) && *bp1)
4467 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
4471 _G.inLine -= (!options.asmpeep);
4474 /*-----------------------------------------------------------------*/
4475 /* genRRC - rotate right with carry */
4476 /*-----------------------------------------------------------------*/
4477 static void genRRC (iCode *ic)
4479 operand *left , *result ;
4480 int size, offset = 0, same;
4483 /* rotate right with carry */
4485 result=IC_RESULT(ic);
4486 aopOp (left,ic,FALSE);
4487 aopOp (result,ic,FALSE);
4489 DEBUGpic14_AopType(__LINE__,left,NULL,result);
4491 same = pic14_sameRegs(AOP(result),AOP(left));
4493 size = AOP_SIZE(result);
4495 /* get the lsb and put it into the carry */
4496 emitpcode(POC_RRFW, popGet(AOP(left),size-1));
4503 emitpcode(POC_RRF, popGet(AOP(left),offset));
4505 emitpcode(POC_RRFW, popGet(AOP(left),offset));
4506 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
4512 freeAsmop(left,NULL,ic,TRUE);
4513 freeAsmop(result,NULL,ic,TRUE);
4516 /*-----------------------------------------------------------------*/
4517 /* genRLC - generate code for rotate left with carry */
4518 /*-----------------------------------------------------------------*/
4519 static void genRLC (iCode *ic)
4521 operand *left , *result ;
4522 int size, offset = 0;
4526 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4527 /* rotate right with carry */
4529 result=IC_RESULT(ic);
4530 aopOp (left,ic,FALSE);
4531 aopOp (result,ic,FALSE);
4533 DEBUGpic14_AopType(__LINE__,left,NULL,result);
4535 same = pic14_sameRegs(AOP(result),AOP(left));
4537 /* move it to the result */
4538 size = AOP_SIZE(result);
4540 /* get the msb and put it into the carry */
4541 emitpcode(POC_RLFW, popGet(AOP(left),size-1));
4548 emitpcode(POC_RLF, popGet(AOP(left),offset));
4550 emitpcode(POC_RLFW, popGet(AOP(left),offset));
4551 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
4558 freeAsmop(left,NULL,ic,TRUE);
4559 freeAsmop(result,NULL,ic,TRUE);
4562 /*-----------------------------------------------------------------*/
4563 /* genGetHbit - generates code get highest order bit */
4564 /*-----------------------------------------------------------------*/
4565 static void genGetHbit (iCode *ic)
4567 operand *left, *result;
4569 result=IC_RESULT(ic);
4570 aopOp (left,ic,FALSE);
4571 aopOp (result,ic,FALSE);
4574 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4575 /* get the highest order byte into a */
4576 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
4577 if(AOP_TYPE(result) == AOP_CRY){
4578 pic14_emitcode("rlc","a");
4579 pic14_outBitC(result);
4582 pic14_emitcode("rl","a");
4583 pic14_emitcode("anl","a,#0x01");
4584 pic14_outAcc(result);
4588 freeAsmop(left,NULL,ic,TRUE);
4589 freeAsmop(result,NULL,ic,TRUE);
4592 /*-----------------------------------------------------------------*/
4593 /* AccLsh - shift left accumulator by known count */
4594 /* MARK: pic14 always rotates through CARRY! */
4595 /*-----------------------------------------------------------------*/
4596 static void AccLsh (pCodeOp *pcop,int shCount)
4599 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4600 shCount &= 0x0007; // shCount : 0..7
4607 emitpcode(POC_RLF,pcop);
4611 emitpcode(POC_RLF,pcop);
4612 emitpcode(POC_RLF,pcop);
4615 emitpcode(POC_RLF,pcop);
4616 emitpcode(POC_RLF,pcop);
4617 emitpcode(POC_RLF,pcop);
4620 emitpcode(POC_SWAPF,pcop);
4623 emitpcode(POC_SWAPF,pcop);
4624 emitpcode(POC_RLF,pcop);
4627 emitpcode(POC_SWAPF,pcop);
4628 emitpcode(POC_RLF,pcop);
4629 emitpcode(POC_RLF,pcop);
4632 emitpcode(POC_RRFW,pcop);
4633 emitpcode(POC_RRF,pcop);
4636 /* clear invalid bits */
4637 emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
4638 emitpcode(POC_ANDWF, pcop);
4641 /*-----------------------------------------------------------------*/
4642 /* AccRsh - shift right accumulator by known count */
4643 /* MARK: pic14 always rotates through CARRY! */
4644 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
4645 /* 1: mask out invalid bits (zero-extend) */
4646 /* 2: sign-extend result (pretty slow) */
4647 /*-----------------------------------------------------------------*/
4648 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
4651 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4652 shCount &= 0x0007; // shCount : 0..7
4658 /* load sign if needed */
4659 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
4660 else if (mask_mode == 1) emitCLRC;
4661 emitpcode(POC_RRF,pcop);
4665 /* load sign if needed */
4666 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
4667 emitpcode(POC_RRF,pcop);
4668 /* load sign if needed */
4669 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
4670 emitpcode(POC_RRF,pcop);
4671 if (mask_mode == 2) return;
4674 /* load sign if needed */
4675 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
4676 emitpcode(POC_RRF,pcop);
4677 /* load sign if needed */
4678 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
4679 emitpcode(POC_RRF,pcop);
4680 /* load sign if needed */
4681 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
4682 emitpcode(POC_RRF,pcop);
4683 if (mask_mode == 2) return;
4686 emitpcode(POC_SWAPF,pcop);
4689 emitpcode(POC_SWAPF,pcop);
4690 emitpcode(POC_RRF,pcop);
4693 emitpcode(POC_SWAPF,pcop);
4694 emitpcode(POC_RRF,pcop);
4695 emitpcode(POC_RRF,pcop);
4701 emitpcode(POC_RLFW,pcop);
4702 emitpcode(POC_CLRF,pcop);
4704 emitpcode(POC_COMF,pcop);
4707 emitpcode(POC_RLFW,pcop);
4708 emitpcode(POC_RLF,pcop);
4715 /* leave invalid bits undefined */
4719 /* clear invalid bits -- zero-extend */
4720 emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
4721 emitpcode(POC_ANDWF, pcop);
4723 if (mask_mode == 2) {
4725 emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
4726 emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
4727 emitpcode(POC_IORWF, pcop);
4731 /*-----------------------------------------------------------------*/
4732 /* movLeft2Result - move byte from left to result */
4733 /*-----------------------------------------------------------------*/
4734 static void movLeft2Result (operand *left, int offl,
4735 operand *result, int offr)
4738 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4739 if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
4740 aopGet(AOP(left),offl,FALSE,FALSE);
4742 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
4743 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
4747 /*-----------------------------------------------------------------*/
4748 /* shiftLeft_Left2ResultLit - shift left by known count */
4749 /*-----------------------------------------------------------------*/
4751 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
4753 int size, same, offr, i;
4755 size = AOP_SIZE(left);
4756 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
4758 same = pic14_sameRegs (AOP(left), AOP(result));
4761 shCount = shCount & 0x07;
4767 case 0: /* takes 0 or 2N cycles (for offr==0) */
4768 if (!same || offr) {
4769 for (i=size-1; i >= 0; i--)
4770 movLeft2Result (left, i, result, offr + i);
4774 case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
4776 shiftLeft_Left2ResultLit (left, result, 8 * offr);
4777 shiftLeft_Left2ResultLit (result, result, shCount);
4778 return; /* prevent clearing result again */
4781 for (i=0; i < size; i++) {
4782 if (same && !offr) {
4783 emitpcode (POC_RLF, popGet (AOP(left), i));
4785 emitpcode (POC_RLFW, popGet (AOP(left), i));
4786 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
4792 case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
4793 /* works in-place/with offr as well */
4794 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
4795 emitpcode (POC_ANDLW, popGetLit (0xF0));
4796 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
4798 for (i = size - 2; i >= 0; i--)
4800 emitpcode (POC_SWAPFW, popGet (AOP(left), i));
4801 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
4802 emitpcode (POC_ANDLW, popGetLit (0x0F));
4803 emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
4804 emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
4808 case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
4809 /* works in-place/with offr as well */
4810 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
4811 for (i = size-2; i >= 0; i--) {
4812 emitpcode (POC_RRFW, popGet (AOP(left), i));
4813 emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
4815 emitpcode (POC_CLRF, popGet (AOP(result), offr));
4816 emitpcode (POC_RRF, popGet (AOP(result), offr));
4820 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
4821 shiftLeft_Left2ResultLit (result, result, 1);
4822 return; /* prevent clearing result again */
4828 emitpcode (POC_CLRF, popGet (AOP(result), offr));
4832 /*-----------------------------------------------------------------*/
4833 /* shiftRight_Left2ResultLit - shift right by known count */
4834 /*-----------------------------------------------------------------*/
4836 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
4838 int size, same, offr, i;
4840 size = AOP_SIZE(left);
4841 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
4843 same = pic14_sameRegs (AOP(left), AOP(result));
4846 shCount = shCount & 0x07;
4854 case 0: /* takes 0 or 2N cycles (for offr==0) */
4855 if (!same || offr) {
4856 for (i=0; i < size; i++)
4857 movLeft2Result (left, i + offr, result, i);
4861 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
4862 emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
4864 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
4865 shiftRight_Left2ResultLit (result, result, shCount, sign);
4866 return; /* prevent sign-extending result again */
4870 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
4873 for (i = size-1; i >= 0; i--) {
4874 if (same && !offr) {
4875 emitpcode (POC_RRF, popGet (AOP(left), i));
4877 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
4878 emitpcode (POC_MOVWF, popGet (AOP(result), i));
4884 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
4885 /* works in-place/with offr as well */
4886 emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
4887 emitpcode (POC_ANDLW, popGetLit (0x0F));
4888 emitpcode (POC_MOVWF, popGet(AOP(result), 0));
4890 for (i = 1; i < size; i++)
4892 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
4893 emitpcode (POC_MOVWF, popGet (AOP(result), i));
4894 emitpcode (POC_ANDLW, popGetLit (0xF0));
4895 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
4896 emitpcode (POC_XORWF, popGet (AOP(result), i));
4901 emitpcode (POC_MOVLW, popGetLit (0xF0));
4902 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
4903 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
4907 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
4908 /* works in-place/with offr as well */
4909 emitpcode (POC_RLFW, popGet (AOP(left), offr));
4910 for (i = 0; i < size-1; i++) {
4911 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
4912 emitpcode (POC_MOVWF, popGet (AOP(result), i));
4914 emitpcode (POC_CLRF, popGet (AOP(result), size-1));
4916 emitpcode (POC_RLF, popGet (AOP(result), size-1));
4919 emitpcode (POC_DECF, popGet (AOP(result), size-1));
4924 shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
4925 shiftRight_Left2ResultLit (result, result, 1, sign);
4926 return; /* prevent sign extending result again */
4931 addSign (result, size, sign);
4934 /*-----------------------------------------------------------------*
4935 * genMultiAsm - repeat assembly instruction for size of register.
4936 * if endian == 1, then the high byte (i.e base address + size of
4937 * register) is used first else the low byte is used first;
4938 *-----------------------------------------------------------------*/
4939 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
4945 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4958 emitpcode(poc, popGet(AOP(reg),offset));
4964 /*-----------------------------------------------------------------*/
4965 /* loadSignToC - load the operand's sign bit into CARRY */
4966 /*-----------------------------------------------------------------*/
4968 static void loadSignToC (operand *op)
4971 assert (op && AOP(op) && AOP_SIZE(op));
4974 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
4978 /*-----------------------------------------------------------------*/
4979 /* genRightShift - generate code for right shifting */
4980 /*-----------------------------------------------------------------*/
4981 static void genGenericShift (iCode *ic, int shiftRight)
4983 operand *right, *left, *result;
4986 symbol *tlbl, *tlbl1, *inverselbl;
4989 /* if signed then we do it the hard way preserve the
4990 sign bit moving it inwards */
4991 retype = getSpec(operandType(IC_RESULT(ic)));
4992 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4994 /* signed & unsigned types are treated the same : i.e. the
4995 signed is NOT propagated inwards : quoting from the
4996 ANSI - standard : "for E1 >> E2, is equivalent to division
4997 by 2**E2 if unsigned or if it has a non-negative value,
4998 otherwise the result is implementation defined ", MY definition
4999 is that the sign does not get propagated */
5001 right = IC_RIGHT(ic);
5003 result = IC_RESULT(ic);
5005 aopOp(right,ic,FALSE);
5006 aopOp(left,ic,FALSE);
5007 aopOp(result,ic,FALSE);
5009 /* if the shift count is known then do it
5010 as efficiently as possible */
5011 if (AOP_TYPE(right) == AOP_LIT) {
5012 int lit = (int) ulFromVal (AOP(right)->aopu.aop_lit);
5016 shiftRight = !shiftRight;
5020 shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
5022 shiftLeft_Left2ResultLit (left, result, lit);
5023 //genRightShiftLiteral (left,right,result,ic, 0);
5027 /* shift count is unknown then we have to form
5028 a loop get the loop count in B : Note: we take
5029 only the lower order byte since shifting
5030 more that 32 bits make no sense anyway, ( the
5031 largest size of an object can be only 32 bits ) */
5033 /* we must not overwrite the shift counter */
5034 assert (!pic14_sameRegs(AOP(right),AOP(result)));
5036 /* now move the left to the result if they are not the
5038 if (!pic14_sameRegs(AOP(left),AOP(result)))
5040 size = min(AOP_SIZE(result), AOP_SIZE(left));
5042 mov2w(AOP(left), size);
5043 movwf(AOP(result), size);
5045 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
5048 tlbl = newiTempLabel(NULL);
5049 tlbl1= newiTempLabel(NULL);
5051 size = AOP_SIZE(result);
5053 mov2w(AOP(right),0);
5054 if (!SPEC_USIGN(operandType(right)))
5056 inverselbl = newiTempLabel(NULL);
5057 /* signed shift count -- invert shift direction for c<0 */
5058 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
5059 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
5061 emitpcode(POC_SUBLW, popGetLit(0)); /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
5062 /* check for `a = b >> c' with `-c == 0' */
5064 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
5065 emitpLabel(tlbl->key);
5066 /* propagate the sign bit inwards for SIGNED result */
5067 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
5068 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
5069 emitpcode(POC_ADDLW, popGetLit(1)); /* clears CARRY (unless W==0 afterwards) */
5071 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
5073 if (!SPEC_USIGN(operandType(right)))
5075 symbol *inv_loop = newiTempLabel(NULL);
5077 shiftRight = !shiftRight; /* invert shift direction */
5079 /* we came here from the code above -- we are done */
5080 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
5082 /* emit code for shifting N<0 steps, count is already in W */
5083 emitpLabel(inverselbl->key);
5084 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
5085 emitpLabel(inv_loop->key);
5086 /* propagate the sign bit inwards for SIGNED result */
5087 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
5088 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
5089 emitpcode(POC_ADDLW, popGetLit(1));
5091 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
5094 emitpLabel(tlbl1->key);
5096 freeAsmop(left,NULL,ic,TRUE);
5097 freeAsmop (right,NULL,ic,TRUE);
5098 freeAsmop(result,NULL,ic,TRUE);
5101 static void genRightShift (iCode *ic)
5103 genGenericShift(ic, 1);
5106 static void genLeftShift (iCode *ic)
5108 genGenericShift(ic, 0);
5111 /*-----------------------------------------------------------------*/
5112 /* SetIrp - Set IRP bit */
5113 /*-----------------------------------------------------------------*/
5114 static void SetIrp(operand *result)
5117 if (AOP_TYPE(result) == AOP_LIT) {
5118 unsigned lit = (unsigned) double2ul (operandLitValue(result));
5124 if ((AOP_TYPE(result) == AOP_PCODE)
5125 && (AOP(result)->aopu.pcop->type == PO_LITERAL))
5127 int addrs = PCOL(AOP(result)->aopu.pcop)->lit;
5133 emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
5134 if(AOP_SIZE(result) > 1) {
5135 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
5143 setup_fsr (operand *ptr)
5146 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
5148 /* also setup-up IRP */
5152 /*-----------------------------------------------------------------*/
5153 /* emitPtrByteGet - emits code to get a byte into WREG from an */
5154 /* arbitrary pointer (__code, __data, generic) */
5155 /*-----------------------------------------------------------------*/
5157 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
5164 if (!alreadyAddressed) setup_fsr (src);
5165 emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
5169 assert( AOP_SIZE(src) == 2 );
5171 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
5173 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
5174 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
5175 call_libraryfunc ("__gptrget1");
5179 assert( AOP_SIZE(src) == 3 );
5181 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
5183 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
5185 call_libraryfunc ("__gptrget1");
5189 assert( !"unhandled pointer type" );
5194 /*-----------------------------------------------------------------*/
5195 /* emitPtrByteSet - emits code to set a byte from src through a */
5196 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR). */
5197 /*-----------------------------------------------------------------*/
5199 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
5206 if (!alreadyAddressed) setup_fsr (dst);
5207 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
5211 assert( !"trying to assign to __code pointer" );
5215 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
5217 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
5219 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
5221 call_libraryfunc ("__gptrput1");
5225 assert( !"unhandled pointer type" );
5230 /*-----------------------------------------------------------------*/
5231 /* genUnpackBits - generates code for unpacking bits */
5232 /*-----------------------------------------------------------------*/
5233 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
5235 int rsize; /* result size */
5236 sym_link *etype; /* bitfield type information */
5237 int blen; /* bitfield length */
5238 int bstr; /* bitfield starting bit within byte */
5241 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5242 etype = getSpec(operandType(result));
5243 rsize = getSize (operandType (result));
5244 blen = SPEC_BLEN (etype);
5245 bstr = SPEC_BSTR (etype);
5247 /* single bit field case */
5249 if (ifx) { /* that is for an if statement */
5252 resolveIfx(&rIfx,ifx);
5253 if (ptype == -1) /* direct */
5254 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
5256 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
5257 emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
5258 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5262 assert (!pic14_sameRegs (AOP(result), AOP(left)));
5263 for (i=0; i < AOP_SIZE(result); i++)
5264 emitpcode (POC_CLRF, popGet (AOP(result), i));
5269 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
5270 /* adjust result below */
5277 emitPtrByteGet (left, ptype, FALSE);
5278 emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
5280 /* adjust result below */
5284 assert( !"unhandled pointer type" );
5287 /* move sign-/zero extended bit to result */
5288 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
5289 emitpcode (POC_INCF, popGet (AOP(result), 0));
5291 emitpcode (POC_DECF, popGet (AOP(result), 0));
5293 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
5297 else if (blen <= 8 && ((blen + bstr) <= 8))
5302 for (i=0; i < AOP_SIZE(result); i++)
5303 emitpcode (POC_CLRF, popGet (AOP(result), i));
5308 mov2w(AOP(left), 0);
5315 emitPtrByteGet (left, ptype, FALSE);
5319 assert( !"unhandled pointer type" );
5323 emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
5324 movwf(AOP(result), 0);
5325 AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
5327 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
5329 /* signed bitfield */
5330 assert (bstr + blen > 0);
5331 emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
5332 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
5333 emitpcode(POC_IORWF, popGet(AOP(result),0));
5335 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
5339 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
5343 /*-----------------------------------------------------------------*/
5344 /* genDataPointerGet - generates code when ptr offset is known */
5345 /*-----------------------------------------------------------------*/
5346 static void genDataPointerGet (operand *left,
5350 int size , offset = 0;
5353 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5356 /* optimization - most of the time, left and result are the same
5357 * address, but different types. for the pic code, we could omit
5360 aopOp(result,ic,TRUE);
5362 if (pic14_sameRegs (AOP(left), AOP(result)))
5365 DEBUGpic14_AopType(__LINE__,left,NULL,result);
5367 //emitpcode(POC_MOVFW, popGet(AOP(left),0));
5369 size = AOP_SIZE(result);
5370 if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
5374 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
5375 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5379 freeAsmop(left,NULL,ic,TRUE);
5380 freeAsmop(result,NULL,ic,TRUE);
5384 /*-----------------------------------------------------------------*/
5385 /* genNearPointerGet - pic14_emitcode for near pointer fetch */
5386 /*-----------------------------------------------------------------*/
5387 static void genNearPointerGet (operand *left,
5392 sym_link *ltype = operandType(left);
5393 sym_link *rtype = operandType(result);
5394 sym_link *retype= getSpec(rtype); /* bitfield type information */
5398 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5401 aopOp(left,ic,FALSE);
5403 /* if left is rematerialisable and
5404 result is not bit variable type and
5405 the left is pointer to data space i.e
5406 lower 128 bytes of space */
5407 if (AOP_TYPE(left) == AOP_PCODE && //AOP_TYPE(left) == AOP_IMMD &&
5408 !IS_BITVAR(retype) &&
5409 PIC_IS_DATA_PTR(ltype)) {
5410 genDataPointerGet (left,result,ic);
5414 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5415 aopOp (result,ic,FALSE);
5417 /* Check if can access directly instead of via a pointer */
5418 if ((AOP_TYPE(left) == AOP_PCODE)
5419 && (AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
5420 && (AOP_SIZE(result) == 1))
5425 if (IS_BITFIELD(getSpec(operandType(result))))
5427 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
5431 /* If the pointer value is not in a the FSR then need to put it in */
5432 /* Must set/reset IRP bit for use with FSR. */
5437 /* if bitfield then unpack the bits */
5439 /* we have can just get the values */
5440 int size = AOP_SIZE(result);
5443 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5447 emitpcode(POC_MOVWF,popGet(AOP(left),0));
5449 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
5450 if (AOP_TYPE(result) == AOP_LIT) {
5451 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
5453 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5455 if (size && !direct)
5456 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
5461 /* now some housekeeping stuff */
5463 /* we had to allocate for this iCode */
5464 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5465 freeAsmop(NULL,aop,ic,TRUE);
5467 /* we did not allocate which means left
5468 already in a pointer register, then
5469 if size > 0 && this could be used again
5470 we have to point it back to where it
5472 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5473 if (AOP_SIZE(result) > 1 &&
5474 !OP_SYMBOL(left)->remat &&
5475 ( OP_SYMBOL(left)->liveTo > ic->seq ||
5477 int size = AOP_SIZE(result) - 1;
5479 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
5485 freeAsmop(left,NULL,ic,TRUE);
5486 freeAsmop(result,NULL,ic,TRUE);
5490 /*-----------------------------------------------------------------*/
5491 /* genGenPointerGet - gget value from generic pointer space */
5492 /*-----------------------------------------------------------------*/
5493 static void genGenPointerGet (operand *left,
5494 operand *result, iCode *ic)
5497 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5498 aopOp(left,ic,FALSE);
5499 aopOp(result,ic,FALSE);
5502 DEBUGpic14_AopType(__LINE__,left,NULL,result);
5504 if (IS_BITFIELD(getSpec(operandType(result))))
5506 genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
5511 /* emit call to __gptrget */
5512 char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
5513 int size = AOP_SIZE(result);
5516 assert (size > 0 && size <= 4);
5518 /* pass arguments */
5519 assert (AOP_SIZE(left) == 3);
5520 mov2w(AOP(left), 0);
5521 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
5522 mov2w(AOP(left), 1);
5523 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
5524 mov2w(AOP(left), 2);
5525 call_libraryfunc (func[size]);
5528 movwf (AOP(result), --size);
5530 emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
5531 movwf (AOP(result), size);
5535 freeAsmop(left,NULL,ic,TRUE);
5536 freeAsmop(result,NULL,ic,TRUE);
5540 /*-----------------------------------------------------------------*/
5541 /* genConstPointerGet - get value from const generic pointer space */
5542 /*-----------------------------------------------------------------*/
5543 static void genConstPointerGet (operand *left,
5544 operand *result, iCode *ic)
5546 //sym_link *retype = getSpec(operandType(result));
5548 symbol *albl, *blbl;//, *clbl;
5555 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5556 aopOp(left,ic,FALSE);
5557 aopOp(result,ic,FALSE);
5559 size = AOP_SIZE(result);
5561 DEBUGpic14_AopType(__LINE__,left,NULL,result);
5563 DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
5565 lit = op_isLitLike (left);
5566 poc = lit ? POC_MOVLW : POC_MOVFW;
5568 if (IS_BITFIELD(getSpec(operandType(result))))
5570 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
5575 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
5576 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
5577 assert (size > 0 && size <= 4);
5580 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
5582 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
5583 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
5584 call_libraryfunc (func[size]);
5586 movwf(AOP(result),size-1);
5587 for (i = 1; i < size; i++)
5589 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
5590 movwf(AOP(result),size - 1 - i);
5595 freeAsmop(left,NULL,ic,TRUE);
5596 freeAsmop(result,NULL,ic,TRUE);
5599 /*-----------------------------------------------------------------*/
5600 /* genPointerGet - generate code for pointer get */
5601 /*-----------------------------------------------------------------*/
5602 static void genPointerGet (iCode *ic)
5604 operand *left, *result ;
5605 sym_link *type, *etype;
5609 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5612 result = IC_RESULT(ic) ;
5614 /* depending on the type of pointer we need to
5615 move it to the correct pointer register */
5616 type = operandType(left);
5617 etype = getSpec(type);
5619 if (IS_PTR_CONST(type))
5620 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
5622 /* if left is of type of pointer then it is simple */
5623 if (IS_PTR(type) && !IS_FUNC(type->next))
5624 p_type = DCL_TYPE(type);
5626 /* we have to go by the storage class */
5627 p_type = PTR_TYPE(SPEC_OCLS(etype));
5629 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
5631 if (SPEC_OCLS(etype)->codesp ) {
5632 DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
5633 //p_type = CPOINTER ;
5636 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
5637 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
5638 /*p_type = FPOINTER ;*/
5640 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
5641 DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
5642 /* p_type = PPOINTER; */
5644 if (SPEC_OCLS(etype) == idata )
5645 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
5646 /* p_type = IPOINTER; */
5648 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
5649 /* p_type = POINTER ; */
5652 /* now that we have the pointer type we assign
5653 the pointer values */
5659 genNearPointerGet (left,result,ic);
5663 genPagedPointerGet(left,result,ic);
5667 genFarPointerGet (left,result,ic);
5671 genConstPointerGet (left,result,ic);
5675 genGenPointerGet (left,result,ic);
5678 assert ( !"unhandled pointer type" );
5684 /*-----------------------------------------------------------------*/
5685 /* genPackBits - generates code for packed bit storage */
5686 /*-----------------------------------------------------------------*/
5687 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
5689 int blen; /* bitfield length */
5690 int bstr; /* bitfield starting bit within byte */
5691 int litval; /* source literal value (if AOP_LIT) */
5692 unsigned char mask; /* bitmask within current byte */
5695 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5697 blen = SPEC_BLEN (etype);
5698 bstr = SPEC_BSTR (etype);
5700 /* If the bitfield length is less than a byte and does not cross byte boundaries */
5701 if ((blen <= 8) && ((bstr + blen) <= 8))
5703 mask = ((unsigned char) (0xFF << (blen + bstr)) |
5704 (unsigned char) (0xFF >> (8 - bstr)));
5706 if (AOP_TYPE (right) == AOP_LIT)
5708 /* Case with a bitfield length <8 and literal source */
5709 int lit = (int) ulFromVal (AOP (right)->aopu.aop_lit);
5716 if (AOP(result)->type == AOP_PCODE)
5717 pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
5719 pcop = popGet(AOP(result),0);
5720 emitpcode(lit?POC_BSF:POC_BCF,pcop);
5726 emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
5730 assert( !"trying to assign to bitfield via pointer to __code space" );
5734 emitPtrByteGet(result, p_type, FALSE);
5736 emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
5738 emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
5740 emitPtrByteSet(result, p_type, TRUE);
5744 assert( !"unhandled pointer type" );
5746 } // switch (p_type)
5749 litval = lit << bstr;
5750 litval &= (~mask) & 0x00ff;
5755 mov2w (AOP(result), 0);
5756 if ((litval|mask) != 0x00ff)
5757 emitpcode(POC_ANDLW, popGetLit (mask));
5759 emitpcode(POC_IORLW, popGetLit (litval));
5760 movwf (AOP(result), 0);
5766 emitPtrByteGet(result, p_type, FALSE);
5767 if ((litval|mask) != 0x00ff)
5768 emitpcode(POC_ANDLW, popGetLit (mask));
5770 emitpcode(POC_IORLW, popGetLit (litval));
5771 emitPtrByteSet(result, p_type, TRUE);
5775 assert( !"trying to assign to bitfield via pointer to __code space" );
5779 assert( !"unhandled pointer type" );
5786 /* right is no literal */
5791 /* Note more efficient code, of pre clearing bit then only setting it if required,
5792 * can only be done if it is known that the result is not a SFR */
5793 emitpcode(POC_RRFW,popGet(AOP(right),0));
5795 emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
5797 emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
5803 emitPtrByteGet (result, p_type, FALSE);
5804 emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
5805 emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
5806 emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
5807 emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
5808 emitPtrByteSet (result, p_type, TRUE);
5812 assert( !"trying to assign to bitfield via pointer to __code space" );
5816 assert( !"unhandled pointer type" );
5821 /* Case with a bitfield 1 < length <= 8 and arbitrary source */
5822 pCodeOp *temp = popGetTempReg ();
5824 mov2w (AOP(right), 0);
5826 emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
5828 emitpcode(POC_MOVWF, temp);
5830 AccLsh (temp, bstr);
5836 mov2w (AOP(result), 0);
5837 emitpcode(POC_ANDLW, popGetLit (mask));
5838 emitpcode(POC_IORFW, temp);
5839 movwf (AOP(result), 0);
5845 emitPtrByteGet (result, p_type, FALSE);
5846 emitpcode(POC_ANDLW, popGetLit (mask));
5847 emitpcode(POC_IORFW, temp);
5848 emitPtrByteSet (result, p_type, TRUE);
5852 assert( !"trying to assign to bitfield via pointer to __code space" );
5856 assert( !"unhandled pointer type" );
5860 popReleaseTempReg (temp);
5862 } // if (AOP(right)->type != AOP_LIT)
5864 } // if (blen <= 8 && ((blen + bstr) <= 8))
5866 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
5869 /*-----------------------------------------------------------------*/
5870 /* genDataPointerSet - remat pointer to data space */
5871 /*-----------------------------------------------------------------*/
5872 static void genDataPointerSet(operand *right,
5876 int size, offset = 0 ;
5880 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5881 aopOp(right,ic,FALSE);
5882 aopOp(result,ic,FALSE);
5884 assert (IS_SYMOP(result));
5885 assert (IS_PTR(OP_SYM_TYPE(result)));
5887 if (AOP_TYPE(right) == AOP_LIT)
5890 size = AOP_SIZE(right);
5891 ressize = getSize(OP_SYM_ETYPE(result));
5892 if (size > ressize) size = ressize;
5893 //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
5895 //assert( !"what's going on here?" );
5898 if ( AOP_TYPE(result) == AOP_PCODE) {
5899 fprintf(stderr,"genDataPointerSet %s, %d\n",
5900 AOP(result)->aopu.pcop->name,
5901 PCOI(AOP(result)->aopu.pcop)->offset);
5905 // tsd, was l+1 - the underline `_' prefix was being stripped
5907 emitpComment ("%s:%u: size=%d/%d, offset=%d, AOP_TYPE(res)=%d", __FILE__,__LINE__, size, ressize, offset, AOP_TYPE(result));
5909 if (AOP_TYPE(right) == AOP_LIT) {
5910 unsigned int lit = pic14aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
5911 //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
5913 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
5914 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
5916 emitpcode(POC_CLRF, popGet(AOP(result), offset));
5919 //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
5920 emitpcode(POC_MOVFW, popGet(AOP(right), offset));
5921 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
5927 freeAsmop(right,NULL,ic,TRUE);
5928 freeAsmop(result,NULL,ic,TRUE);
5931 /*-----------------------------------------------------------------*/
5932 /* genNearPointerSet - pic14_emitcode for near pointer put */
5933 /*-----------------------------------------------------------------*/
5934 static void genNearPointerSet (operand *right,
5939 sym_link *ptype = operandType(result);
5940 sym_link *retype = getSpec(operandType(right));
5941 sym_link *letype = getSpec(ptype);
5946 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5947 aopOp(result,ic,FALSE);
5950 /* if the result is rematerializable &
5951 in data space & not a bit variable */
5952 //if (AOP_TYPE(result) == AOP_IMMD &&
5953 if (AOP_TYPE(result) == AOP_PCODE &&
5954 PIC_IS_DATA_PTR(ptype) &&
5955 !IS_BITVAR (retype) &&
5956 !IS_BITVAR (letype)) {
5957 genDataPointerSet (right,result,ic);
5958 freeAsmop(result,NULL,ic,TRUE);
5963 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5964 aopOp(right,ic,FALSE);
5965 DEBUGpic14_AopType(__LINE__,NULL,right,result);
5967 /* Check if can access directly instead of via a pointer */
5968 if ((AOP_TYPE(result) == AOP_PCODE)
5969 && (AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
5970 && (AOP_SIZE(right) == 1))
5975 if (IS_BITFIELD (letype))
5977 genPackBits (letype, result, right, direct?-1:POINTER);
5981 /* If the pointer value is not in a the FSR then need to put it in */
5982 /* Must set/reset IRP bit for use with FSR. */
5983 /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
5988 /* we have can just get the values */
5989 int size = AOP_SIZE(right);
5992 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5994 char *l = aopGet(AOP(right),offset,FALSE,TRUE);
5996 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
5998 if (AOP_TYPE(right) == AOP_LIT) {
5999 emitpcode(POC_MOVLW,popGet(AOP(right),offset));
6001 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6004 emitpcode(POC_MOVWF,popGet(AOP(result),0));
6006 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
6008 if (size && !direct)
6009 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
6014 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6015 /* now some housekeeping stuff */
6017 /* we had to allocate for this iCode */
6018 freeAsmop(NULL,aop,ic,TRUE);
6020 /* we did not allocate which means left
6021 already in a pointer register, then
6022 if size > 0 && this could be used again
6023 we have to point it back to where it
6025 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6026 if (AOP_SIZE(right) > 1 &&
6027 !OP_SYMBOL(result)->remat &&
6028 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6030 int size = AOP_SIZE(right) - 1;
6032 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
6036 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6039 freeAsmop(right,NULL,ic,TRUE);
6040 freeAsmop(result,NULL,ic,TRUE);
6043 /*-----------------------------------------------------------------*/
6044 /* genGenPointerSet - set value from generic pointer space */
6045 /*-----------------------------------------------------------------*/
6046 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
6048 sym_link *retype = getSpec(operandType(result));
6051 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6052 aopOp(right,ic,FALSE);
6053 aopOp(result,ic,FALSE);
6056 DEBUGpic14_AopType(__LINE__,right,NULL,result);
6058 if (IS_BITFIELD(retype))
6060 genPackBits (retype, result, right, GPOINTER);
6065 /* emit call to __gptrput */
6066 char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
6067 int size = AOP_SIZE(right);
6070 /* The following assertion fails for
6071 * struct foo { char a; char b; } bar;
6072 * void demo(struct foo *dst, char c) { dst->b = c; }
6073 * as size will be 1 (sizeof(c)), whereas dst->b will be accessed
6074 * using (((char *)dst)+1), whose OP_SYM_ETYPE still is struct foo
6076 * The frontend seems to guarantee that IC_LEFT has the correct size,
6077 * it works fine both for larger and smaller types of `char c'.
6079 //assert (size == getSize(OP_SYM_ETYPE(result)));
6080 assert (size > 0 && size <= 4);
6082 /* pass arguments */
6083 /* - value (MSB in Gstack_base_addr-2, growing downwards) */
6089 mov2w_op (right, off);
6090 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
6095 assert (AOP_SIZE(result) == 3);
6096 mov2w(AOP(result), 0);
6097 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
6098 mov2w(AOP(result), 1);
6099 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
6100 mov2w(AOP(result), 2);
6101 call_libraryfunc (func[size]);
6104 freeAsmop(right,NULL,ic,TRUE);
6105 freeAsmop(result,NULL,ic,TRUE);
6108 /*-----------------------------------------------------------------*/
6109 /* genPointerSet - stores the value into a pointer location */
6110 /*-----------------------------------------------------------------*/
6111 static void genPointerSet (iCode *ic)
6113 operand *right, *result ;
6114 sym_link *type, *etype;
6118 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6120 right = IC_RIGHT(ic);
6121 result = IC_RESULT(ic) ;
6123 /* depending on the type of pointer we need to
6124 move it to the correct pointer register */
6125 type = operandType(result);
6126 etype = getSpec(type);
6127 /* if left is of type of pointer then it is simple */
6128 if (IS_PTR(type) && !IS_FUNC(type->next)) {
6129 p_type = DCL_TYPE(type);
6132 /* we have to go by the storage class */
6133 p_type = PTR_TYPE(SPEC_OCLS(etype));
6135 /* if (SPEC_OCLS(etype)->codesp ) { */
6136 /* p_type = CPOINTER ; */
6139 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6140 /* p_type = FPOINTER ; */
6142 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6143 /* p_type = PPOINTER ; */
6145 /* if (SPEC_OCLS(etype) == idata ) */
6146 /* p_type = IPOINTER ; */
6148 /* p_type = POINTER ; */
6151 /* now that we have the pointer type we assign
6152 the pointer values */
6158 genNearPointerSet (right,result,ic);
6162 genPagedPointerSet (right,result,ic);
6166 genFarPointerSet (right,result,ic);
6170 genGenPointerSet (right,result,ic);
6174 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6175 "genPointerSet: illegal pointer type");
6179 /*-----------------------------------------------------------------*/
6180 /* genIfx - generate code for Ifx statement */
6181 /*-----------------------------------------------------------------*/
6182 static void genIfx (iCode *ic, iCode *popIc)
6184 operand *cond = IC_COND(ic);
6188 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6190 aopOp(cond,ic,FALSE);
6192 /* get the value into acc */
6193 if (AOP_TYPE(cond) != AOP_CRY)
6194 pic14_toBoolean(cond);
6198 /* if there was something to be popped then do it */
6204 /* This assumes that CARRY is set iff cond is true */
6207 assert (!IC_FALSE(ic));
6208 emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
6210 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
6212 assert (IC_FALSE(ic));
6213 emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
6215 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
6219 static int hasWarned = 0;
6222 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
6229 /* now Z is set iff !cond */
6232 assert (!IC_FALSE(ic));
6234 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
6237 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
6243 /* the result is now in the accumulator */
6244 freeAsmop(cond,NULL,ic,TRUE);
6247 /*-----------------------------------------------------------------*/
6248 /* genAddrOf - generates code for address of */
6249 /*-----------------------------------------------------------------*/
6250 static void genAddrOf (iCode *ic)
6252 operand *right, *result, *left;
6256 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6259 //aopOp(IC_RESULT(ic),ic,FALSE);
6261 aopOp((left=IC_LEFT(ic)),ic,FALSE);
6262 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6263 aopOp((result=IC_RESULT(ic)),ic,TRUE);
6265 DEBUGpic14_AopType(__LINE__,left,right,result);
6266 assert (IS_SYMOP (left));
6268 /* sanity check: generic pointers to code space are not yet supported,
6269 * pionters to codespace must not be assigned addresses of __data values. */
6271 fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
6272 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)));
6273 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)));
6274 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)));
6275 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)));
6278 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 __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
6280 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
6281 OP_SYMBOL(left)->name);
6282 } else if (IS_SYMOP(result) && !IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
6283 fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
6284 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
6285 OP_SYMBOL(left)->name);
6288 size = AOP_SIZE(IC_RESULT(ic));
6289 if (IS_SYMOP(result) && IS_GENPTR(OP_SYM_TYPE(result))) {
6291 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
6296 /* fixing bug #863624, reported from (errolv) */
6297 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
6298 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
6301 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
6302 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6307 if (IS_SYMOP(result) && IS_GENPTR(OP_SYM_TYPE(result)))
6309 /* provide correct tag */
6310 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
6311 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
6312 movwf (AOP(result), 2);
6315 freeAsmop(left,NULL,ic,FALSE);
6316 freeAsmop(result,NULL,ic,TRUE);
6320 /*-----------------------------------------------------------------*/
6321 /* genAssign - generate code for assignment */
6322 /*-----------------------------------------------------------------*/
6323 static void genAssign (iCode *ic)
6325 operand *result, *right;
6326 int size, offset,know_W;
6327 unsigned long lit = 0L;
6329 result = IC_RESULT(ic);
6330 right = IC_RIGHT(ic) ;
6333 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6335 /* if they are the same */
6336 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
6339 aopOp(right,ic,FALSE);
6340 aopOp(result,ic,TRUE);
6342 DEBUGpic14_AopType(__LINE__,NULL,right,result);
6344 /* if they are the same registers */
6345 if (pic14_sameRegs(AOP(right),AOP(result)))
6348 /* special case: assign from __code */
6349 if (!IS_ITEMP(right) /* --> iTemps never reside in __code */
6350 && IS_SYMOP (right) /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
6351 && !IS_FUNC(OP_SYM_TYPE(right)) /* --> we would want its address instead of the first instruction */
6352 && !IS_CODEPTR(OP_SYM_TYPE(right)) /* --> get symbols address instread */
6353 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
6355 emitpComment ("genAssign from CODESPACE");
6356 genConstPointerGet (right, result, ic);
6360 /* just for symmetry reasons... */
6361 if (!IS_ITEMP(result)
6362 && IS_SYMOP (result)
6363 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
6365 assert ( !"cannot write to CODESPACE" );
6368 /* if the result is a bit */
6369 if (AOP_TYPE(result) == AOP_CRY) {
6371 /* if the right size is a literal then
6372 we know what the value is */
6373 if (AOP_TYPE(right) == AOP_LIT) {
6375 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
6376 popGet(AOP(result),0));
6378 if (((int) operandLitValue(right)))
6379 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
6380 AOP(result)->aopu.aop_dir,
6381 AOP(result)->aopu.aop_dir);
6383 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
6384 AOP(result)->aopu.aop_dir,
6385 AOP(result)->aopu.aop_dir);
6389 /* the right is also a bit variable */
6390 if (AOP_TYPE(right) == AOP_CRY) {
6391 emitpcode(POC_BCF, popGet(AOP(result),0));
6392 emitpcode(POC_BTFSC, popGet(AOP(right),0));
6393 emitpcode(POC_BSF, popGet(AOP(result),0));
6395 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
6396 AOP(result)->aopu.aop_dir,
6397 AOP(result)->aopu.aop_dir);
6398 pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
6399 AOP(right)->aopu.aop_dir,
6400 AOP(right)->aopu.aop_dir);
6401 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
6402 AOP(result)->aopu.aop_dir,
6403 AOP(result)->aopu.aop_dir);
6408 emitpcode(POC_BCF, popGet(AOP(result),0));
6409 pic14_toBoolean(right);
6411 emitpcode(POC_BSF, popGet(AOP(result),0));
6412 //aopPut(AOP(result),"a",0);
6416 /* bit variables done */
6418 size = AOP_SIZE(result);
6420 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
6421 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6422 if(aopIdx(AOP(result),0) == 4) {
6423 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6424 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
6425 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6428 DEBUGpic14_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
6434 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6435 if(AOP_TYPE(right) == AOP_LIT) {
6436 lit = (unsigned long)pic14aopLiteral(AOP(right)->aopu.aop_lit, offset) & 0x0ff;
6438 if(know_W != (int)(lit&0xff))
6439 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
6441 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6443 emitpcode(POC_CLRF, popGet(AOP(result),offset));
6445 } else if (AOP_TYPE(right) == AOP_CRY) {
6446 emitpcode(POC_CLRF, popGet(AOP(result),offset));
6448 emitpcode(POC_BTFSS, popGet(AOP(right),0));
6449 emitpcode(POC_INCF, popGet(AOP(result),0));
6452 mov2w_op (right, offset);
6453 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6461 freeAsmop (right,NULL,ic,FALSE);
6462 freeAsmop (result,NULL,ic,TRUE);
6465 /*-----------------------------------------------------------------*/
6466 /* genJumpTab - genrates code for jump table */
6467 /*-----------------------------------------------------------------*/
6468 static void genJumpTab (iCode *ic)
6474 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6476 aopOp(IC_JTCOND(ic),ic,FALSE);
6477 /* get the condition into accumulator */
6478 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
6480 /* multiply by three */
6481 pic14_emitcode("add","a,acc");
6482 pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
6484 jtab = newiTempLabel(NULL);
6485 pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
6486 pic14_emitcode("jmp","@a+dptr");
6487 pic14_emitcode("","%05d_DS_:",jtab->key+100);
6489 emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
6490 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
6491 emitpcode(POC_MOVLW, popGetLabel(jtab->key));
6492 emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
6494 emitpcode(POC_INCF, popCopyReg(&pc_pclath));
6495 emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
6496 emitpLabel(jtab->key);
6498 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
6500 /* now generate the jump labels */
6501 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
6502 jtab = setNextItem(IC_JTLABELS(ic))) {
6503 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
6504 emitpcode(POC_GOTO,popGetLabel(jtab->key));
6510 /*-----------------------------------------------------------------*/
6511 /* genCast - gen code for casting */
6512 /*-----------------------------------------------------------------*/
6513 static void genCast (iCode *ic)
6515 operand *result = IC_RESULT(ic);
6516 sym_link *restype = operandType(result);
6517 sym_link *rtype = operandType(IC_RIGHT(ic));
6518 operand *right = IC_RIGHT(ic);
6522 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
6523 /* if they are equivalent then do nothing */
6524 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
6527 aopOp(right,ic,FALSE) ;
6528 aopOp(result,ic,FALSE);
6530 DEBUGpic14_AopType(__LINE__,NULL,right,result);
6532 /* if the result is a bit */
6533 if (AOP_TYPE(result) == AOP_CRY) {
6534 assert(!"assigning to bit variables is not supported");
6537 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
6539 size = AOP_SIZE(result);
6541 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
6543 emitpcode(POC_CLRF, popGet(AOP(result),0));
6544 emitpcode(POC_BTFSC, popGet(AOP(right),0));
6545 emitpcode(POC_INCF, popGet(AOP(result),0));
6548 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
6553 if (IS_PTR(restype))
6555 operand *result = IC_RESULT(ic);
6556 //operand *left = IC_LEFT(ic);
6557 operand *right = IC_RIGHT(ic);
6560 /* copy common part */
6561 int max, size = AOP_SIZE(result);
6562 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
6563 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
6565 /* warn if we discard generic opinter tag */
6566 if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
6568 //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
6574 mov2w_op (right, size);
6575 movwf (AOP(result), size);
6578 /* upcast into generic pointer type? */
6579 if (IS_GENPTR(restype)
6580 && (size < AOP_SIZE(result))
6581 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
6583 //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
6586 switch (DCL_TYPE(rtype))
6588 case POINTER: /* __data */
6589 case FPOINTER: /* __data */
6590 assert (AOP_SIZE(right) == 2);
6594 case CPOINTER: /* __code */
6595 assert (AOP_SIZE(right) == 2);
6599 case GPOINTER: /* unknown destination, __data or __code */
6600 /* assume __data space (address of immediate) */
6601 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
6602 if (AOP(right)->code)
6609 assert (!"unhandled pointer type");
6612 /* convert other values into pointers to __data space */
6616 assert (AOP_SIZE(result) == 3);
6618 emitpcode(POC_CLRF, popGet(AOP(result), 2));
6620 emitpcode(POC_MOVLW, popGetLit(tag));
6621 movwf(AOP(result), 2);
6624 addSign(result, max, 0);
6629 /* if they are the same size : or less */
6630 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
6632 /* if they are in the same place */
6633 if (pic14_sameRegs(AOP(right),AOP(result)))
6636 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
6637 if (IS_PTR_CONST(rtype))
6638 DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
6639 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
6640 DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
6642 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
6643 emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
6644 emitpcode(POC_MOVWF, popGet(AOP(result),0));
6645 emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
6646 emitpcode(POC_MOVWF, popGet(AOP(result),1));
6647 if(AOP_SIZE(result) <2)
6648 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
6652 /* if they in different places then copy */
6653 size = AOP_SIZE(result);
6656 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
6657 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6659 //aopPut(AOP(result),
6660 // aopGet(AOP(right),offset,FALSE,FALSE),
6669 /* so we now know that the size of destination is greater
6670 than the size of the source. */
6672 /* we move to result for the size of source */
6673 size = AOP_SIZE(right);
6676 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
6677 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6681 addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
6684 freeAsmop(right,NULL,ic,TRUE);
6685 freeAsmop(result,NULL,ic,TRUE);
6689 /*-----------------------------------------------------------------*/
6690 /* genDjnz - generate decrement & jump if not zero instrucion */
6691 /*-----------------------------------------------------------------*/
6692 static int genDjnz (iCode *ic, iCode *ifx)
6696 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6701 /* if the if condition has a false label
6702 then we cannot save */
6706 /* if the minus is not of the form
6708 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
6709 !IS_OP_LITERAL(IC_RIGHT(ic)))
6712 if (operandLitValue(IC_RIGHT(ic)) != 1)
6715 /* if the size of this greater than one then no
6717 if (getSize(operandType(IC_RESULT(ic))) > 1)
6720 /* otherwise we can save BIG */
6721 lbl = newiTempLabel(NULL);
6722 lbl1= newiTempLabel(NULL);
6724 aopOp(IC_RESULT(ic),ic,FALSE);
6726 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
6727 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
6729 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
6734 /*-----------------------------------------------------------------*/
6735 /* genReceive - generate code for a receive iCode */
6736 /*-----------------------------------------------------------------*/
6737 static void genReceive (iCode *ic)
6740 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6742 if (isOperandInFarSpace(IC_RESULT(ic)) &&
6743 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
6744 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
6746 int size = getSize(operandType(IC_RESULT(ic)));
6747 int offset = fReturnSizePic - size;
6749 pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
6750 fReturn[fReturnSizePic - offset - 1] : "acc"));
6753 aopOp(IC_RESULT(ic),ic,FALSE);
6754 size = AOP_SIZE(IC_RESULT(ic));
6757 pic14_emitcode ("pop","acc");
6758 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
6763 aopOp(IC_RESULT(ic),ic,FALSE);
6765 GpsuedoStkPtr = ic->parmBytes; // address used arg on stack
6766 assignResultValue(IC_RESULT(ic));
6769 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
6772 /*-----------------------------------------------------------------*/
6773 /* genDummyRead - generate code for dummy read of volatiles */
6774 /*-----------------------------------------------------------------*/
6776 genDummyRead (iCode * ic)
6779 pic14_emitcode ("; genDummyRead","");
6780 pic14_emitcode ("; not implemented","");
6785 /*-----------------------------------------------------------------*/
6786 /* genpic14Code - generate code for pic14 based controllers */
6787 /*-----------------------------------------------------------------*/
6789 * At this point, ralloc.c has gone through the iCode and attempted
6790 * to optimize in a way suitable for a PIC. Now we've got to generate
6791 * PIC instructions that correspond to the iCode.
6793 * Once the instructions are generated, we'll pass through both the
6794 * peep hole optimizer and the pCode optimizer.
6795 *-----------------------------------------------------------------*/
6797 void genpic14Code (iCode *lic)
6804 lineHead = lineCurr = NULL;
6806 pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
6809 /* if debug information required */
6810 if (options.debug && debugFile && currFunc) {
6811 debugFile->writeFunction (currFunc, lic);
6815 for (ic = lic ; ic ; ic = ic->next ) {
6817 //DEBUGpic14_emitcode(";ic","");
6818 //fprintf (stderr, "in ic loop\n");
6819 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
6820 //ic->lineno, printCLine(ic->filename, ic->lineno));
6822 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
6824 //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
6825 cline = printCLine (ic->filename, ic->lineno);
6826 if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
6827 addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
6828 //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
6831 if (options.iCodeInAsm) {
6832 const char *iLine = printILine(ic);
6833 emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
6836 /* if the result is marked as
6837 spilt and rematerializable or code for
6838 this has already been generated then
6840 if (resultRemat(ic) || ic->generated )
6843 /* depending on the operation */
6862 /* IPOP happens only when trying to restore a
6863 spilt live range, if there is an ifx statement
6864 following this pop then the if statement might
6865 be using some of the registers being popped which
6866 would destory the contents of the register so
6867 we need to check for this condition and handle it */
6869 ic->next->op == IFX &&
6870 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
6871 genIfx (ic->next,ic);
6889 genEndFunction (ic);
6909 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
6926 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
6930 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
6937 /* note these two are xlated by algebraic equivalence
6938 during parsing SDCC.y */
6939 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
6940 "got '>=' or '<=' shouldn't have come here");
6944 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
6956 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
6960 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
6964 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
6991 case GET_VALUE_AT_ADDRESS:
6996 if (POINTER_SET(ic))
7023 addSet(&_G.sendSet,ic);
7026 case DUMMY_READ_VOLATILE:
7031 fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
7038 /* now we are ready to call the
7039 peep hole optimizer */
7040 if (!options.nopeep) {
7041 peepHole (&lineHead);
7043 /* now do the actual printing */
7044 printLine (lineHead,codeOutBuf);
7047 DFPRINTF((stderr,"printing pBlock\n\n"));
7048 printpBlock(stdout,pb);
7054 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
7055 * (meaning: representing its own address) or not (referencing its contents).
7056 * This can only be decided based on the operand's type. */
7058 aop_isLitLike (asmop *aop)
7061 if (aop->type == AOP_LIT) return 1;
7062 if (aop->type == AOP_IMMD) return 1;
7063 if ((aop->type == AOP_PCODE) &&
7064 ((aop->aopu.pcop->type == PO_LITERAL)))
7066 /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
7067 * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
7074 op_isLitLike (operand *op)
7077 if (aop_isLitLike (AOP(op))) return 1;
7078 if (IS_SYMOP(op) && IS_FUNC(OP_SYM_TYPE(op))) return 1;
7079 if (IS_SYMOP(op) && IS_PTR(OP_SYM_TYPE(op))
7080 && (AOP_TYPE(op) == AOP_PCODE)
7081 && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {