1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for pic
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 PIC port - Scott Dattalo scott@dattalo.com (2000)
8 cont'd - Raphael Neider <rneider AT web.de> (2005)
10 This program is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the
12 Free Software Foundation; either version 2, or (at your option) any
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 In other words, you are welcome to use, share and improve this program.
25 You are forbidden to forbid anyone else to use, share and improve
26 what you give them. Help stamp out software-hoarding!
29 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
30 Made everything static
31 -------------------------------------------------------------------------*/
37 #include "SDCCglobl.h"
41 #include "SDCCpeeph.h"
47 /* The PIC port(s) need not differentiate between POINTER and FPOINTER. */
48 #define PIC_IS_DATA_PTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
49 #define PIC_IS_FARPTR(x) (PIC_IS_DATA_PTR(x))
51 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
52 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
53 void genMult8X8_8 (operand *, operand *,operand *);
54 extern void printpBlock(FILE *of, pBlock *pb);
56 static int labelOffset=0;
57 extern int debug_verbose;
58 extern int pic14_hasInterrupt;
59 //static int optimized_for_speed = 0;
61 /* max_key keeps track of the largest label number used in
62 a function. This is then used to adjust the label offset
63 for the next function.
66 static int GpsuedoStkPtr=0;
67 static int pic14_inISR = 0;
69 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
70 extern char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
71 const char *AopType(short type);
73 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0x00ff)
75 /* this is the down and dirty file with all kinds of
76 kludgy & hacky stuff. This is what it is all about
77 CODE GENERATION for a specific MCU . some of the
78 routines may be reusable, will have to see */
80 static char *zero = "0x00";
81 static char *one = "0x01";
82 static char *spname = "sp";
84 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
85 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
86 static char **fReturn = fReturnpic14;
96 /* Resolved ifx structure. This structure stores information
97 about an iCode ifx that makes it easier to generate code.
99 typedef struct resolvedIfx {
100 symbol *lbl; /* pointer to a label */
101 int condition; /* true or false ifx */
102 int generated; /* set true when the code associated with the ifx
106 extern int pic14_nRegs;
107 extern struct dbuf_s *codeOutBuf;
108 static void saverbank (int, iCode *,bool);
110 static lineNode *lineHead = NULL;
111 static lineNode *lineCurr = NULL;
115 /*-----------------------------------------------------------------*/
116 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
117 /* exponent of 2 is returned, otherwise -1 is */
119 /* note that this is similar to the function `powof2' in SDCCsymt */
123 /*-----------------------------------------------------------------*/
124 static int my_powof2 (unsigned long num)
127 if( (num & (num-1)) == 0) {
140 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
143 DEBUGpic14_emitcode ("; ","line = %d result %s=%s, size=%d, left %s=%s, size=%d, right %s=%s, size=%d",
145 ((result) ? AopType(AOP_TYPE(result)) : "-"),
146 ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
147 ((result) ? AOP_SIZE(result) : 0),
148 ((left) ? AopType(AOP_TYPE(left)) : "-"),
149 ((left) ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
150 ((left) ? AOP_SIZE(left) : 0),
151 ((right) ? AopType(AOP_TYPE(right)) : "-"),
152 ((right) ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
153 ((right) ? AOP_SIZE(right) : 0));
157 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
160 DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
162 ((result) ? AopType(AOP_TYPE(result)) : "-"),
163 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
164 ((left) ? AopType(AOP_TYPE(left)) : "-"),
165 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
166 ((right) ? AopType(AOP_TYPE(right)) : "-"),
167 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
171 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
174 char lb[INITIAL_INLINEASM];
175 unsigned char *lbp = (unsigned char *)lb;
177 if(!debug_verbose && !options.debug)
184 sprintf(lb,"%s\t",inst);
186 sprintf(lb,"%s",inst);
187 vsprintf(lb+(strlen(lb)),fmt,ap);
191 while (isspace(*lbp)) lbp++;
194 lineCurr = (lineCurr ?
195 connectLine(lineCurr,newLineNode(lb)) :
196 (lineHead = newLineNode(lb)));
197 lineCurr->isInline = _G.inLine;
198 lineCurr->isDebug = _G.debugLine;
200 addpCode2pBlock(pb,newpCodeCharP(lb));
205 static void Safe_vsnprintf (char *buf, size_t size, const char *fmt, va_list ap)
207 #if defined (HAVE_VSNPRINTF)
208 vsnprintf (buf, size, fmt, ap);
209 #elif defined (HAVE_VSPRINTF)
210 vsprintf (buf, size, fmt, ap);
211 if (strlen (buf) >= size)
213 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
215 #elif defined (HAVE_SNPRINTF)
216 snprintf (buf, size, "vs(n)printf required");
217 #elif defined (HAVE_SRINTF)
218 sprintf (buf, "vs(n)printf required");
219 if (strlen (buf) >= size)
221 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
224 assert ( !"neither vsnprintf nor vsprintf is present -- unable to proceed" );
228 void emitpComment (const char *fmt, ...)
235 Safe_vsnprintf (buffer, 4096, fmt, va);
236 //fprintf (stderr, "%s\n" ,buffer);
237 addpCode2pBlock (pb, newpCodeCharP (buffer));
240 Safe_vsnprintf (buffer, 4096, fmt, va);
241 fprintf (stderr, "No current pBlock -- discarding comment [%s]\n", buffer);
247 void emitpLabel(int key)
249 addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
252 /* gen.h defines a macro emitpcode that should be used to call emitpcode
253 * as this allows for easy debugging (ever asked the question: where was
254 * this instruction geenrated? Here is the answer... */
255 void emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
258 addpCode2pBlock(pb,newpCode(poc,pcop));
260 static int has_warned = 0;
262 DEBUGpic14_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
265 fprintf( stderr, "WARNING: encountered NULL pcop--this is probably a compiler bug...\n" );
270 void emitpcodeNULLop(PIC_OPCODE poc)
273 addpCode2pBlock(pb,newpCode(poc,NULL));
278 /*-----------------------------------------------------------------*/
279 /* pic14_emitcode - writes the code into a file : for now it is simple */
280 /*-----------------------------------------------------------------*/
281 void pic14_emitcode (char *inst,char *fmt, ...)
284 char lb[INITIAL_INLINEASM];
291 sprintf(lb,"%s\t",inst);
293 sprintf(lb,"%s",inst);
294 vsprintf(lb+(strlen(lb)),fmt,ap);
298 while (isspace(*lbp)) lbp++;
301 lineCurr = (lineCurr ?
302 connectLine(lineCurr,newLineNode(lb)) :
303 (lineHead = newLineNode(lb)));
304 lineCurr->isInline = _G.inLine;
305 lineCurr->isDebug = _G.debugLine;
306 lineCurr->isLabel = (lbp[strlen (lbp) - 1] == ':');
309 addpCode2pBlock(pb,newpCodeCharP(lb));
314 /*-----------------------------------------------------------------*/
315 /* pic14_emitDebuggerSymbol - associate the current code location */
316 /* with a debugger symbol */
317 /*-----------------------------------------------------------------*/
319 pic14_emitDebuggerSymbol (char * debugSym)
322 pic14_emitcode ("", ";%s ==.", debugSym);
326 /*-----------------------------------------------------------------*/
327 /* newAsmop - creates a new asmOp */
328 /*-----------------------------------------------------------------*/
329 asmop *newAsmop (short type)
333 aop = Safe_calloc(1,sizeof(asmop));
338 /*-----------------------------------------------------------------*/
339 /* resolveIfx - converts an iCode ifx into a form more useful for */
340 /* generating code */
341 /*-----------------------------------------------------------------*/
342 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
347 // DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
349 resIfx->condition = 1; /* assume that the ifx is true */
350 resIfx->generated = 0; /* indicate that the ifx has not been used */
353 resIfx->lbl = NULL; /* this is wrong: newiTempLabel(NULL); / * oops, there is no ifx. so create a label */
355 DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
356 __FUNCTION__,__LINE__,resIfx->lbl->key);
360 resIfx->lbl = IC_TRUE(ifx);
362 resIfx->lbl = IC_FALSE(ifx);
363 resIfx->condition = 0;
367 DEBUGpic14_emitcode("; ***","ifx true is non-null");
369 DEBUGpic14_emitcode("; ***","ifx false is non-null");
373 // DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
376 /*-----------------------------------------------------------------*/
377 /* pointerCode - returns the code for a pointer type */
378 /*-----------------------------------------------------------------*/
380 static int pointerCode (sym_link *etype)
383 return PTR_TYPE(SPEC_OCLS(etype));
388 /*-----------------------------------------------------------------*/
389 /* aopForSym - for a true symbol */
390 /*-----------------------------------------------------------------*/
391 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
394 memmap *space= SPEC_OCLS(sym->etype);
396 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
397 /* if already has one */
401 //DEBUGpic14_emitcode(";","%d",__LINE__);
402 /* if it is in direct space */
403 if (IN_DIRSPACE(space)) {
404 sym->aop = aop = newAsmop (AOP_DIR);
405 aop->aopu.aop_dir = sym->rname ;
406 aop->size = getSize(sym->type);
407 DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
411 /* special case for a function */
412 if (IS_FUNC(sym->type)) {
414 sym->aop = aop = newAsmop(AOP_PCODE);
415 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
416 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
417 PCOI(aop->aopu.pcop)->_function = 1;
418 PCOI(aop->aopu.pcop)->index = 0;
419 aop->size = FPTRSIZE;
421 sym->aop = aop = newAsmop(AOP_IMMD);
422 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
423 strcpy(aop->aopu.aop_immd,sym->rname);
424 aop->size = FPTRSIZE;
426 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
430 if (IS_ARRAY(sym->type)) {
431 sym->aop = aop = newAsmop(AOP_PCODE);
432 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
433 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
434 PCOI(aop->aopu.pcop)->_function = 0;
435 PCOI(aop->aopu.pcop)->index = 0;
436 aop->size = getSize(sym->etype) * DCL_ELEM(sym->type);
438 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
442 /* only remaining is far space */
443 /* in which case DPTR gets the address */
444 sym->aop = aop = newAsmop(AOP_PCODE);
446 aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
447 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
448 PCOI(aop->aopu.pcop)->index = 0;
450 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
451 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
453 allocDirReg (IC_LEFT(ic));
455 aop->size = FPTRSIZE;
457 /* if it is in code space */
458 if (IN_CODESPACE(space))
464 /*-----------------------------------------------------------------*/
465 /* aopForRemat - rematerialzes an object */
466 /*-----------------------------------------------------------------*/
467 static asmop *aopForRemat (operand *op) // x symbol *sym)
469 symbol *sym = OP_SYMBOL(op);
471 asmop *aop = newAsmop(AOP_PCODE);
475 ic = sym->rematiCode;
477 DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
478 if(IS_OP_POINTER(op)) {
479 DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
483 val += (int) operandLitValue(IC_RIGHT(ic));
484 } else if (ic->op == '-') {
485 val -= (int) operandLitValue(IC_RIGHT(ic));
489 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
492 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
493 aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
494 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
495 PCOI(aop->aopu.pcop)->index = val;
497 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
498 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
499 val, IS_PTR_CONST(operandType(op)));
501 // DEBUGpic14_emitcode(";","aop type %s",AopType(AOP_TYPE(IC_LEFT(ic))));
503 allocDirReg (IC_LEFT(ic));
508 int aopIdx (asmop *aop, int offset)
513 if(aop->type != AOP_REG)
516 return aop->aopu.aop_reg[offset]->rIdx;
519 /*-----------------------------------------------------------------*/
520 /* regsInCommon - two operands have some registers in common */
521 /*-----------------------------------------------------------------*/
522 static bool regsInCommon (operand *op1, operand *op2)
527 /* if they have registers in common */
528 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
531 sym1 = OP_SYMBOL(op1);
532 sym2 = OP_SYMBOL(op2);
534 if (sym1->nRegs == 0 || sym2->nRegs == 0)
537 for (i = 0 ; i < sym1->nRegs ; i++) {
542 for (j = 0 ; j < sym2->nRegs ;j++ ) {
546 if (sym2->regs[j] == sym1->regs[i])
554 /*-----------------------------------------------------------------*/
555 /* operandsEqu - equivalent */
556 /*-----------------------------------------------------------------*/
557 static bool operandsEqu ( operand *op1, operand *op2)
561 /* if they not symbols */
562 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
565 sym1 = OP_SYMBOL(op1);
566 sym2 = OP_SYMBOL(op2);
568 /* if both are itemps & one is spilt
569 and the other is not then false */
570 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
571 sym1->isspilt != sym2->isspilt )
574 /* if they are the same */
578 if (sym1->rname[0] && sym2->rname[0]
579 && strcmp (sym1->rname, sym2->rname) == 0)
583 /* if left is a tmp & right is not */
587 (sym1->usl.spillLoc == sym2))
594 (sym2->usl.spillLoc == sym1))
600 /*-----------------------------------------------------------------*/
601 /* pic14_sameRegs - two asmops have the same registers */
602 /*-----------------------------------------------------------------*/
603 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
610 if (aop1->type != AOP_REG ||
611 aop2->type != AOP_REG )
614 if (aop1->size != aop2->size )
617 for (i = 0 ; i < aop1->size ; i++ )
618 if (aop1->aopu.aop_reg[i] !=
619 aop2->aopu.aop_reg[i] )
625 /*-----------------------------------------------------------------*/
626 /* aopOp - allocates an asmop for an operand : */
627 /*-----------------------------------------------------------------*/
628 void aopOp (operand *op, iCode *ic, bool result)
637 /* if this a literal */
638 if (IS_OP_LITERAL(op)) {
639 op->aop = aop = newAsmop(AOP_LIT);
640 aop->aopu.aop_lit = op->operand.valOperand;
641 aop->size = getSize(operandType(op));
646 sym_link *type = operandType(op);
647 if(IS_PTR_CONST(type))
648 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
651 /* if already has a asmop then continue */
655 /* if the underlying symbol has a aop */
656 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
657 DEBUGpic14_emitcode(";","%d",__LINE__);
658 op->aop = OP_SYMBOL(op)->aop;
662 /* if this is a true symbol */
663 if (IS_TRUE_SYMOP(op)) {
664 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
665 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
669 /* this is a temporary : this has
675 e) can be a return use only */
680 /* if the type is a conditional */
681 if (sym->regType == REG_CND) {
682 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
687 /* if it is spilt then two situations
689 b) has a spill location */
690 if (sym->isspilt || sym->nRegs == 0) {
692 DEBUGpic14_emitcode(";","%d",__LINE__);
693 /* rematerialize it NOW */
696 sym->aop = op->aop = aop = aopForRemat (op);
697 aop->size = getSize(sym->type);
698 //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
703 if(sym->isptr) { // && sym->uptr
704 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
705 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
707 //PCOI(aop->aopu.pcop)->_const = 0;
708 //PCOI(aop->aopu.pcop)->index = 0;
710 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
711 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
713 //allocDirReg (IC_LEFT(ic));
715 aop->size = getSize(sym->type);
716 DEBUGpic14_emitcode(";","%d",__LINE__);
723 aop = op->aop = sym->aop = newAsmop(AOP_STR);
724 aop->size = getSize(sym->type);
725 for ( i = 0 ; i < fReturnSizePic ; i++ )
726 aop->aopu.aop_str[i] = fReturn[i];
728 DEBUGpic14_emitcode(";","%d",__LINE__);
733 /* else spill location */
734 if (sym->usl.spillLoc)
736 asmop *oldAsmOp = NULL;
738 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
740 /* force a new aop if sizes differ */
741 oldAsmOp = sym->usl.spillLoc->aop;
742 sym->usl.spillLoc->aop = NULL;
744 DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
745 __FUNCTION__,__LINE__,
746 sym->usl.spillLoc->rname,
747 sym->rname, sym->usl.spillLoc->offset);
749 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
750 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
752 /* Don't reuse the new aop, go with the last one */
753 sym->usl.spillLoc->aop = oldAsmOp;
755 //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
756 aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname,
758 sym->usl.spillLoc->offset);
759 aop->size = getSize(sym->type);
766 sym_link *type = operandType(op);
767 if(IS_PTR_CONST(type))
768 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
771 /* must be in a register */
772 DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
773 sym->aop = op->aop = aop = newAsmop(AOP_REG);
774 aop->size = sym->nRegs;
775 for ( i = 0 ; i < sym->nRegs ;i++)
776 aop->aopu.aop_reg[i] = sym->regs[i];
779 /*-----------------------------------------------------------------*/
780 /* freeAsmop - free up the asmop given to an operand */
781 /*----------------------------------------------------------------*/
782 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
796 /* all other cases just dealloc */
800 OP_SYMBOL(op)->aop = NULL;
801 /* if the symbol has a spill */
803 SPIL_LOC(op)->aop = NULL;
808 /*-----------------------------------------------------------------*/
809 /* aopGet - for fetching value of the aop */
810 /*-----------------------------------------------------------------*/
811 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
816 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
817 /* offset is greater than
820 if (offset > (aop->size - 1) &&
821 aop->type != AOP_LIT)
824 /* depending on type */
829 sprintf (s,"%s",aop->aopu.aop_immd);
832 sprintf(s,"(%s >> %d)",
838 DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
839 rs = Safe_calloc(1,strlen(s)+1);
845 sprintf(s,"(%s + %d)",
848 DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
850 sprintf(s,"%s",aop->aopu.aop_dir);
851 rs = Safe_calloc(1,strlen(s)+1);
857 // return aop->aopu.aop_reg[offset]->dname;
859 return aop->aopu.aop_reg[offset]->name;
862 //pic14_emitcode(";","%d",__LINE__);
863 return aop->aopu.aop_dir;
866 sprintf(s, "0x%02x", pic14aopLiteral (aop->aopu.aop_lit, offset));
872 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
875 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
877 return aop->aopu.aop_str[offset];
881 pCodeOp *pcop = aop->aopu.pcop;
882 DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
884 if (pcop->type == PO_IMMEDIATE) {
885 offset += PCOI(pcop)->index;
888 DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
889 sprintf(s,"(%s+%d)", pcop->name,offset);
891 DEBUGpic14_emitcode(";","%s",pcop->name);
892 sprintf(s,"%s", pcop->name);
895 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
898 rs = Safe_calloc(1,strlen(s)+1);
904 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
905 "aopget got unsupported aop->type");
910 /*-----------------------------------------------------------------*/
911 /* popGetTempReg - create a new temporary pCodeOp */
912 /*-----------------------------------------------------------------*/
913 pCodeOp *popGetTempReg(void)
918 pcop = newpCodeOp(NULL, PO_GPR_TEMP);
919 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
920 PCOR(pcop)->r->wasUsed=1;
921 PCOR(pcop)->r->isFree=0;
927 /*-----------------------------------------------------------------*/
928 /* popReleaseTempReg - create a new temporary pCodeOp */
929 /*-----------------------------------------------------------------*/
930 void popReleaseTempReg(pCodeOp *pcop)
933 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
934 PCOR(pcop)->r->isFree = 1;
937 /*-----------------------------------------------------------------*/
938 /* popGetLabel - create a new pCodeOp of type PO_LABEL */
939 /*-----------------------------------------------------------------*/
940 pCodeOp *popGetLabel(unsigned int key)
943 DEBUGpic14_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, labelOffset);
945 if(key>(unsigned int)max_key)
948 return newpCodeOpLabel(NULL,key+100+labelOffset);
951 /*-------------------------------------------------------------------*/
952 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
953 /*-------------------------------------------------------------------*/
954 pCodeOp *popGetHighLabel(unsigned int key)
957 pcop = popGetLabel(key);
958 PCOLAB(pcop)->offset = 1;
962 /*-----------------------------------------------------------------*/
963 /* popGetLit - asm operator to pcode operator conversion */
964 /*-----------------------------------------------------------------*/
965 pCodeOp *popGetLit(unsigned int lit)
968 return newpCodeOpLit((unsigned char)lit);
971 /*-----------------------------------------------------------------*/
972 /* popGetImmd - asm operator to pcode immediate conversion */
973 /*-----------------------------------------------------------------*/
974 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
977 return newpCodeOpImmd(name, offset,index, 0, is_func);
982 /*-----------------------------------------------------------------*/
983 /* popGetWithString - asm operator to pcode operator conversion */
984 /*-----------------------------------------------------------------*/
985 pCodeOp *popGetWithString(char *str, int isExtern)
991 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
995 pcop = newpCodeOp(str,PO_STR);
996 PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1001 pCodeOp *popGetExternal (char *str, int isReg)
1006 pcop = newpCodeOpRegFromStr(str);
1008 pcop = popGetWithString (str, 1);
1014 for (sym = setFirstItem (externs); sym; sym = setNextItem (externs))
1016 if (!strcmp (str, sym->rname)) break;
1021 sym = newSymbol(str, 0);
1022 strncpy(sym->rname, str, SDCC_NAME_MAX);
1023 addSet (&externs, sym);
1030 /*-----------------------------------------------------------------*/
1031 /* popRegFromString - */
1032 /*-----------------------------------------------------------------*/
1033 pCodeOp *popRegFromString(char *str, int size, int offset)
1036 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1037 pcop->type = PO_DIR;
1039 DEBUGpic14_emitcode(";","%d",__LINE__);
1044 pcop->name = Safe_calloc(1,strlen(str)+1);
1045 strcpy(pcop->name,str);
1047 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1049 PCOR(pcop)->r = dirregWithName(pcop->name);
1050 if(PCOR(pcop)->r == NULL) {
1051 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1052 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1053 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1055 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1057 PCOR(pcop)->instance = offset;
1062 /*-----------------------------------------------------------------*/
1063 /*-----------------------------------------------------------------*/
1064 pCodeOp *popRegFromIdx(int rIdx)
1068 DEBUGpic14_emitcode ("; ***","%s,%d , rIdx=0x%x",
1069 __FUNCTION__,__LINE__,rIdx);
1071 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1073 PCOR(pcop)->rIdx = rIdx;
1074 PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1075 PCOR(pcop)->r->isFree = 0;
1076 PCOR(pcop)->r->wasUsed = 1;
1078 pcop->type = PCOR(pcop)->r->pc_type;
1084 /*-----------------------------------------------------------------*/
1085 /* popGet - asm operator to pcode operator conversion */
1086 /*-----------------------------------------------------------------*/
1087 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1089 //char *s = buffer ;
1094 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1095 /* offset is greater than
1101 /* XXX: still needed for BIT operands (AOP_CRY) */
1102 if (offset > (aop->size - 1) &&
1103 aop->type != AOP_LIT &&
1104 aop->type != AOP_PCODE)
1106 printf( "%s: (offset[%d] > AOP_SIZE(op)[%d]-1) && AOP_TYPE(op) != AOP_LIT)\n", __FUNCTION__, offset, aop->size);
1107 return NULL; //zero;
1110 /* depending on type */
1111 switch (aop->type) {
1114 DEBUGpic14_emitcode(";","%d",__LINE__);
1115 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1118 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1120 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1121 pcop->type = PO_DIR;
1123 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1124 strcpy(pcop->name,aop->aopu.aop_dir);
1125 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1126 if(PCOR(pcop)->r == NULL) {
1127 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1128 PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1129 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1131 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1133 PCOR(pcop)->instance = offset;
1141 assert (offset < aop->size);
1142 rIdx = aop->aopu.aop_reg[offset]->rIdx;
1144 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1145 PCOR(pcop)->rIdx = rIdx;
1146 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1147 PCOR(pcop)->r->wasUsed=1;
1148 PCOR(pcop)->r->isFree=0;
1150 PCOR(pcop)->instance = offset;
1151 pcop->type = PCOR(pcop)->r->pc_type;
1152 //rs = aop->aopu.aop_reg[offset]->name;
1153 DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1158 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1159 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1160 //if(PCOR(pcop)->r == NULL)
1161 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1165 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1168 DEBUGpic14_emitcode(";","%d %s",__LINE__,aop->aopu.aop_str[offset]);
1169 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1171 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1172 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1173 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1174 pcop->type = PCOR(pcop)->r->pc_type;
1175 pcop->name = PCOR(pcop)->r->name;
1182 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1184 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1185 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1186 switch (aop->aopu.pcop->type)
1189 pcop = pCodeOpCopy (aop->aopu.pcop);
1190 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1191 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1192 PCOI(pcop)->index += offset;
1193 //PCOI(pcop)->offset = 0;
1196 pcop = pCodeOpCopy (aop->aopu.pcop);
1197 PCOR(pcop)->instance = offset;
1200 assert ( !"unhandled pCode type" );
1206 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1207 "popGet got unsupported aop->type");
1211 /*-----------------------------------------------------------------*/
1212 /* popGetAddr - access the low/high word of a symbol (immediate) */
1213 /* (for non-PO_IMMEDIATEs this is the same as popGet) */
1214 /*-----------------------------------------------------------------*/
1215 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1217 if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1219 pCodeOp *pcop = aop->aopu.pcop;
1220 assert (offset <= GPTRSIZE);
1222 /* special case: index >= 2 should return GPOINTER-style values */
1225 pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1229 pcop = pCodeOpCopy (pcop);
1230 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1231 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1232 PCOI(pcop)->offset += offset;
1233 PCOI(pcop)->index += index;
1234 //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);
1237 return popGet (aop, offset + index);
1241 /*-----------------------------------------------------------------*/
1242 /* aopPut - puts a string for a aop */
1243 /*-----------------------------------------------------------------*/
1244 void aopPut (asmop *aop, char *s, int offset)
1249 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1251 if (aop->size && offset > ( aop->size - 1)) {
1252 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1253 "aopPut got offset > aop->size");
1257 /* will assign value to value */
1258 /* depending on where it is ofcourse */
1259 switch (aop->type) {
1262 sprintf(d,"(%s + %d)",
1263 aop->aopu.aop_dir,offset);
1264 fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1267 sprintf(d,"%s",aop->aopu.aop_dir);
1270 DEBUGpic14_emitcode(";","%d",__LINE__);
1272 pic14_emitcode("movf","%s,w",s);
1273 pic14_emitcode("movwf","%s",d);
1276 pic14_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
1277 if(offset >= aop->size) {
1278 emitpcode(POC_CLRF,popGet(aop,offset));
1281 emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
1284 emitpcode(POC_MOVWF,popGet(aop,offset));
1290 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1291 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1294 strcmp(s,"r0") == 0 ||
1295 strcmp(s,"r1") == 0 ||
1296 strcmp(s,"r2") == 0 ||
1297 strcmp(s,"r3") == 0 ||
1298 strcmp(s,"r4") == 0 ||
1299 strcmp(s,"r5") == 0 ||
1300 strcmp(s,"r6") == 0 ||
1301 strcmp(s,"r7") == 0 )
1302 pic14_emitcode("mov","%s,%s ; %d",
1303 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1307 if(strcmp(s,"W")==0 )
1308 pic14_emitcode("movf","%s,w ; %d",s,__LINE__);
1310 pic14_emitcode("movwf","%s",
1311 aop->aopu.aop_reg[offset]->name);
1313 if(strcmp(s,zero)==0) {
1314 emitpcode(POC_CLRF,popGet(aop,offset));
1316 } else if(strcmp(s,"W")==0) {
1317 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1318 pcop->type = PO_GPR_REGISTER;
1320 PCOR(pcop)->rIdx = -1;
1321 PCOR(pcop)->r = NULL;
1323 DEBUGpic14_emitcode(";","%d",__LINE__);
1324 pcop->name = Safe_strdup(s);
1325 emitpcode(POC_MOVFW,pcop);
1326 emitpcode(POC_MOVWF,popGet(aop,offset));
1327 } else if(strcmp(s,one)==0) {
1328 emitpcode(POC_CLRF,popGet(aop,offset));
1329 emitpcode(POC_INCF,popGet(aop,offset));
1331 emitpcode(POC_MOVWF,popGet(aop,offset));
1337 if (strcmp(s,"a") == 0)
1338 pic14_emitcode("push","acc");
1340 pic14_emitcode("push","%s",s);
1345 /* if bit variable */
1346 if (!aop->aopu.aop_dir) {
1347 pic14_emitcode("clr","a");
1348 pic14_emitcode("rlc","a");
1351 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1354 pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1357 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1359 lbl = newiTempLabel(NULL);
1361 if (strcmp(s,"a")) {
1364 pic14_emitcode("clr","c");
1365 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1366 pic14_emitcode("cpl","c");
1367 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1368 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1375 if (strcmp(aop->aopu.aop_str[offset],s))
1376 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1380 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1381 "aopPut got unsupported aop->type");
1387 /*-----------------------------------------------------------------*/
1388 /* mov2w_op - generate either a MOVLW or MOVFW based operand type */
1389 /*-----------------------------------------------------------------*/
1390 static void mov2w_op (operand *op, int offset)
1395 /* for PO_IMMEDIATEs: use address or value? */
1396 if (op_isLitLike (op))
1398 /* access address of op */
1399 if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
1400 if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
1402 if (offset == GPTRSIZE-1)
1403 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1405 emitpcode (POC_MOVLW, popGetLit (0));
1408 emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
1410 /* access value stored in op */
1411 mov2w (AOP(op), offset);
1416 /*-----------------------------------------------------------------*/
1417 /* mov2w - generate either a MOVLW or MOVFW based operand type */
1418 /*-----------------------------------------------------------------*/
1419 void mov2w (asmop *aop, int offset)
1425 DEBUGpic14_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
1427 if ( aop_isLitLike (aop) )
1428 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1430 emitpcode(POC_MOVFW,popGet(aop,offset));
1434 static void movwf (asmop *op, int offset)
1436 emitpcode (POC_MOVWF, popGet(op, offset));
1439 static pCodeOp *get_argument_pcop (int idx)
1441 assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1442 return popRegFromIdx (Gstack_base_addr - (idx - 1));
1445 static pCodeOp *get_return_val_pcop (int offset)
1447 assert (offset > 0 && "the most significant byte is returned via WREG");
1448 return popRegFromIdx (Gstack_base_addr - (offset - 1));
1451 static void pass_argument (operand *op, int offset, int idx)
1454 mov2w_op (op, offset);
1456 emitpcode(POC_MOVWF, get_argument_pcop (idx));
1459 static void get_returnvalue (operand *op, int offset, int idx)
1462 emitpcode(POC_MOVFW, get_return_val_pcop (idx));
1463 movwf(AOP(op), offset);
1466 static void call_libraryfunc (char *name)
1470 /* library code might reside in different page... */
1471 emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1472 /* call the library function */
1473 emitpcode (POC_CALL, popGetExternal (name, 0));
1474 /* might return from different page... */
1475 emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1477 /* create symbol, mark it as `extern' */
1478 sym = findSym(SymbolTab, NULL, name);
1480 sym = newSymbol(name, 0);
1481 strncpy(sym->rname, name, SDCC_NAME_MAX);
1482 addSym(SymbolTab, sym, sym->rname, 0, 0, 0);
1483 addSet(&externs, sym);
1488 /*-----------------------------------------------------------------*/
1489 /* pic14_getDataSize - get the operand data size */
1490 /*-----------------------------------------------------------------*/
1491 int pic14_getDataSize(operand *op)
1495 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1498 size = getSize(OP_SYM_ETYPE(op));
1500 //return AOP_SIZE(op);
1502 // tsd- in the pic port, the genptr size is 1, so this code here
1503 // fails. ( in the 8051 port, the size was 4).
1505 size = AOP_SIZE(op);
1506 if (IS_GENPTR(OP_SYM_TYPE(op)))
1508 sym_link *type = operandType(op);
1509 if (IS_GENPTR(type))
1511 /* generic pointer; arithmetic operations
1512 * should ignore the high byte (pointer type).
1515 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1522 /*-----------------------------------------------------------------*/
1523 /* pic14_outAcc - output Acc */
1524 /*-----------------------------------------------------------------*/
1525 void pic14_outAcc(operand *result)
1528 DEBUGpic14_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
1529 DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1532 size = pic14_getDataSize(result);
1534 emitpcode(POC_MOVWF,popGet(AOP(result),0));
1537 /* unsigned or positive */
1539 emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1544 /*-----------------------------------------------------------------*/
1545 /* pic14_outBitC - output a bit C */
1546 /*-----------------------------------------------------------------*/
1547 void pic14_outBitC(operand *result)
1550 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1551 /* if the result is bit */
1552 if (AOP_TYPE(result) == AOP_CRY)
1553 aopPut(AOP(result),"c",0);
1555 pic14_emitcode("clr","a ; %d", __LINE__);
1556 pic14_emitcode("rlc","a");
1557 pic14_outAcc(result);
1561 /*-----------------------------------------------------------------*/
1562 /* pic14_toBoolean - emit code for orl a,operator(sizeop) */
1563 /*-----------------------------------------------------------------*/
1564 void pic14_toBoolean(operand *oper)
1566 int size = AOP_SIZE(oper);
1569 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1574 /* MOVFW does not load the flags... */
1575 emitpcode(POC_MOVLW, popGetLit(0));
1578 emitpcode(POC_MOVFW,popGet(AOP(oper),0));
1582 while (offset < size) {
1583 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
1585 /* Z is set iff (oper == 0) */
1589 /*-----------------------------------------------------------------*/
1590 /* genNot - generate code for ! operation */
1591 /*-----------------------------------------------------------------*/
1592 static void genNot (iCode *ic)
1599 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1600 /* assign asmOps to operand & result */
1601 aopOp (IC_LEFT(ic),ic,FALSE);
1602 aopOp (IC_RESULT(ic),ic,TRUE);
1604 DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1605 /* if in bit space then a special case */
1606 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1607 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1608 emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
1609 emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
1611 emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
1612 emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
1613 emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
1618 size = AOP_SIZE(IC_LEFT(ic));
1619 mov2w (AOP(IC_LEFT(ic)),0);
1622 if (op_isLitLike (IC_LEFT(ic)))
1623 emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
1625 emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
1627 emitpcode(POC_MOVLW, popGetLit (0));
1629 emitpcode(POC_MOVLW, popGetLit (1));
1630 movwf(AOP(IC_RESULT(ic)), 0);
1632 for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
1634 emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
1639 /* release the aops */
1640 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1641 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1645 /*-----------------------------------------------------------------*/
1646 /* genCpl - generate code for complement */
1647 /*-----------------------------------------------------------------*/
1648 static void genCpl (iCode *ic)
1650 operand *left, *result;
1655 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1656 aopOp((left = IC_LEFT(ic)),ic,FALSE);
1657 aopOp((result=IC_RESULT(ic)),ic,TRUE);
1659 /* if both are in bit space then
1661 if (AOP_TYPE(result) == AOP_CRY &&
1662 AOP_TYPE(left) == AOP_CRY ) {
1664 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir);
1665 pic14_emitcode("cpl","c");
1666 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir);
1670 size = AOP_SIZE(result);
1671 if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
1673 emitpcode(POC_COMFW,popGet(AOP(left),offset));
1674 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
1677 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
1681 /* release the aops */
1682 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1683 freeAsmop(result,NULL,ic,TRUE);
1686 /*-----------------------------------------------------------------*/
1687 /* genUminusFloat - unary minus for floating points */
1688 /*-----------------------------------------------------------------*/
1689 static void genUminusFloat(operand *op,operand *result)
1691 int size ,offset =0 ;
1696 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1697 /* for this we just need to flip the
1698 first it then copy the rest in place */
1699 size = AOP_SIZE(op) - 1;
1700 l = aopGet(AOP(op),3,FALSE,FALSE);
1704 pic14_emitcode("cpl","acc.7");
1705 aopPut(AOP(result),"a",3);
1709 aopGet(AOP(op),offset,FALSE,FALSE),
1715 /*-----------------------------------------------------------------*/
1716 /* genUminus - unary minus code generation */
1717 /*-----------------------------------------------------------------*/
1718 static void genUminus (iCode *ic)
1721 sym_link *optype, *rtype;
1725 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1727 aopOp(IC_LEFT(ic),ic,FALSE);
1728 aopOp(IC_RESULT(ic),ic,TRUE);
1730 /* if both in bit space then special
1732 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1733 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1735 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0));
1736 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
1737 emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0));
1742 optype = operandType(IC_LEFT(ic));
1743 rtype = operandType(IC_RESULT(ic));
1745 /* if float then do float stuff */
1746 if (IS_FLOAT(optype)) {
1747 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1751 /* otherwise subtract from zero by taking the 2's complement */
1752 size = AOP_SIZE(IC_LEFT(ic));
1754 for(i=0; i<size; i++) {
1755 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
1756 emitpcode(POC_COMF, popGet(AOP(IC_LEFT(ic)),i));
1758 emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
1759 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
1763 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0));
1764 for(i=1; i<size; i++) {
1766 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),i));
1770 /* release the aops */
1771 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1772 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1775 /*-----------------------------------------------------------------*/
1776 /* saveRegisters - will look for a call and save the registers */
1777 /*-----------------------------------------------------------------*/
1778 static void saveRegisters(iCode *lic)
1786 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1788 for (ic = lic ; ic ; ic = ic->next)
1789 if (ic->op == CALL || ic->op == PCALL)
1793 fprintf(stderr,"found parameter push with no function call\n");
1797 /* if the registers have been saved already then
1799 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
1802 /* find the registers in use at this time
1803 and push them away to safety */
1804 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1809 fprintf(stderr, "ERROR: saveRegisters did not do anything to save registers, please report this as a bug.\n");
1811 dtype = operandType(IC_LEFT(ic));
1812 if (currFunc && dtype &&
1813 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
1814 IFFUNC_ISISR(currFunc->type) &&
1817 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
1820 /*-----------------------------------------------------------------*/
1821 /* unsaveRegisters - pop the pushed registers */
1822 /*-----------------------------------------------------------------*/
1823 static void unsaveRegisters (iCode *ic)
1830 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1831 /* find the registers in use at this time
1832 and push them away to safety */
1833 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1836 if (options.useXstack) {
1837 pic14_emitcode("mov","r0,%s",spname);
1838 for (i = pic14_nRegs ; i >= 0 ; i--) {
1839 if (bitVectBitValue(rsave,i)) {
1840 pic14_emitcode("dec","r0");
1841 pic14_emitcode("movx","a,@r0");
1842 pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
1846 pic14_emitcode("mov","%s,r0",spname);
1848 //for (i = pic14_nRegs ; i >= 0 ; i--) {
1849 // if (bitVectBitValue(rsave,i))
1850 // pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
1856 /*-----------------------------------------------------------------*/
1858 /*-----------------------------------------------------------------*/
1859 static void pushSide(operand * oper, int size)
1863 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1865 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1866 if (AOP_TYPE(oper) != AOP_REG &&
1867 AOP_TYPE(oper) != AOP_DIR &&
1869 pic14_emitcode("mov","a,%s",l);
1870 pic14_emitcode("push","acc");
1872 pic14_emitcode("push","%s",l);
1877 /*-----------------------------------------------------------------*/
1878 /* assignResultValue - */
1879 /*-----------------------------------------------------------------*/
1880 static void assignResultValue(operand * oper)
1882 int size = AOP_SIZE(oper);
1887 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1889 DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
1891 /* assign MSB first (passed via WREG) */
1893 get_returnvalue (oper, size, offset + GpsuedoStkPtr);
1899 /*-----------------------------------------------------------------*/
1900 /* genIpush - genrate code for pushing this gets a little complex */
1901 /*-----------------------------------------------------------------*/
1902 static void genIpush (iCode *ic)
1906 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
1908 int size, offset = 0 ;
1912 /* if this is not a parm push : ie. it is spill push
1913 and spill push is always done on the local stack */
1914 if (!ic->parmPush) {
1916 /* and the item is spilt then do nothing */
1917 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1920 aopOp(IC_LEFT(ic),ic,FALSE);
1921 size = AOP_SIZE(IC_LEFT(ic));
1922 /* push it on the stack */
1924 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1929 pic14_emitcode("push","%s",l);
1934 /* this is a paramter push: in this case we call
1935 the routine to find the call and save those
1936 registers that need to be saved */
1939 /* then do the push */
1940 aopOp(IC_LEFT(ic),ic,FALSE);
1943 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1944 size = AOP_SIZE(IC_LEFT(ic));
1947 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1948 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1949 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1951 pic14_emitcode("mov","a,%s",l);
1952 pic14_emitcode("push","acc");
1954 pic14_emitcode("push","%s",l);
1957 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1961 /*-----------------------------------------------------------------*/
1962 /* genIpop - recover the registers: can happen only for spilling */
1963 /*-----------------------------------------------------------------*/
1964 static void genIpop (iCode *ic)
1968 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
1969 assert (!"genIpop -- unimplemented");
1974 /* if the temp was not pushed then */
1975 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1978 aopOp(IC_LEFT(ic),ic,FALSE);
1979 size = AOP_SIZE(IC_LEFT(ic));
1982 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1985 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1989 /*-----------------------------------------------------------------*/
1990 /* unsaverbank - restores the resgister bank from stack */
1991 /*-----------------------------------------------------------------*/
1992 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1996 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2002 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2004 if (options.useXstack) {
2006 r = getFreePtr(ic,&aop,FALSE);
2009 pic14_emitcode("mov","%s,_spx",r->name);
2010 pic14_emitcode("movx","a,@%s",r->name);
2011 pic14_emitcode("mov","psw,a");
2012 pic14_emitcode("dec","%s",r->name);
2015 pic14_emitcode ("pop","psw");
2018 for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2019 if (options.useXstack) {
2020 pic14_emitcode("movx","a,@%s",r->name);
2021 //pic14_emitcode("mov","(%s+%d),a",
2022 // regspic14[i].base,8*bank+regspic14[i].offset);
2023 pic14_emitcode("dec","%s",r->name);
2026 pic14_emitcode("pop",""); //"(%s+%d)",
2027 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2030 if (options.useXstack) {
2032 pic14_emitcode("mov","_spx,%s",r->name);
2033 freeAsmop(NULL,aop,ic,TRUE);
2039 /*-----------------------------------------------------------------*/
2040 /* saverbank - saves an entire register bank on the stack */
2041 /*-----------------------------------------------------------------*/
2042 static void saverbank (int bank, iCode *ic, bool pushPsw)
2046 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2052 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2053 if (options.useXstack) {
2056 r = getFreePtr(ic,&aop,FALSE);
2057 pic14_emitcode("mov","%s,_spx",r->name);
2061 for (i = 0 ; i < pic14_nRegs ;i++) {
2062 if (options.useXstack) {
2063 pic14_emitcode("inc","%s",r->name);
2064 //pic14_emitcode("mov","a,(%s+%d)",
2065 // regspic14[i].base,8*bank+regspic14[i].offset);
2066 pic14_emitcode("movx","@%s,a",r->name);
2068 pic14_emitcode("push","");// "(%s+%d)",
2069 //regspic14[i].base,8*bank+regspic14[i].offset);
2073 if (options.useXstack) {
2074 pic14_emitcode("mov","a,psw");
2075 pic14_emitcode("movx","@%s,a",r->name);
2076 pic14_emitcode("inc","%s",r->name);
2077 pic14_emitcode("mov","_spx,%s",r->name);
2078 freeAsmop (NULL,aop,ic,TRUE);
2081 pic14_emitcode("push","psw");
2083 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2089 /*-----------------------------------------------------------------*/
2090 /* genCall - generates a call statement */
2091 /*-----------------------------------------------------------------*/
2092 static void genCall (iCode *ic)
2101 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2103 /* if caller saves & we have not saved then */
2107 /* if we are calling a function that is not using
2108 the same register bank then we need to save the
2109 destination registers on the stack */
2110 dtype = operandType(IC_LEFT(ic));
2111 if (currFunc && dtype &&
2112 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2113 IFFUNC_ISISR(currFunc->type) &&
2116 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2118 /* if send set is not empty the assign */
2121 /* For the Pic port, there is no data stack.
2122 * So parameters passed to functions are stored
2123 * in registers. (The pCode optimizer will get
2124 * rid of most of these :).
2126 int psuedoStkPtr=-1;
2127 int firstTimeThruLoop = 1;
2129 _G.sendSet = reverseSet(_G.sendSet);
2131 /* First figure how many parameters are getting passed */
2132 for (sic = setFirstItem(_G.sendSet) ; sic ;
2133 sic = setNextItem(_G.sendSet)) {
2135 aopOp(IC_LEFT(sic),sic,FALSE);
2136 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2137 freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2140 for (sic = setFirstItem(_G.sendSet) ; sic ;
2141 sic = setNextItem(_G.sendSet)) {
2142 int size, offset = 0;
2144 aopOp(IC_LEFT(sic),sic,FALSE);
2145 size = AOP_SIZE(IC_LEFT(sic));
2148 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2149 AopType(AOP_TYPE(IC_LEFT(sic))));
2151 if(!firstTimeThruLoop) {
2152 /* If this is not the first time we've been through the loop
2153 * then we need to save the parameter in a temporary
2154 * register. The last byte of the last parameter is
2156 emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2159 firstTimeThruLoop=0;
2161 mov2w_op (IC_LEFT(sic), offset);
2164 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2169 sym = OP_SYMBOL(IC_LEFT(ic));
2170 name = sym->rname[0] ? sym->rname : sym->name;
2172 * As SDCC emits code as soon as it reaches the end of each
2173 * function's definition, prototyped functions that are implemented
2174 * after the current one are always considered EXTERN, which
2175 * introduces many unneccessary PAGESEL instructions.
2176 * XXX: Use a post pass to iterate over all `CALL _name' statements
2177 * and insert `PAGESEL _name' and `PAGESEL $' around the CALL
2178 * only iff there is no definition of the function in the whole
2179 * file (might include this in the PAGESEL pass).
2181 isExtern = IS_EXTERN(sym->etype) || pic14_inISR;
2183 /* Extern functions and ISRs maybe on a different page;
2184 * must call pagesel */
2185 emitpcode(POC_PAGESEL,popGetWithString(name,1));
2187 emitpcode(POC_CALL,popGetWithString(name,isExtern));
2189 /* May have returned from a different page;
2190 * must use pagesel to restore PCLATH before next
2191 * goto or call instruction */
2192 emitpcode(POC_PAGESEL,popGetWithString("$",0));
2195 /* if we need assign a result value */
2196 if ((IS_ITEMP(IC_RESULT(ic)) &&
2197 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2198 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2199 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2202 aopOp(IC_RESULT(ic),ic,FALSE);
2205 assignResultValue(IC_RESULT(ic));
2207 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2208 AopType(AOP_TYPE(IC_RESULT(ic))));
2210 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2213 /* if register bank was saved then pop them */
2215 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2217 /* if we hade saved some registers then unsave them */
2218 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2219 unsaveRegisters (ic);
2224 /*-----------------------------------------------------------------*/
2225 /* genPcall - generates a call by pointer statement */
2226 /*-----------------------------------------------------------------*/
2227 static void genPcall (iCode *ic)
2230 symbol *albl = newiTempLabel(NULL);
2231 symbol *blbl = newiTempLabel(NULL);
2238 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2239 /* if caller saves & we have not saved then */
2243 /* if we are calling a function that is not using
2244 the same register bank then we need to save the
2245 destination registers on the stack */
2246 dtype = operandType(IC_LEFT(ic));
2247 if (currFunc && dtype &&
2248 IFFUNC_ISISR(currFunc->type) &&
2249 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2250 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2253 aopOp(left,ic,FALSE);
2254 DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2256 poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2258 pushSide(IC_LEFT(ic), FPTRSIZE);
2260 /* if send set is not empty, assign parameters */
2263 DEBUGpic14_emitcode ("; ***","%s %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2264 /* no way to pass args - W always gets used to make the call */
2266 /* first idea - factor out a common helper function and call it.
2267 But don't know how to get it generated only once in its own block
2269 if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2272 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2273 DEBUGpic14_emitcode ("; ***","%s %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2274 buffer = Safe_calloc(1,strlen(rname)+16);
2275 sprintf(buffer, "%s_goto_helper", rname);
2276 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2280 emitpcode(POC_CALL,popGetLabel(albl->key));
2281 pcop = popGetLabel(blbl->key);
2282 emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
2283 emitpcode(POC_GOTO,pcop);
2284 emitpLabel(albl->key);
2286 emitpcode(poc,popGetAddr(AOP(left),1,0));
2287 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2288 emitpcode(poc,popGetAddr(AOP(left),0,0));
2289 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2291 emitpLabel(blbl->key);
2293 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2295 /* if we need to assign a result value */
2296 if ((IS_ITEMP(IC_RESULT(ic)) &&
2297 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2298 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2299 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2302 aopOp(IC_RESULT(ic),ic,FALSE);
2307 assignResultValue(IC_RESULT(ic));
2309 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2312 /* if register bank was saved then unsave them */
2313 if (currFunc && dtype &&
2314 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2315 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2317 /* if we hade saved some registers then
2320 unsaveRegisters (ic);
2324 /*-----------------------------------------------------------------*/
2325 /* resultRemat - result is rematerializable */
2326 /*-----------------------------------------------------------------*/
2327 static int resultRemat (iCode *ic)
2329 // DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2332 if (SKIP_IC(ic) || ic->op == IFX)
2335 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2336 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2337 if (sym->remat && !POINTER_SET(ic))
2345 /*-----------------------------------------------------------------*/
2346 /* inExcludeList - return 1 if the string is in exclude Reg list */
2347 /*-----------------------------------------------------------------*/
2348 static bool inExcludeList(char *s)
2350 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2353 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2354 if (options.excludeRegs[i] &&
2355 STRCASECMP(options.excludeRegs[i],"none") == 0)
2358 for ( i = 0 ; options.excludeRegs[i]; i++) {
2359 if (options.excludeRegs[i] &&
2360 STRCASECMP(s,options.excludeRegs[i]) == 0)
2367 /*-----------------------------------------------------------------*/
2368 /* genFunction - generated code for function entry */
2369 /*-----------------------------------------------------------------*/
2370 static void genFunction (iCode *ic)
2377 DEBUGpic14_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2379 labelOffset += (max_key+4);
2383 /* create the function header */
2384 pic14_emitcode(";","-----------------------------------------");
2385 pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2386 pic14_emitcode(";","-----------------------------------------");
2388 /* prevent this symbol from being emitted as 'extern' */
2389 pic14_stringInSet(sym->rname, &pic14_localFunctions, 1);
2391 pic14_emitcode("","%s:",sym->rname);
2392 addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2394 /* mark symbol as NOT extern (even if it was declared so previously) */
2395 assert(IS_SPEC(sym->etype));
2396 SPEC_EXTR(sym->etype) = 0;
2398 if (!SPEC_OCLS(sym->etype)) SPEC_OCLS(sym->etype) = code;
2399 addSetIfnotP(&SPEC_OCLS(sym->etype)->syms, sym);
2401 ftype = operandType(IC_LEFT(ic));
2403 /* if critical function then turn interrupts off */
2404 if (IFFUNC_ISCRITICAL(ftype))
2405 pic14_emitcode("clr","ea");
2407 /* here we need to generate the equates for the
2408 register bank if required */
2410 if (FUNC_REGBANK(ftype) != rbank) {
2413 rbank = FUNC_REGBANK(ftype);
2414 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2415 if (strcmp(regspic14[i].base,"0") == 0)
2416 pic14_emitcode("","%s = 0x%02x",
2418 8*rbank+regspic14[i].offset);
2420 pic14_emitcode ("","%s = %s + 0x%02x",
2423 8*rbank+regspic14[i].offset);
2428 /* if this is an interrupt service routine */
2430 if (IFFUNC_ISISR(sym->type)) {
2432 emitpcode(POC_MOVWF, popCopyReg(&pc_wsave));
2433 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2434 /* XXX: Why? Does this assume that ssave and psave reside
2435 * in a shared bank or bank0? We cannot guarantee the
2438 emitpcode(POC_CLRF, popCopyReg(&pc_status));
2439 emitpcode(POC_MOVWF, popCopyReg(&pc_ssave));
2440 //emitpcode(POC_MOVWF, popGetExternal("___sdcc_saved_status",1 ));
2441 emitpcode(POC_MOVFW, popCopyReg(&pc_pclath));
2442 /* during an interrupt PCLATH must be cleared before a goto or call statement */
2443 emitpcode(POC_CLRF, popCopyReg(&pc_pclath));
2444 emitpcode(POC_MOVWF, popCopyReg(&pc_psave));
2445 //emitpcode(POC_MOVWF, popGetExternal("___sdcc_saved_pclath", 1));
2446 emitpcode(POC_MOVFW, popCopyReg(&pc_fsr));
2447 emitpcode(POC_MOVWF, popGetExternal("___sdcc_saved_fsr", 1));
2449 pBlockConvert2ISR(pb);
2450 pic14_hasInterrupt = 1;
2452 /* if callee-save to be used for this function
2453 then save the registers being used in this function */
2454 if (IFFUNC_CALLEESAVES(sym->type)) {
2457 /* if any registers used */
2458 if (sym->regsUsed) {
2459 /* save the registers used */
2460 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2461 if (bitVectBitValue(sym->regsUsed,i)) {
2462 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2470 /* set the register bank to the desired value */
2471 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2472 pic14_emitcode("push","psw");
2473 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);
2476 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2478 if (options.useXstack) {
2479 pic14_emitcode("mov","r0,%s",spname);
2480 pic14_emitcode("mov","a,_bp");
2481 pic14_emitcode("movx","@r0,a");
2482 pic14_emitcode("inc","%s",spname);
2486 /* set up the stack */
2487 pic14_emitcode ("push","_bp"); /* save the callers stack */
2489 pic14_emitcode ("mov","_bp,%s",spname);
2492 /* adjust the stack for the function */
2497 werror(W_STACK_OVERFLOW,sym->name);
2499 if (i > 3 && sym->recvSize < 4) {
2501 pic14_emitcode ("mov","a,sp");
2502 pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2503 pic14_emitcode ("mov","sp,a");
2508 pic14_emitcode("inc","sp");
2513 pic14_emitcode ("mov","a,_spx");
2514 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2515 pic14_emitcode ("mov","_spx,a");
2520 /*-----------------------------------------------------------------*/
2521 /* genEndFunction - generates epilogue for functions */
2522 /*-----------------------------------------------------------------*/
2523 static void genEndFunction (iCode *ic)
2525 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2529 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2531 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2533 pic14_emitcode ("mov","%s,_bp",spname);
2536 /* if use external stack but some variables were
2537 added to the local stack then decrement the
2539 if (options.useXstack && sym->stack) {
2540 pic14_emitcode("mov","a,sp");
2541 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2542 pic14_emitcode("mov","sp,a");
2546 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2547 if (options.useXstack) {
2548 pic14_emitcode("mov","r0,%s",spname);
2549 pic14_emitcode("movx","a,@r0");
2550 pic14_emitcode("mov","_bp,a");
2551 pic14_emitcode("dec","%s",spname);
2555 pic14_emitcode ("pop","_bp");
2559 /* restore the register bank */
2560 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2561 pic14_emitcode ("pop","psw");
2563 if (IFFUNC_ISISR(sym->type)) {
2565 /* now we need to restore the registers */
2566 /* if this isr has no bank i.e. is going to
2567 run with bank 0 , then we need to save more
2569 if (!FUNC_REGBANK(sym->type)) {
2571 /* if this function does not call any other
2572 function then we can be economical and
2573 save only those registers that are used */
2574 if (! IFFUNC_HASFCALL(sym->type)) {
2577 /* if any registers used */
2578 if (sym->regsUsed) {
2579 /* save the registers used */
2580 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2581 if (bitVectBitValue(sym->regsUsed,i)) {
2582 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2588 /* this function has a function call; cannot
2589 determines register usage so we will have the
2591 unsaverbank(0,ic,FALSE);
2595 /* if debug then send end of function */
2596 if (options.debug && debugFile && currFunc) {
2597 debugFile->writeEndFunction (currFunc, ic, 1);
2600 emitpcode(POC_MOVFW, popGetExternal("___sdcc_saved_fsr", 1));
2601 emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
2602 //emitpcode(POC_MOVFW, popGetExternal("___sdcc_saved_pclath", 1));
2603 emitpcode(POC_MOVFW, popCopyReg(&pc_psave));
2604 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
2605 emitpcode(POC_CLRF, popCopyReg(&pc_status)); // see genFunction
2606 //emitpcode(POC_SWAPFW, popGetExternal("___sdcc_saved_status", 1));
2607 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
2608 emitpcode(POC_MOVWF, popCopyReg(&pc_status));
2609 emitpcode(POC_SWAPF, popCopyReg(&pc_wsave));
2610 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
2611 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
2612 emitpcodeNULLop(POC_RETFIE);
2615 if (IFFUNC_ISCRITICAL(sym->type))
2616 pic14_emitcode("setb","ea");
2618 if (IFFUNC_CALLEESAVES(sym->type)) {
2621 /* if any registers used */
2622 if (sym->regsUsed) {
2623 /* save the registers used */
2624 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2625 if (bitVectBitValue(sym->regsUsed,i)) {
2626 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2632 /* if debug then send end of function */
2633 if (options.debug && debugFile && currFunc) {
2634 debugFile->writeEndFunction (currFunc, ic, 1);
2637 pic14_emitcode ("return","");
2638 emitpcodeNULLop(POC_RETURN);
2640 /* Mark the end of a function */
2641 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
2646 /*-----------------------------------------------------------------*/
2647 /* genRet - generate code for return statement */
2648 /*-----------------------------------------------------------------*/
2649 static void genRet (iCode *ic)
2651 int size,offset = 0;
2655 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2656 /* if we have no return value then
2657 just generate the "ret" */
2661 /* we have something to return then
2662 move the return value into place */
2663 aopOp(IC_LEFT(ic),ic,FALSE);
2664 size = AOP_SIZE(IC_LEFT(ic));
2666 for (offset = 0; offset < size; offset++)
2668 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
2671 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2674 /* generate a jump to the return label
2675 if the next is not the return statement */
2676 if (!(ic->next && ic->next->op == LABEL &&
2677 IC_LABEL(ic->next) == returnLabel)) {
2679 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
2684 /*-----------------------------------------------------------------*/
2685 /* genLabel - generates a label */
2686 /*-----------------------------------------------------------------*/
2687 static void genLabel (iCode *ic)
2691 /* special case never generate */
2692 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2693 if (IC_LABEL(ic) == entryLabel)
2696 emitpLabel(IC_LABEL(ic)->key);
2697 pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
2700 /*-----------------------------------------------------------------*/
2701 /* genGoto - generates a goto */
2702 /*-----------------------------------------------------------------*/
2704 static void genGoto (iCode *ic)
2708 emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
2709 pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
2713 /*-----------------------------------------------------------------*/
2714 /* genMultbits :- multiplication of bits */
2715 /*-----------------------------------------------------------------*/
2716 static void genMultbits (operand *left,
2721 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2723 if(!pic14_sameRegs(AOP(result),AOP(right)))
2724 emitpcode(POC_BSF, popGet(AOP(result),0));
2726 emitpcode(POC_BTFSC,popGet(AOP(right),0));
2727 emitpcode(POC_BTFSS,popGet(AOP(left),0));
2728 emitpcode(POC_BCF, popGet(AOP(result),0));
2733 /*-----------------------------------------------------------------*/
2734 /* genMultOneByte : 8 bit multiplication & division */
2735 /*-----------------------------------------------------------------*/
2736 static void genMultOneByte (operand *left,
2740 char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
2748 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2749 DEBUGpic14_AopType(__LINE__,left,right,result);
2750 DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
2752 /* (if two literals, the value is computed before) */
2753 /* if one literal, literal on the right */
2754 if (AOP_TYPE(left) == AOP_LIT){
2760 assert (AOP_SIZE(left) == AOP_SIZE(right));
2762 size = min(AOP_SIZE(result),AOP_SIZE(left));
2763 offset = Gstack_base_addr - (2*size - 1);
2765 /* pass right operand as argument */
2766 for (i=0; i < size; i++)
2768 mov2w (AOP(right), i);
2769 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
2772 /* pass left operand as argument */
2773 for (i=0; i < size; i++)
2775 mov2w (AOP(left), i);
2776 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
2778 assert (offset == Gstack_base_addr);
2780 /* call library routine */
2781 assert (size > 0 && size <= 4);
2782 call_libraryfunc (func[size]);
2785 movwf (AOP(result), size-1);
2786 for (i=0; i < size - 1; i++)
2788 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
2789 movwf (AOP(result), size - 2 - i);
2792 /* now (zero-/sign) extend the result to its size */
2793 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2796 /*-----------------------------------------------------------------*/
2797 /* genMult - generates code for multiplication */
2798 /*-----------------------------------------------------------------*/
2799 static void genMult (iCode *ic)
2801 operand *left = IC_LEFT(ic);
2802 operand *right = IC_RIGHT(ic);
2803 operand *result= IC_RESULT(ic);
2807 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2808 /* assign the amsops */
2809 aopOp (left,ic,FALSE);
2810 aopOp (right,ic,FALSE);
2811 aopOp (result,ic,TRUE);
2813 DEBUGpic14_AopType(__LINE__,left,right,result);
2815 /* special cases first */
2817 if (AOP_TYPE(left) == AOP_CRY &&
2818 AOP_TYPE(right)== AOP_CRY) {
2819 genMultbits(left,right,result);
2823 /* if both are of size == 1 */
2824 if (AOP_SIZE(left) == 1 &&
2825 AOP_SIZE(right) == 1 ) {
2826 genMultOneByte(left,right,result);
2830 /* should have been converted to function call */
2834 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2835 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2836 freeAsmop(result,NULL,ic,TRUE);
2839 /*-----------------------------------------------------------------*/
2840 /* genDivbits :- division of bits */
2841 /*-----------------------------------------------------------------*/
2842 static void genDivbits (operand *left,
2851 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2852 /* the result must be bit */
2853 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
2854 l = aopGet(AOP(left),0,FALSE,FALSE);
2858 pic14_emitcode("div","ab");
2859 pic14_emitcode("rrc","a");
2860 aopPut(AOP(result),"c",0);
2863 /*-----------------------------------------------------------------*/
2864 /* genDivOneByte : 8 bit division */
2865 /*-----------------------------------------------------------------*/
2866 static void genDivOneByte (operand *left,
2874 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2876 assert (AOP_SIZE(right) == 1);
2877 assert (AOP_SIZE(left) == 1);
2879 size = min(AOP_SIZE(result),AOP_SIZE(left));
2880 sign = !(SPEC_USIGN(operandType(left))
2881 && SPEC_USIGN(operandType(right)));
2883 if (AOP_TYPE(right) == AOP_LIT)
2885 /* XXX: might add specialized code */
2890 /* unsigned division */
2892 mov2w(AOP(right),0);
2893 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
2895 call_libraryfunc("__divuchar");
2896 movwf(AOP(result),0);
2901 temp = popGetTempReg();
2902 lbl = newiTempLabel(NULL);
2904 /* XXX: improve this naive approach:
2905 [result] = [a] / [b]
2906 ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
2910 movwf temp // temp <-- left
2911 movf right,W // W <-- right
2915 subwf temp,F // temp <-- temp - W
2916 skipNC // subwf clears CARRY (i.e. sets BORROW) if temp < W
2918 decf result // we just subtract once too often
2921 /* XXX: This loops endlessly on DIVIDE BY ZERO */
2922 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
2925 emitpcode(POC_MOVWF, temp);
2926 mov2w(AOP(right),0);
2927 emitpcode(POC_CLRF, popGet(AOP(result),0));
2929 emitpLabel(lbl->key);
2930 emitpcode(POC_INCF, popGet(AOP(result),0));
2931 emitpcode(POC_SUBWF, temp);
2933 emitpcode(POC_GOTO, popGetLabel(lbl->key));
2934 emitpcode(POC_DECF, popGet(AOP(result),0));
2935 popReleaseTempReg(temp);
2940 /* signed division */
2941 mov2w(AOP(right),0);
2942 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
2944 call_libraryfunc("__divschar");
2945 movwf(AOP(result),0);
2948 /* now performed the signed/unsigned division -- extend result */
2949 addSign(result, 1, sign);
2952 /*-----------------------------------------------------------------*/
2953 /* genDiv - generates code for division */
2954 /*-----------------------------------------------------------------*/
2955 static void genDiv (iCode *ic)
2957 operand *left = IC_LEFT(ic);
2958 operand *right = IC_RIGHT(ic);
2959 operand *result= IC_RESULT(ic);
2962 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2963 /* assign the amsops */
2964 aopOp (left,ic,FALSE);
2965 aopOp (right,ic,FALSE);
2966 aopOp (result,ic,TRUE);
2968 /* special cases first */
2970 if (AOP_TYPE(left) == AOP_CRY &&
2971 AOP_TYPE(right)== AOP_CRY) {
2972 genDivbits(left,right,result);
2976 /* if both are of size == 1 */
2977 if (AOP_SIZE(left) == 1 &&
2978 AOP_SIZE(right) == 1 ) {
2979 genDivOneByte(left,right,result);
2983 /* should have been converted to function call */
2986 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2987 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2988 freeAsmop(result,NULL,ic,TRUE);
2991 /*-----------------------------------------------------------------*/
2992 /* genModOneByte : 8 bit modulus */
2993 /*-----------------------------------------------------------------*/
2994 static void genModOneByte (operand *left,
3002 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3004 assert (AOP_SIZE(right) == 1);
3005 assert (AOP_SIZE(left) == 1);
3007 size = min(AOP_SIZE(result),AOP_SIZE(left));
3008 sign = !(SPEC_USIGN(operandType(left))
3009 && SPEC_USIGN(operandType(right)));
3011 if (AOP_TYPE(right) == AOP_LIT)
3013 /* XXX: might add specialized code */
3018 /* unsigned division */
3020 mov2w(AOP(right),0);
3021 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3023 call_libraryfunc("__moduchar");
3024 movwf(AOP(result),0);
3029 lbl = newiTempLabel(NULL);
3031 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3033 /* XXX: improve this naive approach:
3034 [result] = [a] % [b]
3035 ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3039 movwf result // result <-- left
3040 movf right,W // W <-- right
3042 subwf result,F // result <-- result - W
3043 skipNC // subwf clears CARRY (i.e. sets BORROW) if result < W
3045 addwf result, F // we just subtract once too often
3048 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3049 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3051 if (!pic14_sameRegs(AOP(left), AOP(result)))
3054 emitpcode(POC_MOVWF, popGet(AOP(result),0));
3056 mov2w(AOP(right),0);
3058 emitpLabel(lbl->key);
3059 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3061 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3062 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3067 /* signed division */
3068 mov2w(AOP(right),0);
3069 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3071 call_libraryfunc("__modschar");
3072 movwf(AOP(result),0);
3075 /* now we performed the signed/unsigned modulus -- extend result */
3076 addSign(result, 1, sign);
3079 /*-----------------------------------------------------------------*/
3080 /* genMod - generates code for division */
3081 /*-----------------------------------------------------------------*/
3082 static void genMod (iCode *ic)
3084 operand *left = IC_LEFT(ic);
3085 operand *right = IC_RIGHT(ic);
3086 operand *result= IC_RESULT(ic);
3089 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3090 /* assign the amsops */
3091 aopOp (left,ic,FALSE);
3092 aopOp (right,ic,FALSE);
3093 aopOp (result,ic,TRUE);
3095 /* if both are of size == 1 */
3096 if (AOP_SIZE(left) == 1 &&
3097 AOP_SIZE(right) == 1 ) {
3098 genModOneByte(left,right,result);
3102 /* should have been converted to function call */
3106 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3107 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3108 freeAsmop(result,NULL,ic,TRUE);
3111 /*-----------------------------------------------------------------*/
3112 /* genIfxJump :- will create a jump depending on the ifx */
3113 /*-----------------------------------------------------------------*/
3115 note: May need to add parameter to indicate when a variable is in bit space.
3117 static void genIfxJump (iCode *ic, char *jval)
3121 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3122 /* if true label then we jump if condition
3124 if ( IC_TRUE(ic) ) {
3126 if(strcmp(jval,"a") == 0)
3128 else if (strcmp(jval,"c") == 0)
3131 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3132 emitpcode(POC_BTFSC, newpCodeOpBit(jval,-1,1));
3135 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3136 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3140 /* false label is present */
3141 if(strcmp(jval,"a") == 0)
3143 else if (strcmp(jval,"c") == 0)
3146 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3147 emitpcode(POC_BTFSS, newpCodeOpBit(jval,-1,1));
3150 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3151 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3156 /* mark the icode as generated */
3161 /*-----------------------------------------------------------------*/
3163 /*-----------------------------------------------------------------*/
3164 static void genSkip(iCode *ifx,int status_bit)
3170 if ( IC_TRUE(ifx) ) {
3171 switch(status_bit) {
3186 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3187 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3191 switch(status_bit) {
3205 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3206 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3213 /*-----------------------------------------------------------------*/
3215 /*-----------------------------------------------------------------*/
3216 static void genSkipc(resolvedIfx *rifx)
3227 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3228 emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3229 rifx->generated = 1;
3233 /*-----------------------------------------------------------------*/
3235 /*-----------------------------------------------------------------*/
3236 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3242 if( (rifx->condition ^ invert_condition) & 1)
3247 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3248 rifx->generated = 1;
3253 /*-----------------------------------------------------------------*/
3255 /*-----------------------------------------------------------------*/
3256 static void genSkipz(iCode *ifx, int condition)
3259 assert (ifx != NULL);
3267 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3269 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3272 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3274 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3280 /*-----------------------------------------------------------------*/
3282 /*-----------------------------------------------------------------*/
3283 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3290 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3292 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3295 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3296 rifx->generated = 1;
3301 /*-----------------------------------------------------------------*/
3302 /* genChkZeroes :- greater or less than comparison */
3303 /* For each byte in a literal that is zero, inclusive or the */
3304 /* the corresponding byte in the operand with W */
3305 /* returns true if any of the bytes are zero */
3306 /*-----------------------------------------------------------------*/
3307 static int genChkZeroes(operand *op, int lit, int size)
3314 i = (lit >> (size*8)) & 0xff;
3318 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3320 emitpcode(POC_IORFW, popGet(AOP(op),size));
3330 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3331 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
3332 #define DEBUGpc emitpComment
3334 /*-----------------------------------------------------------------*/
3335 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
3336 /* aop (if it's NOT a literal) or from lit (if */
3337 /* aop is a literal) */
3338 /*-----------------------------------------------------------------*/
3339 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3340 if (aop->type == AOP_LIT) {
3341 emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3343 emitpcode (POC_MOVFW, popGet (aop, offset));
3347 /* genCmp performs a left < right comparison, stores
3348 * the outcome in result (if != NULL) and generates
3349 * control flow code for the ifx (if != NULL).
3351 * This version leaves in sequences like
3352 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3353 * which should be optmized by the peephole
3354 * optimizer - RN 2005-01-01 */
3355 static void genCmp (operand *left,operand *right,
3356 operand *result, iCode *ifx, int sign)
3366 int invert_result = 0;
3370 assert (AOP_SIZE(left) == AOP_SIZE(right));
3371 assert (left && right);
3373 size = AOP_SIZE(right) - 1;
3374 mask = (0x100UL << (size*8)) - 1;
3375 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3380 resolveIfx (&rIfx, ifx);
3382 /**********************************************************************
3383 * handle bits - bit compares are promoted to int compares seemingly! *
3384 **********************************************************************/
3386 // THIS IS COMPLETELY UNTESTED!
3387 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3388 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3389 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3390 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3393 // 1 < {0,1} is false --> clear C by skipping the next instruction
3394 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3395 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3396 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3397 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3398 emitCLRC; // only skipped for left=0 && right=1
3400 goto correct_result_in_carry;
3404 /*************************************************
3405 * make sure that left is register (or the like) *
3406 *************************************************/
3407 if (!isAOP_REGlike(left)) {
3408 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
3409 assert (isAOP_LIT(left));
3410 assert (isAOP_REGlike(right));
3411 // swap left and right
3412 // left < right <==> right > left <==> (right >= left + 1)
3413 lit = ulFromVal(AOP(left)->aopu.aop_lit);
3415 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
3416 // MAXVALUE < right? always false
3417 if (performedLt) emitCLRC; else emitSETC;
3418 goto correct_result_in_carry;
3421 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
3422 // that's why we handled it above.
3429 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
3430 } else if (isAOP_LIT(right)) {
3431 lit = ulFromVal(AOP(right)->aopu.aop_lit);
3434 assert (isAOP_REGlike(left)); // left must be register or the like
3435 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
3437 /*************************************************
3438 * special cases go here *
3439 *************************************************/
3441 if (isAOP_LIT(right)) {
3443 // unsigned comparison to a literal
3444 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
3446 // unsigned left < 0? always false
3447 if (performedLt) emitCLRC; else emitSETC;
3448 goto correct_result_in_carry;
3451 // signed comparison to a literal
3452 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
3453 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
3454 // signed left < 0x80000000? always false
3455 if (performedLt) emitCLRC; else emitSETC;
3456 goto correct_result_in_carry;
3457 } else if (lit == 0) {
3458 // compare left < 0; set CARRY if SIGNBIT(left) is set
3459 if (performedLt) emitSETC; else emitCLRC;
3460 emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
3461 if (performedLt) emitCLRC; else emitSETC;
3462 goto correct_result_in_carry;
3465 } // right is literal
3467 /*************************************************
3468 * perform a general case comparison *
3469 * make sure we get CARRY==1 <==> left >= right *
3470 *************************************************/
3471 // compare most significant bytes
3472 //DEBUGpc ("comparing bytes at offset %d", size);
3474 // unsigned comparison
3475 pic14_mov2w_regOrLit (AOP(right), lit, size);
3476 emitpcode (POC_SUBFW, popGet (AOP(left), size));
3478 // signed comparison
3479 // (add 2^n to both operands then perform an unsigned comparison)
3480 if (isAOP_LIT(right)) {
3481 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
3482 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
3484 if (litbyte == 0x80) {
3485 // left >= 0x80 -- always true, but more bytes to come
3486 mov2w (AOP(left), size);
3487 emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
3490 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
3491 mov2w (AOP(left), size);
3492 emitpcode (POC_ADDLW, popGetLit (0x80));
3493 emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
3496 pCodeOp *pctemp = popGetTempReg();
3497 mov2w (AOP(left), size);
3498 emitpcode (POC_ADDLW, popGetLit (0x80));
3499 emitpcode (POC_MOVWF, pctemp);
3500 mov2w (AOP(right), size);
3501 emitpcode (POC_ADDLW, popGetLit (0x80));
3502 emitpcode (POC_SUBFW, pctemp);
3503 popReleaseTempReg(pctemp);
3507 // compare remaining bytes (treat as unsigned case from above)
3508 templbl = newiTempLabel ( NULL );
3511 //DEBUGpc ("comparing bytes at offset %d", offs);
3513 emitpcode (POC_GOTO, popGetLabel (templbl->key));
3514 pic14_mov2w_regOrLit (AOP(right), lit, offs);
3515 emitpcode (POC_SUBFW, popGet (AOP(left), offs));
3517 emitpLabel (templbl->key);
3518 goto result_in_carry;
3522 /****************************************************
3523 * now CARRY contains the result of the comparison: *
3524 * SUBWF sets CARRY iff *
3525 * F-W >= 0 <==> F >= W <==> !(F < W) *
3526 * (F=left, W=right) *
3527 ****************************************************/
3531 // value will be used in the following genSkipc()
3532 rIfx.condition ^= 1;
3535 correct_result_in_carry:
3537 // assign result to variable (if neccessary)
3538 if (result && AOP_TYPE(result) != AOP_CRY) {
3539 //DEBUGpc ("assign result");
3540 size = AOP_SIZE(result);
3542 emitpcode (POC_CLRF, popGet (AOP(result), size));
3544 if (invert_result) {
3546 emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
3548 emitpcode (POC_RLF, popGet (AOP(result), 0));
3552 // perform conditional jump
3554 //DEBUGpc ("generate control flow");
3562 /* OLD VERSION -- BUGGY, DO NOT USE */
3564 /*-----------------------------------------------------------------*/
3565 /* genCmp :- greater or less than comparison */
3566 /*-----------------------------------------------------------------*/
3567 static void genCmp (operand *left,operand *right,
3568 operand *result, iCode *ifx, int sign)
3570 int size; //, offset = 0 ;
3571 unsigned long lit = 0L,i = 0;
3572 resolvedIfx rFalseIfx;
3573 // resolvedIfx rTrueIfx;
3577 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3580 DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
3581 DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
3585 resolveIfx(&rFalseIfx,ifx);
3586 truelbl = newiTempLabel(NULL);
3587 size = max(AOP_SIZE(left),AOP_SIZE(right));
3589 DEBUGpic14_AopType(__LINE__,left,right,result);
3593 /* if literal is on the right then swap with left */
3594 if ((AOP_TYPE(right) == AOP_LIT)) {
3595 operand *tmp = right ;
3596 unsigned long mask = (0x100 << (8*(size-1))) - 1;
3597 lit = ulFromVal(AOP(right)->aopu.aop_lit);
3600 lit = (lit - 1) & mask;
3603 rFalseIfx.condition ^= 1;
3606 } else if ((AOP_TYPE(left) == AOP_LIT)) {
3607 lit = ulFromVal(AOP(left)->aopu.aop_lit);
3611 //if(IC_TRUE(ifx) == NULL)
3612 /* if left & right are bit variables */
3613 if (AOP_TYPE(left) == AOP_CRY &&
3614 AOP_TYPE(right) == AOP_CRY ) {
3615 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3616 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3618 /* subtract right from left if at the
3619 end the carry flag is set then we know that
3620 left is greater than right */
3622 symbol *lbl = newiTempLabel(NULL);
3625 if(AOP_TYPE(right) == AOP_LIT) {
3627 //lit = ulFromVal(AOP(right)->aopu.aop_lit);
3629 DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
3636 genSkipCond(&rFalseIfx,left,size-1,7);
3638 /* no need to compare to 0...*/
3639 /* NOTE: this is a de-generate compare that most certainly
3640 * creates some dead code. */
3641 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3643 if(ifx) ifx->generated = 1;
3650 //i = (lit >> (size*8)) & 0xff;
3651 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3653 emitpcode(POC_MOVFW, popGet(AOP(left),size));
3655 i = ((0-lit) & 0xff);
3658 /* lit is 0x7f, all signed chars are less than
3659 * this except for 0x7f itself */
3660 emitpcode(POC_XORLW, popGetLit(0x7f));
3661 genSkipz2(&rFalseIfx,0);
3663 emitpcode(POC_ADDLW, popGetLit(0x80));
3664 emitpcode(POC_ADDLW, popGetLit(i^0x80));
3665 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
3670 genSkipz2(&rFalseIfx,1);
3672 emitpcode(POC_ADDLW, popGetLit(i));
3673 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
3677 if(ifx) ifx->generated = 1;
3681 /* chars are out of the way. now do ints and longs */
3684 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3691 genSkipCond(&rFalseIfx,left,size,7);
3692 if(ifx) ifx->generated = 1;
3697 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3699 //rFalseIfx.condition ^= 1;
3700 //genSkipCond(&rFalseIfx,left,size,7);
3701 //rFalseIfx.condition ^= 1;
3703 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3704 if(rFalseIfx.condition)
3705 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
3707 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
3709 emitpcode(POC_MOVLW, popGetLit(0x100-lit));
3710 emitpcode(POC_ADDFW, popGet(AOP(left),0));
3711 emitpcode(POC_MOVFW, popGet(AOP(left),1));
3714 emitpcode(POC_IORFW, popGet(AOP(left),size--));
3716 if(rFalseIfx.condition) {
3718 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
3724 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
3725 emitpLabel(truelbl->key);
3726 if(ifx) ifx->generated = 1;
3733 if( (lit & 0xff) == 0) {
3734 /* lower byte is zero */
3735 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3736 i = ((lit >> 8) & 0xff) ^0x80;
3737 emitpcode(POC_MOVFW, popGet(AOP(left),size));
3738 emitpcode(POC_ADDLW, popGetLit( 0x80));
3739 emitpcode(POC_ADDLW, popGetLit(0x100-i));
3740 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
3743 if(ifx) ifx->generated = 1;
3748 /* Special cases for signed longs */
3749 if( (lit & 0xffffff) == 0) {
3750 /* lower byte is zero */
3751 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3752 i = ((lit >> 8*3) & 0xff) ^0x80;
3753 emitpcode(POC_MOVFW, popGet(AOP(left),size));
3754 emitpcode(POC_ADDLW, popGetLit( 0x80));
3755 emitpcode(POC_ADDLW, popGetLit(0x100-i));
3756 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
3759 if(ifx) ifx->generated = 1;
3767 if(lit & (0x80 << (size*8))) {
3768 /* lit is negative */
3769 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3771 //genSkipCond(&rFalseIfx,left,size,7);
3773 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3775 if(rFalseIfx.condition)
3776 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
3778 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
3782 /* lit is positive */
3783 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3784 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3785 if(rFalseIfx.condition)
3786 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
3788 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
3792 /* There are no more special cases, so perform a general compare */
3794 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3795 emitpcode(POC_SUBFW, popGet(AOP(left),size));
3799 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3801 emitpcode(POC_SUBFW, popGet(AOP(left),size));
3803 //rFalseIfx.condition ^= 1;
3804 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
3806 emitpLabel(truelbl->key);
3808 if(ifx) ifx->generated = 1;
3815 /* sign is out of the way. So now do an unsigned compare */
3816 DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
3819 /* General case - compare to an unsigned literal on the right.*/
3821 i = (lit >> (size*8)) & 0xff;
3822 emitpcode(POC_MOVLW, popGetLit(i));
3823 emitpcode(POC_SUBFW, popGet(AOP(left),size));
3825 i = (lit >> (size*8)) & 0xff;
3828 emitpcode(POC_MOVLW, popGetLit(i));
3830 emitpcode(POC_SUBFW, popGet(AOP(left),size));
3832 /* this byte of the lit is zero,
3833 *if it's not the last then OR in the variable */
3835 emitpcode(POC_IORFW, popGet(AOP(left),size));
3840 emitpLabel(lbl->key);
3841 //if(emitFinalCheck)
3842 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
3844 emitpLabel(truelbl->key);
3846 if(ifx) ifx->generated = 1;
3853 if(AOP_TYPE(left) == AOP_LIT) {
3854 //symbol *lbl = newiTempLabel(NULL);
3856 //EXPERIMENTAL lit = ulFromVal(AOP(left)->aopu.aop_lit);
3859 DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
3862 if((lit == 0) && (sign == 0)){
3865 emitpcode(POC_MOVFW, popGet(AOP(right),size));
3867 emitpcode(POC_IORFW, popGet(AOP(right),--size));
3869 genSkipz2(&rFalseIfx,0);
3870 if(ifx) ifx->generated = 1;
3877 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
3878 /* degenerate compare can never be true */
3879 if(rFalseIfx.condition == 0)
3880 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3882 if(ifx) ifx->generated = 1;
3887 /* signed comparisons to a literal byte */
3889 int lp1 = (lit+1) & 0xff;
3891 DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
3894 rFalseIfx.condition ^= 1;
3895 genSkipCond(&rFalseIfx,right,0,7);
3898 emitpcode(POC_MOVFW, popGet(AOP(right),0));
3899 emitpcode(POC_XORLW, popGetLit(0x7f));
3900 genSkipz2(&rFalseIfx,1);
3903 emitpcode(POC_MOVFW, popGet(AOP(right),0));
3904 emitpcode(POC_ADDLW, popGetLit(0x80));
3905 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
3906 rFalseIfx.condition ^= 1;
3907 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
3910 if(ifx) ifx->generated = 1;
3912 /* unsigned comparisons to a literal byte */
3914 switch(lit & 0xff ) {
3916 emitpcode(POC_MOVFW, popGet(AOP(right),0));
3917 genSkipz2(&rFalseIfx,0);
3918 if(ifx) ifx->generated = 1;
3921 genSkipCond(&rFalseIfx,right,0,7);
3922 if(ifx) ifx->generated = 1;
3926 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
3927 emitpcode(POC_SUBFW, popGet(AOP(right),0));
3928 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3929 rFalseIfx.condition ^= 1;
3930 if (AOP_TYPE(result) == AOP_CRY) {
3931 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
3932 if(ifx) ifx->generated = 1;
3934 DEBUGpic14_emitcode ("; ***","%s %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
3935 emitpcode(POC_CLRF, popGet(AOP(result),0));
3936 emitpcode(POC_RLF, popGet(AOP(result),0));
3937 emitpcode(POC_MOVLW, popGetLit(0x01));
3938 emitpcode(POC_XORWF, popGet(AOP(result),0));
3949 /* Size is greater than 1 */
3957 /* this means lit = 0xffffffff, or -1 */
3960 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
3961 rFalseIfx.condition ^= 1;
3962 genSkipCond(&rFalseIfx,right,size,7);
3963 if(ifx) ifx->generated = 1;
3970 if(rFalseIfx.condition) {
3971 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
3972 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
3975 emitpcode(POC_MOVFW, popGet(AOP(right),size));
3977 emitpcode(POC_IORFW, popGet(AOP(right),size));
3981 if(rFalseIfx.condition) {
3982 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
3983 emitpLabel(truelbl->key);
3985 rFalseIfx.condition ^= 1;
3986 genSkipCond(&rFalseIfx,right,s,7);
3989 if(ifx) ifx->generated = 1;
3993 if((size == 1) && (0 == (lp1&0xff))) {
3994 /* lower byte of signed word is zero */
3995 DEBUGpic14_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
3996 i = ((lp1 >> 8) & 0xff) ^0x80;
3997 emitpcode(POC_MOVFW, popGet(AOP(right),size));
3998 emitpcode(POC_ADDLW, popGetLit( 0x80));
3999 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4000 rFalseIfx.condition ^= 1;
4001 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4004 if(ifx) ifx->generated = 1;
4008 if(lit & (0x80 << (size*8))) {
4009 /* Lit is less than zero */
4010 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
4011 //rFalseIfx.condition ^= 1;
4012 //genSkipCond(&rFalseIfx,left,size,7);
4013 //rFalseIfx.condition ^= 1;
4014 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4015 //emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4017 if(rFalseIfx.condition)
4018 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4020 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4024 /* Lit is greater than or equal to zero */
4025 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
4026 //rFalseIfx.condition ^= 1;
4027 //genSkipCond(&rFalseIfx,right,size,7);
4028 //rFalseIfx.condition ^= 1;
4030 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4031 //emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4033 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4034 if(rFalseIfx.condition)
4035 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4037 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4042 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4043 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4047 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4049 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4051 rFalseIfx.condition ^= 1;
4052 //rFalseIfx.condition = 1;
4053 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4055 emitpLabel(truelbl->key);
4057 if(ifx) ifx->generated = 1;
4062 /* compare word or long to an unsigned literal on the right.*/
4067 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4070 break; /* handled above */
4073 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4075 emitpcode(POC_IORFW, popGet(AOP(right),size));
4076 genSkipz2(&rFalseIfx,0);
4080 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4082 emitpcode(POC_IORFW, popGet(AOP(right),size));
4085 if(rFalseIfx.condition)
4086 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4088 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4091 emitpcode(POC_MOVLW, popGetLit(lit+1));
4092 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4094 rFalseIfx.condition ^= 1;
4095 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4098 emitpLabel(truelbl->key);
4100 if(ifx) ifx->generated = 1;
4106 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4107 i = (lit >> (size*8)) & 0xff;
4109 emitpcode(POC_MOVLW, popGetLit(i));
4110 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4113 i = (lit >> (size*8)) & 0xff;
4116 emitpcode(POC_MOVLW, popGetLit(i));
4118 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4120 /* this byte of the lit is zero,
4121 *if it's not the last then OR in the variable */
4123 emitpcode(POC_IORFW, popGet(AOP(right),size));
4128 emitpLabel(lbl->key);
4130 rFalseIfx.condition ^= 1;
4131 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4135 emitpLabel(truelbl->key);
4136 if(ifx) ifx->generated = 1;
4140 /* Compare two variables */
4142 DEBUGpic14_emitcode(";sign","%d",sign);
4146 /* Sigh. thus sucks... */
4148 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4149 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4150 emitpcode(POC_MOVLW, popGetLit(0x80));
4151 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4152 emitpcode(POC_XORFW, popGet(AOP(right),size));
4153 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4155 /* Signed char comparison */
4156 /* Special thanks to Nikolai Golovchenko for this snippet */
4157 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4158 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4159 emitpcode(POC_RRFW, popGet(AOP(left),0)); /* could be any register */
4160 emitpcode(POC_XORFW, popGet(AOP(left),0));
4161 emitpcode(POC_XORFW, popGet(AOP(right),0));
4162 emitpcode(POC_ADDLW, popGetLit(0x80));
4164 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4165 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4167 if(ifx) ifx->generated = 1;
4173 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4174 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4178 /* The rest of the bytes of a multi-byte compare */
4182 emitpcode(POC_GOTO, popGetLabel(lbl->key));
4185 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4186 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4191 emitpLabel(lbl->key);
4193 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4194 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
4195 (AOP_TYPE(result) == AOP_REG)) {
4196 emitpcode(POC_CLRF, popGet(AOP(result),0));
4197 emitpcode(POC_RLF, popGet(AOP(result),0));
4199 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4201 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4202 if(ifx) ifx->generated = 1;
4209 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4210 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4211 pic14_outBitC(result);
4213 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4214 /* if the result is used in the next
4215 ifx conditional branch then generate
4216 code a little differently */
4218 genIfxJump (ifx,"c");
4220 pic14_outBitC(result);
4221 /* leave the result in acc */
4227 /*-----------------------------------------------------------------*/
4228 /* genCmpGt :- greater than comparison */
4229 /*-----------------------------------------------------------------*/
4230 static void genCmpGt (iCode *ic, iCode *ifx)
4232 operand *left, *right, *result;
4233 sym_link *letype , *retype;
4237 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4239 right= IC_RIGHT(ic);
4240 result = IC_RESULT(ic);
4242 letype = getSpec(operandType(left));
4243 retype =getSpec(operandType(right));
4244 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4245 /* assign the amsops */
4246 aopOp (left,ic,FALSE);
4247 aopOp (right,ic,FALSE);
4248 aopOp (result,ic,TRUE);
4250 genCmp(right, left, result, ifx, sign);
4252 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4253 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4254 freeAsmop(result,NULL,ic,TRUE);
4257 /*-----------------------------------------------------------------*/
4258 /* genCmpLt - less than comparisons */
4259 /*-----------------------------------------------------------------*/
4260 static void genCmpLt (iCode *ic, iCode *ifx)
4262 operand *left, *right, *result;
4263 sym_link *letype , *retype;
4267 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4269 right= IC_RIGHT(ic);
4270 result = IC_RESULT(ic);
4272 letype = getSpec(operandType(left));
4273 retype =getSpec(operandType(right));
4274 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4276 /* assign the amsops */
4277 aopOp (left,ic,FALSE);
4278 aopOp (right,ic,FALSE);
4279 aopOp (result,ic,TRUE);
4281 genCmp(left, right, result, ifx, sign);
4283 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4284 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4285 freeAsmop(result,NULL,ic,TRUE);
4288 /*-----------------------------------------------------------------*/
4289 /* genCmpEq - generates code for equal to */
4290 /*-----------------------------------------------------------------*/
4291 static void genCmpEq (iCode *ic, iCode *ifx)
4293 operand *left, *right, *result;
4295 symbol *false_label;
4298 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4301 DEBUGpic14_emitcode ("; ifx is non-null","");
4303 DEBUGpic14_emitcode ("; ifx is null","");
4305 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4306 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4307 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4309 DEBUGpic14_AopType(__LINE__,left,right,result);
4311 /* if literal, move literal to right */
4312 if (op_isLitLike (IC_LEFT(ic))) {
4313 operand *tmp = right ;
4319 if (ifx && !IC_TRUE(ifx))
4321 assert (IC_FALSE(ifx));
4322 false_label = IC_FALSE(ifx);
4325 size = min(AOP_SIZE(left),AOP_SIZE(right));
4326 assert(!pic14_sameRegs(AOP(result),AOP(left)));
4327 assert(!pic14_sameRegs(AOP(result),AOP(right)));
4329 /* assume left != right */
4332 for (i=0; i < AOP_SIZE(result); i++)
4334 emitpcode(POC_CLRF, popGet(AOP(result),i));
4338 if (AOP_TYPE(right) == AOP_LIT)
4340 unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit);
4342 size = AOP_SIZE(left);
4343 assert(!op_isLitLike(left));
4348 mov2w(AOP(left), 0);
4349 for (i=1; i < size; i++)
4350 emitpcode(POC_IORFW,popGet(AOP(left),i));
4351 /* now Z is set iff `left == right' */
4353 if (!false_label) false_label = newiTempLabel(NULL);
4354 emitpcode(POC_GOTO, popGetLabel(false_label->key));
4358 for (i=0; i < size; i++)
4361 emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
4362 /* now Z is cleared if `left != right' */
4364 if (!false_label) false_label = newiTempLabel(NULL);
4365 emitpcode(POC_GOTO, popGetLabel(false_label->key));
4372 /* right is no literal */
4375 for (i=0; i < size; i++)
4377 mov2w(AOP(right),i);
4378 emitpcode(POC_XORFW,popGet(AOP(left),i));
4379 /* now Z is cleared if `left != right' */
4381 if (!false_label) false_label = newiTempLabel(NULL);
4382 emitpcode(POC_GOTO, popGetLabel(false_label->key));
4386 /* if we reach here, left == right */
4388 if (AOP_SIZE(result) > 0)
4390 emitpcode(POC_INCF, popGet(AOP(result),0));
4393 if (ifx && IC_TRUE(ifx))
4395 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4398 if (false_label && (!ifx || IC_TRUE(ifx)))
4399 emitpLabel(false_label->key);
4401 if (ifx) ifx->generated = 1;
4403 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4404 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4405 freeAsmop(result,NULL,ic,TRUE);
4408 /*-----------------------------------------------------------------*/
4409 /* ifxForOp - returns the icode containing the ifx for operand */
4410 /*-----------------------------------------------------------------*/
4411 static iCode *ifxForOp ( operand *op, iCode *ic )
4414 /* if true symbol then needs to be assigned */
4415 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4416 if (IS_TRUE_SYMOP(op))
4419 /* if this has register type condition and
4420 the next instruction is ifx with the same operand
4421 and live to of the operand is upto the ifx only then */
4423 ic->next->op == IFX &&
4424 IC_COND(ic->next)->key == op->key &&
4425 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4429 ic->next->op == IFX &&
4430 IC_COND(ic->next)->key == op->key) {
4431 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
4435 DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
4437 ic->next->op == IFX)
4438 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
4441 ic->next->op == IFX &&
4442 IC_COND(ic->next)->key == op->key) {
4443 DEBUGpic14_emitcode ("; "," key is okay");
4444 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
4445 OP_SYMBOL(op)->liveTo,
4452 /*-----------------------------------------------------------------*/
4453 /* genAndOp - for && operation */
4454 /*-----------------------------------------------------------------*/
4455 static void genAndOp (iCode *ic)
4457 operand *left,*right, *result;
4461 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4462 /* note here that && operations that are in an
4463 if statement are taken away by backPatchLabels
4464 only those used in arthmetic operations remain */
4465 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4466 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4467 aopOp((result=IC_RESULT(ic)),ic,FALSE);
4469 DEBUGpic14_AopType(__LINE__,left,right,result);
4471 emitpcode(POC_MOVFW,popGet(AOP(left),0));
4472 emitpcode(POC_ANDFW,popGet(AOP(right),0));
4473 emitpcode(POC_MOVWF,popGet(AOP(result),0));
4475 /* if both are bit variables */
4476 /* if (AOP_TYPE(left) == AOP_CRY && */
4477 /* AOP_TYPE(right) == AOP_CRY ) { */
4478 /* pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
4479 /* pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
4480 /* pic14_outBitC(result); */
4482 /* tlbl = newiTempLabel(NULL); */
4483 /* pic14_toBoolean(left); */
4484 /* pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
4485 /* pic14_toBoolean(right); */
4486 /* pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
4487 /* pic14_outBitAcc(result); */
4490 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4491 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4492 freeAsmop(result,NULL,ic,TRUE);
4496 /*-----------------------------------------------------------------*/
4497 /* genOrOp - for || operation */
4498 /*-----------------------------------------------------------------*/
4501 modified this code, but it doesn't appear to ever get called
4504 static void genOrOp (iCode *ic)
4506 operand *left,*right, *result;
4510 /* note here that || operations that are in an
4511 if statement are taken away by backPatchLabels
4512 only those used in arthmetic operations remain */
4514 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4515 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4516 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4517 aopOp((result=IC_RESULT(ic)),ic,FALSE);
4519 DEBUGpic14_AopType(__LINE__,left,right,result);
4521 for (i=0; i < AOP_SIZE(result); i++)
4523 emitpcode(POC_CLRF, popGet(AOP(result), i));
4526 tlbl = newiTempLabel(NULL);
4527 pic14_toBoolean(left);
4529 emitpcode(POC_GOTO, popGetLabel(tlbl->key));
4530 pic14_toBoolean(right);
4531 emitpLabel(tlbl->key);
4532 /* here Z is clear IFF `left || right' */
4534 emitpcode(POC_INCF, popGet(AOP(result), 0));
4536 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4537 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4538 freeAsmop(result,NULL,ic,TRUE);
4541 /*-----------------------------------------------------------------*/
4542 /* isLiteralBit - test if lit == 2^n */
4543 /*-----------------------------------------------------------------*/
4544 static int isLiteralBit(unsigned long lit)
4546 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4547 0x100L,0x200L,0x400L,0x800L,
4548 0x1000L,0x2000L,0x4000L,0x8000L,
4549 0x10000L,0x20000L,0x40000L,0x80000L,
4550 0x100000L,0x200000L,0x400000L,0x800000L,
4551 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4552 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4556 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4557 for(idx = 0; idx < 32; idx++)
4563 /*-----------------------------------------------------------------*/
4564 /* continueIfTrue - */
4565 /*-----------------------------------------------------------------*/
4566 static void continueIfTrue (iCode *ic)
4569 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4573 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
4574 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4579 /*-----------------------------------------------------------------*/
4581 /*-----------------------------------------------------------------*/
4582 static void jumpIfTrue (iCode *ic)
4585 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4589 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
4590 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4595 /*-----------------------------------------------------------------*/
4596 /* jmpTrueOrFalse - */
4597 /*-----------------------------------------------------------------*/
4598 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4601 // ugly but optimized by peephole
4602 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4604 symbol *nlbl = newiTempLabel(NULL);
4605 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);
4606 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4607 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4608 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
4611 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4612 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4617 /*-----------------------------------------------------------------*/
4618 /* genAnd - code for and */
4619 /*-----------------------------------------------------------------*/
4620 static void genAnd (iCode *ic, iCode *ifx)
4622 operand *left, *right, *result;
4624 unsigned long lit = 0L;
4629 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4630 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4631 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4632 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4634 resolveIfx(&rIfx,ifx);
4636 /* if left is a literal & right is not then exchange them */
4637 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4638 AOP_NEEDSACC(left)) {
4639 operand *tmp = right ;
4644 /* if result = right then exchange them */
4645 if(pic14_sameRegs(AOP(result),AOP(right))){
4646 operand *tmp = right ;
4651 /* if right is bit then exchange them */
4652 if (AOP_TYPE(right) == AOP_CRY &&
4653 AOP_TYPE(left) != AOP_CRY){
4654 operand *tmp = right ;
4658 if(AOP_TYPE(right) == AOP_LIT)
4659 lit = ulFromVal (AOP(right)->aopu.aop_lit);
4661 size = AOP_SIZE(result);
4663 DEBUGpic14_AopType(__LINE__,left,right,result);
4666 // result = bit & yy;
4667 if (AOP_TYPE(left) == AOP_CRY){
4668 // c = bit & literal;
4669 if(AOP_TYPE(right) == AOP_LIT){
4671 if(size && pic14_sameRegs(AOP(result),AOP(left)))
4674 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4677 if(size && (AOP_TYPE(result) == AOP_CRY)){
4678 pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4681 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4685 pic14_emitcode("clr","c");
4688 if (AOP_TYPE(right) == AOP_CRY){
4690 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4691 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4694 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
4696 pic14_emitcode("rrc","a");
4697 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4703 pic14_outBitC(result);
4705 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4706 genIfxJump(ifx, "c");
4710 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4711 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4712 if((AOP_TYPE(right) == AOP_LIT) &&
4713 (AOP_TYPE(result) == AOP_CRY) &&
4714 (AOP_TYPE(left) != AOP_CRY)){
4715 int posbit = isLiteralBit(lit);
4719 //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
4722 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
4727 while (posbit > 7) {
4731 emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
4732 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
4733 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4740 symbol *tlbl = newiTempLabel(NULL);
4741 int sizel = AOP_SIZE(left);
4743 pic14_emitcode("setb","c");
4745 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4746 mov2w( AOP(left), offset);
4748 if((posbit = isLiteralBit(bytelit)) != 0) {
4749 emitpcode(rIfx.condition ? POC_BTFSC : POC_BTFSS, // XXX: or the other way round?
4750 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit - 1, 0));
4751 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
4754 emitpcode(POC_ANDLW, newpCodeOpLit(bytelit & 0x0ff));
4755 if (rIfx.condition) emitSKPZ;
4758 if(bytelit != 0x0FFL)
4760 pic14_emitcode("anl","a,%s",
4761 aopGet(AOP(right),offset,FALSE,TRUE));
4763 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
4766 emitpcode(POC_GOTO, popGetLabel(rIfx.lbl->key));
4772 // bit = left & literal
4774 pic14_emitcode("clr","c");
4775 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4777 // if(left & literal)
4780 jmpTrueOrFalse(ifx, tlbl);
4784 pic14_outBitC(result);
4788 /* if left is same as result */
4789 if(pic14_sameRegs(AOP(result),AOP(left))){
4791 for(;size--; offset++,lit>>=8) {
4792 if(AOP_TYPE(right) == AOP_LIT){
4793 switch(lit & 0xff) {
4795 /* and'ing with 0 has clears the result */
4796 emitpcode(POC_CLRF,popGet(AOP(result),offset));
4799 /* and'ing with 0xff is a nop when the result and left are the same */
4804 int p = my_powof2( (~lit) & 0xff );
4806 /* only one bit is set in the literal, so use a bcf instruction */
4807 emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
4810 if(know_W != (int)(lit&0xff))
4811 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
4813 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
4818 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
4819 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
4824 // left & result in different registers
4825 if(AOP_TYPE(result) == AOP_CRY){
4827 // if(size), result in bit
4828 // if(!size && ifx), conditional oper: if(left & right)
4829 symbol *tlbl = newiTempLabel(NULL);
4830 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4832 pic14_emitcode("setb","c");
4834 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4835 pic14_emitcode("anl","a,%s",
4836 aopGet(AOP(left),offset,FALSE,FALSE));
4837 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
4842 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4843 pic14_outBitC(result);
4845 jmpTrueOrFalse(ifx, tlbl);
4847 for(;(size--);offset++) {
4849 // result = left & right
4850 if(AOP_TYPE(right) == AOP_LIT){
4851 int t = (lit >> (offset*8)) & 0x0FFL;
4854 emitpcode(POC_CLRF,popGet(AOP(result),offset));
4857 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4858 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
4861 emitpcode(POC_MOVLW, popGetLit(t));
4862 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
4863 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
4868 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
4869 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
4870 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
4876 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4877 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4878 freeAsmop(result,NULL,ic,TRUE);
4881 /*-----------------------------------------------------------------*/
4882 /* genOr - code for or */
4883 /*-----------------------------------------------------------------*/
4884 static void genOr (iCode *ic, iCode *ifx)
4886 operand *left, *right, *result;
4888 unsigned long lit = 0L;
4891 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4893 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4894 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4895 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4897 DEBUGpic14_AopType(__LINE__,left,right,result);
4899 /* if left is a literal & right is not then exchange them */
4900 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4901 AOP_NEEDSACC(left)) {
4902 operand *tmp = right ;
4907 /* if result = right then exchange them */
4908 if(pic14_sameRegs(AOP(result),AOP(right))){
4909 operand *tmp = right ;
4914 /* if right is bit then exchange them */
4915 if (AOP_TYPE(right) == AOP_CRY &&
4916 AOP_TYPE(left) != AOP_CRY){
4917 operand *tmp = right ;
4922 DEBUGpic14_AopType(__LINE__,left,right,result);
4924 if(AOP_TYPE(right) == AOP_LIT)
4925 lit = ulFromVal (AOP(right)->aopu.aop_lit);
4927 size = AOP_SIZE(result);
4931 if (AOP_TYPE(left) == AOP_CRY){
4932 if(AOP_TYPE(right) == AOP_LIT){
4933 // c = bit & literal;
4935 // lit != 0 => result = 1
4936 if(AOP_TYPE(result) == AOP_CRY){
4938 emitpcode(POC_BSF, popGet(AOP(result),0));
4939 //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
4940 // AOP(result)->aopu.aop_dir,
4941 // AOP(result)->aopu.aop_dir);
4943 continueIfTrue(ifx);
4947 // lit == 0 => result = left
4948 if(size && pic14_sameRegs(AOP(result),AOP(left)))
4950 pic14_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
4953 if (AOP_TYPE(right) == AOP_CRY){
4954 if(pic14_sameRegs(AOP(result),AOP(left))){
4956 emitpcode(POC_BCF, popGet(AOP(result),0));
4957 emitpcode(POC_BTFSC, popGet(AOP(right),0));
4958 emitpcode(POC_BSF, popGet(AOP(result),0));
4960 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
4961 AOP(result)->aopu.aop_dir,
4962 AOP(result)->aopu.aop_dir);
4963 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
4964 AOP(right)->aopu.aop_dir,
4965 AOP(right)->aopu.aop_dir);
4966 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
4967 AOP(result)->aopu.aop_dir,
4968 AOP(result)->aopu.aop_dir);
4970 emitpcode(POC_BCF, popGet(AOP(result),0));
4971 emitpcode(POC_BTFSS, popGet(AOP(right),0));
4972 emitpcode(POC_BTFSC, popGet(AOP(left),0));
4973 emitpcode(POC_BSF, popGet(AOP(result),0));
4977 symbol *tlbl = newiTempLabel(NULL);
4978 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4981 emitpcode(POC_BCF, popGet(AOP(result),0));
4983 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4984 pic14_emitcode(";XXX setb","c");
4985 pic14_emitcode(";XXX jb","%s,%05d_DS_",
4986 AOP(left)->aopu.aop_dir,tlbl->key+100);
4987 pic14_toBoolean(right);
4988 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
4989 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4990 jmpTrueOrFalse(ifx, tlbl);
4994 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5001 pic14_outBitC(result);
5003 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5004 genIfxJump(ifx, "c");
5008 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5009 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5010 if((AOP_TYPE(right) == AOP_LIT) &&
5011 (AOP_TYPE(result) == AOP_CRY) &&
5012 (AOP_TYPE(left) != AOP_CRY)){
5014 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5017 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5019 continueIfTrue(ifx);
5022 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5023 // lit = 0, result = boolean(left)
5025 pic14_emitcode(";XXX setb","c");
5026 pic14_toBoolean(right);
5028 symbol *tlbl = newiTempLabel(NULL);
5029 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5031 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5033 genIfxJump (ifx,"a");
5037 pic14_outBitC(result);
5041 /* if left is same as result */
5042 if(pic14_sameRegs(AOP(result),AOP(left))){
5044 for(;size--; offset++,lit>>=8) {
5045 if(AOP_TYPE(right) == AOP_LIT){
5046 if((lit & 0xff) == 0)
5047 /* or'ing with 0 has no effect */
5050 int p = my_powof2(lit & 0xff);
5052 /* only one bit is set in the literal, so use a bsf instruction */
5054 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5056 if(know_W != (int)(lit & 0xff))
5057 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5058 know_W = lit & 0xff;
5059 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5064 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
5065 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5069 // left & result in different registers
5070 if(AOP_TYPE(result) == AOP_CRY){
5072 // if(size), result in bit
5073 // if(!size && ifx), conditional oper: if(left | right)
5074 symbol *tlbl = newiTempLabel(NULL);
5075 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5076 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5080 pic14_emitcode(";XXX setb","c");
5082 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5083 pic14_emitcode(";XXX orl","a,%s",
5084 aopGet(AOP(left),offset,FALSE,FALSE));
5085 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5090 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5091 pic14_outBitC(result);
5093 jmpTrueOrFalse(ifx, tlbl);
5094 } else for(;(size--);offset++){
5096 // result = left | right
5097 if(AOP_TYPE(right) == AOP_LIT){
5098 int t = (lit >> (offset*8)) & 0x0FFL;
5101 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
5102 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5106 emitpcode(POC_MOVLW, popGetLit(t));
5107 emitpcode(POC_IORFW, popGet(AOP(left),offset));
5108 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5113 // faster than result <- left, anl result,right
5114 // and better if result is SFR
5115 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5116 emitpcode(POC_IORFW,popGet(AOP(left),offset));
5117 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5122 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5123 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5124 freeAsmop(result,NULL,ic,TRUE);
5127 /*-----------------------------------------------------------------*/
5128 /* genXor - code for xclusive or */
5129 /*-----------------------------------------------------------------*/
5130 static void genXor (iCode *ic, iCode *ifx)
5132 operand *left, *right, *result;
5134 unsigned long lit = 0L;
5137 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5139 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5140 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5141 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5143 /* if left is a literal & right is not ||
5144 if left needs acc & right does not */
5145 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5146 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5147 operand *tmp = right ;
5152 /* if result = right then exchange them */
5153 if(pic14_sameRegs(AOP(result),AOP(right))){
5154 operand *tmp = right ;
5159 /* if right is bit then exchange them */
5160 if (AOP_TYPE(right) == AOP_CRY &&
5161 AOP_TYPE(left) != AOP_CRY){
5162 operand *tmp = right ;
5166 if(AOP_TYPE(right) == AOP_LIT)
5167 lit = ulFromVal (AOP(right)->aopu.aop_lit);
5169 size = AOP_SIZE(result);
5173 if (AOP_TYPE(left) == AOP_CRY){
5174 if(AOP_TYPE(right) == AOP_LIT){
5175 // c = bit & literal;
5177 // lit>>1 != 0 => result = 1
5178 if(AOP_TYPE(result) == AOP_CRY){
5180 {emitpcode(POC_BSF, popGet(AOP(result),offset));
5181 pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
5183 continueIfTrue(ifx);
5186 pic14_emitcode("setb","c");
5190 // lit == 0, result = left
5191 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5193 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5195 // lit == 1, result = not(left)
5196 if(size && pic14_sameRegs(AOP(result),AOP(left))){
5197 emitpcode(POC_MOVLW, popGet(AOP(result),offset));
5198 emitpcode(POC_XORWF, popGet(AOP(result),offset));
5199 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5202 assert ( !"incomplete genXor" );
5203 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5204 pic14_emitcode("cpl","c");
5211 symbol *tlbl = newiTempLabel(NULL);
5212 if (AOP_TYPE(right) == AOP_CRY){
5214 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5217 int sizer = AOP_SIZE(right);
5219 // if val>>1 != 0, result = 1
5220 pic14_emitcode("setb","c");
5222 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5224 // test the msb of the lsb
5225 pic14_emitcode("anl","a,#0xfe");
5226 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5230 pic14_emitcode("rrc","a");
5232 pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5233 pic14_emitcode("cpl","c");
5234 pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
5239 pic14_outBitC(result);
5241 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5242 genIfxJump(ifx, "c");
5246 if(pic14_sameRegs(AOP(result),AOP(left))){
5247 /* if left is same as result */
5248 for(;size--; offset++) {
5249 if(AOP_TYPE(right) == AOP_LIT){
5250 int t = (lit >> (offset*8)) & 0x0FFL;
5254 emitpcode(POC_MOVLW, popGetLit(t));
5255 emitpcode(POC_XORWF,popGet(AOP(left),offset));
5258 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5259 emitpcode(POC_XORWF,popGet(AOP(left),offset));
5263 // left & result in different registers
5264 if(AOP_TYPE(result) == AOP_CRY){
5266 // if(size), result in bit
5267 // if(!size && ifx), conditional oper: if(left ^ right)
5268 symbol *tlbl = newiTempLabel(NULL);
5269 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5271 pic14_emitcode("setb","c");
5273 if((AOP_TYPE(right) == AOP_LIT) &&
5274 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5275 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
5277 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5278 pic14_emitcode("xrl","a,%s",
5279 aopGet(AOP(left),offset,FALSE,FALSE));
5281 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5286 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5287 pic14_outBitC(result);
5289 jmpTrueOrFalse(ifx, tlbl);
5290 } else for(;(size--);offset++){
5292 // result = left & right
5293 if(AOP_TYPE(right) == AOP_LIT){
5294 int t = (lit >> (offset*8)) & 0x0FFL;
5297 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5298 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5301 emitpcode(POC_COMFW,popGet(AOP(left),offset));
5302 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5305 emitpcode(POC_MOVLW, popGetLit(t));
5306 emitpcode(POC_XORFW,popGet(AOP(left),offset));
5307 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5312 // faster than result <- left, anl result,right
5313 // and better if result is SFR
5314 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5315 emitpcode(POC_XORFW,popGet(AOP(left),offset));
5316 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5321 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5322 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5323 freeAsmop(result,NULL,ic,TRUE);
5326 /*-----------------------------------------------------------------*/
5327 /* genInline - write the inline code out */
5328 /*-----------------------------------------------------------------*/
5329 static void genInline (iCode *ic)
5331 char *buffer, *bp, *bp1;
5332 bool inComment = FALSE;
5335 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5337 _G.inLine += (!options.asmpeep);
5339 buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
5354 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
5359 /* Add \n for labels, not dirs such as c:\mydir */
5360 if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
5365 /* print label, use this special format with NULL directive
5366 * to denote that the argument should not be indented with tab */
5367 addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
5375 if ((bp1 != bp) && *bp1)
5376 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
5380 _G.inLine -= (!options.asmpeep);
5383 /*-----------------------------------------------------------------*/
5384 /* genRRC - rotate right with carry */
5385 /*-----------------------------------------------------------------*/
5386 static void genRRC (iCode *ic)
5388 operand *left , *result ;
5389 int size, offset = 0, same;
5392 /* rotate right with carry */
5394 result=IC_RESULT(ic);
5395 aopOp (left,ic,FALSE);
5396 aopOp (result,ic,FALSE);
5398 DEBUGpic14_AopType(__LINE__,left,NULL,result);
5400 same = pic14_sameRegs(AOP(result),AOP(left));
5402 size = AOP_SIZE(result);
5404 /* get the lsb and put it into the carry */
5405 emitpcode(POC_RRFW, popGet(AOP(left),size-1));
5412 emitpcode(POC_RRF, popGet(AOP(left),offset));
5414 emitpcode(POC_RRFW, popGet(AOP(left),offset));
5415 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5421 freeAsmop(left,NULL,ic,TRUE);
5422 freeAsmop(result,NULL,ic,TRUE);
5425 /*-----------------------------------------------------------------*/
5426 /* genRLC - generate code for rotate left with carry */
5427 /*-----------------------------------------------------------------*/
5428 static void genRLC (iCode *ic)
5430 operand *left , *result ;
5431 int size, offset = 0;
5435 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5436 /* rotate right with carry */
5438 result=IC_RESULT(ic);
5439 aopOp (left,ic,FALSE);
5440 aopOp (result,ic,FALSE);
5442 DEBUGpic14_AopType(__LINE__,left,NULL,result);
5444 same = pic14_sameRegs(AOP(result),AOP(left));
5446 /* move it to the result */
5447 size = AOP_SIZE(result);
5449 /* get the msb and put it into the carry */
5450 emitpcode(POC_RLFW, popGet(AOP(left),size-1));
5457 emitpcode(POC_RLF, popGet(AOP(left),offset));
5459 emitpcode(POC_RLFW, popGet(AOP(left),offset));
5460 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5467 freeAsmop(left,NULL,ic,TRUE);
5468 freeAsmop(result,NULL,ic,TRUE);
5471 /*-----------------------------------------------------------------*/
5472 /* genGetHbit - generates code get highest order bit */
5473 /*-----------------------------------------------------------------*/
5474 static void genGetHbit (iCode *ic)
5476 operand *left, *result;
5478 result=IC_RESULT(ic);
5479 aopOp (left,ic,FALSE);
5480 aopOp (result,ic,FALSE);
5483 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5484 /* get the highest order byte into a */
5485 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
5486 if(AOP_TYPE(result) == AOP_CRY){
5487 pic14_emitcode("rlc","a");
5488 pic14_outBitC(result);
5491 pic14_emitcode("rl","a");
5492 pic14_emitcode("anl","a,#0x01");
5493 pic14_outAcc(result);
5497 freeAsmop(left,NULL,ic,TRUE);
5498 freeAsmop(result,NULL,ic,TRUE);
5501 /*-----------------------------------------------------------------*/
5502 /* AccLsh - shift left accumulator by known count */
5503 /* MARK: pic14 always rotates through CARRY! */
5504 /*-----------------------------------------------------------------*/
5505 static void AccLsh (pCodeOp *pcop,int shCount)
5508 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5509 shCount &= 0x0007; // shCount : 0..7
5516 emitpcode(POC_RLF,pcop);
5520 emitpcode(POC_RLF,pcop);
5521 emitpcode(POC_RLF,pcop);
5524 emitpcode(POC_RLF,pcop);
5525 emitpcode(POC_RLF,pcop);
5526 emitpcode(POC_RLF,pcop);
5529 emitpcode(POC_SWAPF,pcop);
5532 emitpcode(POC_SWAPF,pcop);
5533 emitpcode(POC_RLF,pcop);
5536 emitpcode(POC_SWAPF,pcop);
5537 emitpcode(POC_RLF,pcop);
5538 emitpcode(POC_RLF,pcop);
5541 emitpcode(POC_RRFW,pcop);
5542 emitpcode(POC_RRF,pcop);
5545 /* clear invalid bits */
5546 emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
5547 emitpcode(POC_ANDWF, pcop);
5550 /*-----------------------------------------------------------------*/
5551 /* AccRsh - shift right accumulator by known count */
5552 /* MARK: pic14 always rotates through CARRY! */
5553 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
5554 /* 1: mask out invalid bits (zero-extend) */
5555 /* 2: sign-extend result (pretty slow) */
5556 /*-----------------------------------------------------------------*/
5557 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
5560 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5561 shCount &= 0x0007; // shCount : 0..7
5567 /* load sign if needed */
5568 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
5569 else if (mask_mode == 1) emitCLRC;
5570 emitpcode(POC_RRF,pcop);
5574 /* load sign if needed */
5575 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
5576 emitpcode(POC_RRF,pcop);
5577 /* load sign if needed */
5578 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
5579 emitpcode(POC_RRF,pcop);
5580 if (mask_mode == 2) return;
5583 /* load sign if needed */
5584 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
5585 emitpcode(POC_RRF,pcop);
5586 /* load sign if needed */
5587 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
5588 emitpcode(POC_RRF,pcop);
5589 /* load sign if needed */
5590 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
5591 emitpcode(POC_RRF,pcop);
5592 if (mask_mode == 2) return;
5595 emitpcode(POC_SWAPF,pcop);
5598 emitpcode(POC_SWAPF,pcop);
5599 emitpcode(POC_RRF,pcop);
5602 emitpcode(POC_SWAPF,pcop);
5603 emitpcode(POC_RRF,pcop);
5604 emitpcode(POC_RRF,pcop);
5610 emitpcode(POC_RLFW,pcop);
5611 emitpcode(POC_CLRF,pcop);
5613 emitpcode(POC_COMF,pcop);
5616 emitpcode(POC_RLFW,pcop);
5617 emitpcode(POC_RLF,pcop);
5624 /* leave invalid bits undefined */
5628 /* clear invalid bits -- zero-extend */
5629 emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
5630 emitpcode(POC_ANDWF, pcop);
5632 if (mask_mode == 2) {
5634 emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
5635 emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
5636 emitpcode(POC_IORWF, pcop);
5641 /*-----------------------------------------------------------------*/
5642 /* AccSRsh - signed right shift accumulator by known count */
5643 /*-----------------------------------------------------------------*/
5644 static void AccSRsh (int shCount)
5647 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5650 pic14_emitcode("mov","c,acc.7");
5651 pic14_emitcode("rrc","a");
5652 } else if(shCount == 2){
5653 pic14_emitcode("mov","c,acc.7");
5654 pic14_emitcode("rrc","a");
5655 pic14_emitcode("mov","c,acc.7");
5656 pic14_emitcode("rrc","a");
5658 tlbl = newiTempLabel(NULL);
5659 /* rotate right accumulator */
5660 AccRol(8 - shCount);
5661 /* and kill the higher order bits */
5662 pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
5663 pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5664 pic14_emitcode("orl","a,#0x%02x",
5665 (unsigned char)~SRMask[shCount]);
5666 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5671 /*-----------------------------------------------------------------*/
5672 /* shiftR1Left2Result - shift right one byte from left to result */
5673 /*-----------------------------------------------------------------*/
5674 static void shiftR1Left2ResultSigned (operand *left, int offl,
5675 operand *result, int offr,
5681 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5683 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
5687 emitpcode(POC_RLFW, popGet(AOP(left),offl));
5689 emitpcode(POC_RRF, popGet(AOP(result),offr));
5691 emitpcode(POC_RRFW, popGet(AOP(left),offl));
5692 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5698 emitpcode(POC_RLFW, popGet(AOP(left),offl));
5700 emitpcode(POC_RRF, popGet(AOP(result),offr));
5702 emitpcode(POC_RRFW, popGet(AOP(left),offl));
5703 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5705 emitpcode(POC_RLFW, popGet(AOP(result),offr));
5706 emitpcode(POC_RRF, popGet(AOP(result),offr));
5712 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
5714 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
5715 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5718 emitpcode(POC_RLFW, popGet(AOP(result),offr));
5719 emitpcode(POC_RLFW, popGet(AOP(result),offr));
5720 emitpcode(POC_ANDLW, popGetLit(0x1f));
5722 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
5723 emitpcode(POC_IORLW, popGetLit(0xe0));
5725 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5729 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
5730 emitpcode(POC_ANDLW, popGetLit(0x0f));
5731 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
5732 emitpcode(POC_IORLW, popGetLit(0xf0));
5733 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5737 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
5739 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
5740 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5742 emitpcode(POC_RRFW, popGet(AOP(result),offr));
5743 emitpcode(POC_ANDLW, popGetLit(0x07));
5744 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
5745 emitpcode(POC_IORLW, popGetLit(0xf8));
5746 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5751 emitpcode(POC_MOVLW, popGetLit(0x00));
5752 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
5753 emitpcode(POC_MOVLW, popGetLit(0xfe));
5754 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
5755 emitpcode(POC_IORLW, popGetLit(0x01));
5756 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5758 emitpcode(POC_CLRF, popGet(AOP(result),offr));
5759 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
5760 emitpcode(POC_DECF, popGet(AOP(result),offr));
5761 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
5762 emitpcode(POC_BCF, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
5768 emitpcode(POC_MOVLW, popGetLit(0x00));
5769 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
5770 emitpcode(POC_MOVLW, popGetLit(0xff));
5771 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5773 emitpcode(POC_CLRF, popGet(AOP(result),offr));
5774 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
5775 emitpcode(POC_DECF, popGet(AOP(result),offr));
5783 /*-----------------------------------------------------------------*/
5784 /* shiftR1Left2Result - shift right one byte from left to result */
5785 /*-----------------------------------------------------------------*/
5786 static void shiftR1Left2Result (operand *left, int offl,
5787 operand *result, int offr,
5788 int shCount, int sign)
5793 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5795 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
5797 /* Copy the msb into the carry if signed. */
5799 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
5809 emitpcode(POC_RRF, popGet(AOP(result),offr));
5811 emitpcode(POC_RRFW, popGet(AOP(left),offl));
5812 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5818 emitpcode(POC_RRF, popGet(AOP(result),offr));
5820 emitpcode(POC_RRFW, popGet(AOP(left),offl));
5821 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5824 emitpcode(POC_RRF, popGet(AOP(result),offr));
5829 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
5831 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
5832 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5835 emitpcode(POC_RLFW, popGet(AOP(result),offr));
5836 emitpcode(POC_RLFW, popGet(AOP(result),offr));
5837 emitpcode(POC_ANDLW, popGetLit(0x1f));
5838 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5842 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
5843 emitpcode(POC_ANDLW, popGetLit(0x0f));
5844 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5848 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
5849 emitpcode(POC_ANDLW, popGetLit(0x0f));
5850 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5852 emitpcode(POC_RRF, popGet(AOP(result),offr));
5857 emitpcode(POC_RLFW, popGet(AOP(left),offl));
5858 emitpcode(POC_ANDLW, popGetLit(0x80));
5859 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5860 emitpcode(POC_RLF, popGet(AOP(result),offr));
5861 emitpcode(POC_RLF, popGet(AOP(result),offr));
5866 emitpcode(POC_RLFW, popGet(AOP(left),offl));
5867 emitpcode(POC_CLRF, popGet(AOP(result),offr));
5868 emitpcode(POC_RLF, popGet(AOP(result),offr));
5877 /*-----------------------------------------------------------------*/
5878 /* shiftL1Left2Result - shift left one byte from left to result */
5879 /*-----------------------------------------------------------------*/
5880 static void shiftL1Left2Result (operand *left, int offl,
5881 operand *result, int offr, int shCount)
5887 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5889 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
5890 DEBUGpic14_emitcode ("; ***","same = %d",same);
5891 // l = aopGet(AOP(left),offl,FALSE,FALSE);
5893 /* shift left accumulator */
5894 //AccLsh(shCount); // don't comment out just yet...
5895 // aopPut(AOP(result),"a",offr);
5899 /* Shift left 1 bit position */
5900 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
5902 emitpcode(POC_ADDWF, popGet(AOP(left),offl));
5904 emitpcode(POC_ADDFW, popGet(AOP(left),offl));
5905 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5909 emitpcode(POC_RLFW, popGet(AOP(left),offl));
5910 emitpcode(POC_ANDLW,popGetLit(0x7e));
5911 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
5912 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
5915 emitpcode(POC_RLFW, popGet(AOP(left),offl));
5916 emitpcode(POC_ANDLW,popGetLit(0x3e));
5917 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
5918 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
5919 emitpcode(POC_RLF, popGet(AOP(result),offr));
5922 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
5923 emitpcode(POC_ANDLW, popGetLit(0xf0));
5924 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
5927 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
5928 emitpcode(POC_ANDLW, popGetLit(0xf0));
5929 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
5930 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
5933 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
5934 emitpcode(POC_ANDLW, popGetLit(0x30));
5935 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
5936 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
5937 emitpcode(POC_RLF, popGet(AOP(result),offr));
5940 emitpcode(POC_RRFW, popGet(AOP(left),offl));
5941 emitpcode(POC_CLRF, popGet(AOP(result),offr));
5942 emitpcode(POC_RRF, popGet(AOP(result),offr));
5946 DEBUGpic14_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
5952 /*-----------------------------------------------------------------*/
5953 /* movLeft2Result - move byte from left to result */
5954 /*-----------------------------------------------------------------*/
5955 static void movLeft2Result (operand *left, int offl,
5956 operand *result, int offr)
5959 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5960 if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5961 aopGet(AOP(left),offl,FALSE,FALSE);
5963 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
5964 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5968 /*-----------------------------------------------------------------*/
5969 /* shiftLeft_Left2ResultLit - shift left by known count */
5970 /*-----------------------------------------------------------------*/
5972 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
5974 int size, same, offr, i;
5976 size = AOP_SIZE(left);
5977 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
5979 same = pic14_sameRegs (AOP(left), AOP(result));
5982 shCount = shCount & 0x07;
5988 case 0: /* takes 0 or 2N cycles (for offr==0) */
5989 if (!same || offr) {
5990 for (i=size-1; i >= 0; i--)
5991 movLeft2Result (left, i, result, offr + i);
5995 case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
5997 shiftLeft_Left2ResultLit (left, result, 8 * offr);
5998 shiftLeft_Left2ResultLit (result, result, shCount);
5999 return; /* prevent clearing result again */
6002 for (i=0; i < size; i++) {
6003 if (same && !offr) {
6004 emitpcode (POC_RLF, popGet (AOP(left), i));
6006 emitpcode (POC_RLFW, popGet (AOP(left), i));
6007 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6013 case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
6014 /* works in-place/with offr as well */
6015 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
6016 emitpcode (POC_ANDLW, popGetLit (0xF0));
6017 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
6019 for (i = size - 2; i >= 0; i--)
6021 emitpcode (POC_SWAPFW, popGet (AOP(left), i));
6022 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6023 emitpcode (POC_ANDLW, popGetLit (0x0F));
6024 emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
6025 emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
6029 case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
6030 /* works in-place/with offr as well */
6031 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
6032 for (i = size-2; i >= 0; i--) {
6033 emitpcode (POC_RRFW, popGet (AOP(left), i));
6034 emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
6036 emitpcode (POC_CLRF, popGet (AOP(result), offr));
6037 emitpcode (POC_RRF, popGet (AOP(result), offr));
6041 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
6042 shiftLeft_Left2ResultLit (result, result, 1);
6043 return; /* prevent clearing result again */
6049 emitpcode (POC_CLRF, popGet (AOP(result), offr));
6053 /*-----------------------------------------------------------------*/
6054 /* shiftRight_Left2ResultLit - shift right by known count */
6055 /*-----------------------------------------------------------------*/
6057 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
6059 int size, same, offr, i;
6061 size = AOP_SIZE(left);
6062 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6064 same = pic14_sameRegs (AOP(left), AOP(result));
6067 shCount = shCount & 0x07;
6075 case 0: /* takes 0 or 2N cycles (for offr==0) */
6076 if (!same || offr) {
6077 for (i=0; i < size; i++)
6078 movLeft2Result (left, i + offr, result, i);
6082 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
6083 emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
6085 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
6086 shiftRight_Left2ResultLit (result, result, shCount, sign);
6087 return; /* prevent sign-extending result again */
6091 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
6094 for (i = size-1; i >= 0; i--) {
6095 if (same && !offr) {
6096 emitpcode (POC_RRF, popGet (AOP(left), i));
6098 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
6099 emitpcode (POC_MOVWF, popGet (AOP(result), i));
6105 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
6106 /* works in-place/with offr as well */
6107 emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
6108 emitpcode (POC_ANDLW, popGetLit (0x0F));
6109 emitpcode (POC_MOVWF, popGet(AOP(result), 0));
6111 for (i = 1; i < size; i++)
6113 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
6114 emitpcode (POC_MOVWF, popGet (AOP(result), i));
6115 emitpcode (POC_ANDLW, popGetLit (0xF0));
6116 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
6117 emitpcode (POC_XORWF, popGet (AOP(result), i));
6122 emitpcode (POC_MOVLW, popGetLit (0xF0));
6123 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
6124 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
6128 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
6129 /* works in-place/with offr as well */
6130 emitpcode (POC_RLFW, popGet (AOP(left), offr));
6131 for (i = 0; i < size-1; i++) {
6132 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
6133 emitpcode (POC_MOVWF, popGet (AOP(result), i));
6135 emitpcode (POC_CLRF, popGet (AOP(result), size-1));
6137 emitpcode (POC_RLF, popGet (AOP(result), size-1));
6140 emitpcode (POC_DECF, popGet (AOP(result), size-1));
6145 shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
6146 shiftRight_Left2ResultLit (result, result, 1, sign);
6147 return; /* prevent sign extending result again */
6152 addSign (result, size, sign);
6156 /*-----------------------------------------------------------------*/
6157 /* shiftL2Left2Result - shift left two bytes from left to result */
6158 /*-----------------------------------------------------------------*/
6159 static void shiftL2Left2Result (operand *left, int offl,
6160 operand *result, int offr, int shCount)
6164 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6166 if(pic14_sameRegs(AOP(result), AOP(left))) {
6174 emitpcode(POC_MOVFW,popGet(AOP(result),offr));
6175 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6176 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6180 emitpcode(POC_RLF, popGet(AOP(result),offr));
6181 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6187 emitpcode(POC_MOVLW, popGetLit(0x0f));
6188 emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
6189 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6190 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6191 emitpcode(POC_ANDFW, popGet(AOP(result),offr));
6192 emitpcode(POC_XORWF, popGet(AOP(result),offr));
6193 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6195 emitpcode(POC_RLF, popGet(AOP(result),offr));
6196 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6200 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6201 emitpcode(POC_RRF, popGet(AOP(result),offr));
6202 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6203 emitpcode(POC_RRF, popGet(AOP(result),offr));
6204 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6205 emitpcode(POC_ANDLW,popGetLit(0xc0));
6206 emitpcode(POC_XORFW,popGet(AOP(result),offr));
6207 emitpcode(POC_XORWF,popGet(AOP(result),offr));
6208 emitpcode(POC_XORFW,popGet(AOP(result),offr));
6209 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6212 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6213 emitpcode(POC_RRFW, popGet(AOP(result),offr));
6214 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6215 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6216 emitpcode(POC_RRF, popGet(AOP(result),offr));
6226 /* note, use a mov/add for the shift since the mov has a
6227 chance of getting optimized out */
6228 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6229 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6230 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6231 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6232 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6236 emitpcode(POC_RLF, popGet(AOP(result),offr));
6237 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6243 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6244 emitpcode(POC_ANDLW, popGetLit(0xF0));
6245 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6246 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6247 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6248 emitpcode(POC_ANDLW, popGetLit(0xF0));
6249 emitpcode(POC_XORWF, popGet(AOP(result),offr));
6250 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6254 emitpcode(POC_RLF, popGet(AOP(result),offr));
6255 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6259 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6260 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6261 emitpcode(POC_RRFW, popGet(AOP(result),offl));
6262 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6264 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6265 emitpcode(POC_RRF, popGet(AOP(result),offr));
6266 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6267 emitpcode(POC_ANDLW,popGetLit(0xc0));
6268 emitpcode(POC_XORFW,popGet(AOP(result),offr));
6269 emitpcode(POC_XORWF,popGet(AOP(result),offr));
6270 emitpcode(POC_XORFW,popGet(AOP(result),offr));
6271 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6274 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6275 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6276 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6277 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6278 emitpcode(POC_RRF, popGet(AOP(result),offr));
6284 /*-----------------------------------------------------------------*/
6285 /* shiftR2Left2Result - shift right two bytes from left to result */
6286 /*-----------------------------------------------------------------*/
6287 static void shiftR2Left2Result (operand *left, int offl,
6288 operand *result, int offr,
6289 int shCount, int sign)
6294 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6295 same = pic14_sameRegs(AOP(result), AOP(left));
6297 if(same && ((offl + MSB16) == offr)){
6299 /* don't crash result[offr] */
6300 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6301 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6304 movLeft2Result(left,offl, result, offr);
6305 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6308 /* a:x >> shCount (x = lsb(result))*/
6311 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6313 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6322 emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
6327 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6328 emitpcode(POC_RRF,popGet(AOP(result),offr));
6330 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6331 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6332 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6333 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6338 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
6341 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6342 emitpcode(POC_RRF,popGet(AOP(result),offr));
6349 emitpcode(POC_MOVLW, popGetLit(0xf0));
6350 emitpcode(POC_ANDWF, popGet(AOP(result),offr));
6351 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6353 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6354 emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
6355 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6356 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6358 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6359 emitpcode(POC_ANDLW, popGetLit(0x0f));
6360 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6362 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6363 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6364 emitpcode(POC_ANDLW, popGetLit(0xf0));
6365 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6366 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6370 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6371 emitpcode(POC_RRF, popGet(AOP(result),offr));
6375 emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
6376 emitpcode(POC_BTFSC,
6377 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
6378 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6386 emitpcode(POC_RLF, popGet(AOP(result),offr));
6387 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6389 emitpcode(POC_RLF, popGet(AOP(result),offr));
6390 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6391 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6392 emitpcode(POC_ANDLW,popGetLit(0x03));
6394 emitpcode(POC_BTFSC,
6395 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
6396 emitpcode(POC_IORLW,popGetLit(0xfc));
6398 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6399 emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
6400 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6401 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6403 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6404 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6405 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6406 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6407 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6408 emitpcode(POC_RLF, popGet(AOP(result),offr));
6409 emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
6410 emitpcode(POC_ANDLW,popGetLit(0x03));
6412 emitpcode(POC_BTFSC,
6413 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
6414 emitpcode(POC_IORLW,popGetLit(0xfc));
6416 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6417 //emitpcode(POC_RLF, popGet(AOP(result),offr));
6424 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6425 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6426 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6427 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
6430 emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
6432 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6436 /*-----------------------------------------------------------------*/
6437 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
6438 /*-----------------------------------------------------------------*/
6439 static void shiftLLeftOrResult (operand *left, int offl,
6440 operand *result, int offr, int shCount)
6443 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6445 /* shift left accumulator */
6446 AccLsh(left,offl,shCount);
6447 /* or with result */
6448 emitpcode (POC_IORWF, popGet (AOP(result), offr));
6449 assert ( !"broken (modifies left, fails for left==result))" );
6452 /*-----------------------------------------------------------------*/
6453 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
6454 /*-----------------------------------------------------------------*/
6455 static void shiftRLeftOrResult (operand *left, int offl,
6456 operand *result, int offr, int shCount)
6459 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6461 /* shift right accumulator */
6462 AccRsh(left,offl,shCount);
6463 /* or with result */
6464 emitpcode (POC_IORWF, popGet (AOP(result), offr));
6465 assert ( !"broken (modifies left, fails for left==result))" );
6468 /*-----------------------------------------------------------------*/
6469 /* genlshOne - left shift a one byte quantity by known count */
6470 /*-----------------------------------------------------------------*/
6471 static void genlshOne (operand *result, operand *left, int shCount)
6474 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6475 shiftL1Left2Result(left, LSB, result, LSB, shCount);
6478 /*-----------------------------------------------------------------*/
6479 /* genlshTwo - left shift two bytes by known amount != 0 */
6480 /*-----------------------------------------------------------------*/
6481 static void genlshTwo (operand *result,operand *left, int shCount)
6486 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6487 size = pic14_getDataSize(result);
6489 /* if shCount >= 8 */
6495 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6497 movLeft2Result(left, LSB, result, MSB16);
6499 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
6502 /* 1 <= shCount <= 7 */
6505 shiftL1Left2Result(left, LSB, result, LSB, shCount);
6507 shiftL2Left2Result(left, LSB, result, LSB, shCount);
6511 /*-----------------------------------------------------------------*/
6512 /* shiftLLong - shift left one long from left to result */
6513 /* offl = LSB or MSB16 */
6514 /*-----------------------------------------------------------------*/
6515 static void shiftLLong (operand *left, operand *result, int offr )
6518 int size = AOP_SIZE(result);
6521 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6522 if(size >= LSB+offr){
6523 l = aopGet(AOP(left),LSB,FALSE,FALSE);
6525 pic14_emitcode("add","a,acc");
6526 if (pic14_sameRegs(AOP(left),AOP(result)) &&
6527 size >= MSB16+offr && offr != LSB )
6528 pic14_emitcode("xch","a,%s",
6529 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
6531 aopPut(AOP(result),"a",LSB+offr);
6534 if(size >= MSB16+offr){
6535 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6536 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
6539 pic14_emitcode("rlc","a");
6540 if (pic14_sameRegs(AOP(left),AOP(result)) &&
6541 size >= MSB24+offr && offr != LSB)
6542 pic14_emitcode("xch","a,%s",
6543 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
6545 aopPut(AOP(result),"a",MSB16+offr);
6548 if(size >= MSB24+offr){
6549 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
6550 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
6553 pic14_emitcode("rlc","a");
6554 if (pic14_sameRegs(AOP(left),AOP(result)) &&
6555 size >= MSB32+offr && offr != LSB )
6556 pic14_emitcode("xch","a,%s",
6557 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
6559 aopPut(AOP(result),"a",MSB24+offr);
6562 if(size > MSB32+offr){
6563 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
6564 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
6567 pic14_emitcode("rlc","a");
6568 aopPut(AOP(result),"a",MSB32+offr);
6571 aopPut(AOP(result),zero,LSB);
6574 /*-----------------------------------------------------------------*/
6575 /* genlshFour - shift four byte by a known amount != 0 */
6576 /*-----------------------------------------------------------------*/
6577 static void genlshFour (operand *result, operand *left, int shCount)
6582 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6583 size = AOP_SIZE(result);
6585 /* if shifting more that 3 bytes */
6586 if (shCount >= 24 ) {
6589 /* lowest order of left goes to the highest
6590 order of the destination */
6591 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6593 movLeft2Result(left, LSB, result, MSB32);
6594 aopPut(AOP(result),zero,LSB);
6595 aopPut(AOP(result),zero,MSB16);
6596 aopPut(AOP(result),zero,MSB32);
6600 /* more than two bytes */
6601 else if ( shCount >= 16 ) {
6602 /* lower order two bytes goes to higher order two bytes */
6604 /* if some more remaining */
6606 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6608 movLeft2Result(left, MSB16, result, MSB32);
6609 movLeft2Result(left, LSB, result, MSB24);
6611 aopPut(AOP(result),zero,MSB16);
6612 aopPut(AOP(result),zero,LSB);
6616 /* if more than 1 byte */
6617 else if ( shCount >= 8 ) {
6618 /* lower order three bytes goes to higher order three bytes */
6622 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6624 movLeft2Result(left, LSB, result, MSB16);
6626 else{ /* size = 4 */
6628 movLeft2Result(left, MSB24, result, MSB32);
6629 movLeft2Result(left, MSB16, result, MSB24);
6630 movLeft2Result(left, LSB, result, MSB16);
6631 aopPut(AOP(result),zero,LSB);
6633 else if(shCount == 1)
6634 shiftLLong(left, result, MSB16);
6636 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
6637 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6638 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6639 aopPut(AOP(result),zero,LSB);
6644 /* 1 <= shCount <= 7 */
6645 else if(shCount <= 2){
6646 shiftLLong(left, result, LSB);
6648 shiftLLong(result, result, LSB);
6650 /* 3 <= shCount <= 7, optimize */
6652 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6653 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6654 shiftL2Left2Result(left, LSB, result, LSB, shCount);
6660 /*-----------------------------------------------------------------*/
6661 /* genLeftShiftLiteral - left shifting by known count */
6662 /*-----------------------------------------------------------------*/
6663 static void genLeftShiftLiteral (operand *left,
6668 int shCount = (int) ulFromVal (AOP(right)->aopu.aop_lit);
6672 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6673 freeAsmop(right,NULL,ic,TRUE);
6675 aopOp(left,ic,FALSE);
6676 aopOp(result,ic,FALSE);
6678 size = getSize(operandType(result));
6681 pic14_emitcode("; shift left ","result %d, left %d",size,
6685 /* I suppose that the left size >= result size */
6688 movLeft2Result(left, size, result, size);
6692 else if(shCount >= (size * 8))
6694 aopPut(AOP(result),zero,size);
6698 genlshOne (result,left,shCount);
6703 genlshTwo (result,left,shCount);
6707 genlshFour (result,left,shCount);
6711 freeAsmop(left,NULL,ic,TRUE);
6712 freeAsmop(result,NULL,ic,TRUE);
6716 /*-----------------------------------------------------------------*
6717 * genMultiAsm - repeat assembly instruction for size of register.
6718 * if endian == 1, then the high byte (i.e base address + size of
6719 * register) is used first else the low byte is used first;
6720 *-----------------------------------------------------------------*/
6721 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
6727 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6740 emitpcode(poc, popGet(AOP(reg),offset));
6746 /*-----------------------------------------------------------------*/
6747 /* loadSignToC - load the operand's sign bit into CARRY */
6748 /*-----------------------------------------------------------------*/
6750 static void loadSignToC (operand *op)
6753 assert (op && AOP(op) && AOP_SIZE(op));
6756 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
6760 /*-----------------------------------------------------------------*/
6761 /* genRightShift - generate code for right shifting */
6762 /*-----------------------------------------------------------------*/
6763 static void genGenericShift (iCode *ic, int shiftRight)
6765 operand *right, *left, *result;
6768 symbol *tlbl, *tlbl1, *inverselbl;
6771 /* if signed then we do it the hard way preserve the
6772 sign bit moving it inwards */
6773 retype = getSpec(operandType(IC_RESULT(ic)));
6774 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6776 /* signed & unsigned types are treated the same : i.e. the
6777 signed is NOT propagated inwards : quoting from the
6778 ANSI - standard : "for E1 >> E2, is equivalent to division
6779 by 2**E2 if unsigned or if it has a non-negative value,
6780 otherwise the result is implementation defined ", MY definition
6781 is that the sign does not get propagated */
6783 right = IC_RIGHT(ic);
6785 result = IC_RESULT(ic);
6787 aopOp(right,ic,FALSE);
6788 aopOp(left,ic,FALSE);
6789 aopOp(result,ic,FALSE);
6791 /* if the shift count is known then do it
6792 as efficiently as possible */
6793 if (AOP_TYPE(right) == AOP_LIT) {
6794 int lit = (int) ulFromVal (AOP(right)->aopu.aop_lit);
6798 shiftRight = !shiftRight;
6802 shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
6804 shiftLeft_Left2ResultLit (left, result, lit);
6805 //genRightShiftLiteral (left,right,result,ic, 0);
6809 /* shift count is unknown then we have to form
6810 a loop get the loop count in B : Note: we take
6811 only the lower order byte since shifting
6812 more that 32 bits make no sense anyway, ( the
6813 largest size of an object can be only 32 bits ) */
6815 /* we must not overwrite the shift counter */
6816 assert (!pic14_sameRegs(AOP(right),AOP(result)));
6818 /* now move the left to the result if they are not the
6820 if (!pic14_sameRegs(AOP(left),AOP(result)))
6822 size = min(AOP_SIZE(result), AOP_SIZE(left));
6824 mov2w(AOP(left), size);
6825 movwf(AOP(result), size);
6827 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
6830 tlbl = newiTempLabel(NULL);
6831 tlbl1= newiTempLabel(NULL);
6833 size = AOP_SIZE(result);
6835 mov2w(AOP(right),0);
6836 if (!SPEC_USIGN(operandType(right)))
6838 inverselbl = newiTempLabel(NULL);
6839 /* signed shift count -- invert shift direction for c<0 */
6840 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
6841 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
6843 emitpcode(POC_SUBLW, popGetLit(0)); /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
6844 /* check for `a = b >> c' with `-c == 0' */
6846 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
6847 emitpLabel(tlbl->key);
6848 /* propagate the sign bit inwards for SIGNED result */
6849 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
6850 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
6851 emitpcode(POC_ADDLW, popGetLit(1)); /* clears CARRY (unless W==0 afterwards) */
6853 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
6855 if (!SPEC_USIGN(operandType(right)))
6857 symbol *inv_loop = newiTempLabel(NULL);
6859 shiftRight = !shiftRight; /* invert shift direction */
6861 /* we came here from the code above -- we are done */
6862 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
6864 /* emit code for shifting N<0 steps, count is already in W */
6865 emitpLabel(inverselbl->key);
6866 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
6867 emitpLabel(inv_loop->key);
6868 /* propagate the sign bit inwards for SIGNED result */
6869 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
6870 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
6871 emitpcode(POC_ADDLW, popGetLit(1));
6873 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
6876 emitpLabel(tlbl1->key);
6878 freeAsmop(left,NULL,ic,TRUE);
6879 freeAsmop (right,NULL,ic,TRUE);
6880 freeAsmop(result,NULL,ic,TRUE);
6883 static void genRightShift (iCode *ic)
6885 genGenericShift(ic, 1);
6888 static void genLeftShift (iCode *ic)
6890 genGenericShift(ic, 0);
6893 /*-----------------------------------------------------------------*/
6894 /* SetIrp - Set IRP bit */
6895 /*-----------------------------------------------------------------*/
6896 void SetIrp(operand *result) {
6898 if (AOP_TYPE(result) == AOP_LIT) {
6899 unsigned lit = (unsigned) double2ul (operandLitValue(result));
6905 if (PCOP(AOP(result))->type == PO_LITERAL) {
6906 int addrs = PCOL(AOP(result))->lit;
6912 emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
6913 if(AOP_SIZE(result) > 1) {
6914 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
6922 setup_fsr (operand *ptr)
6925 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
6927 /* also setup-up IRP */
6931 /*-----------------------------------------------------------------*/
6932 /* emitPtrByteGet - emits code to get a byte into WREG from an */
6933 /* arbitrary pointer (__code, __data, generic) */
6934 /*-----------------------------------------------------------------*/
6936 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
6943 if (!alreadyAddressed) setup_fsr (src);
6944 emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
6948 assert( AOP_SIZE(src) == 2 );
6950 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
6952 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
6953 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
6954 call_libraryfunc ("__gptrget1");
6958 assert( AOP_SIZE(src) == 3 );
6960 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
6962 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
6964 call_libraryfunc ("__gptrget1");
6968 assert( !"unhandled pointer type" );
6973 /*-----------------------------------------------------------------*/
6974 /* emitPtrByteSet - emits code to set a byte from src through a */
6975 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR). */
6976 /*-----------------------------------------------------------------*/
6978 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
6985 if (!alreadyAddressed) setup_fsr (dst);
6986 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
6990 assert( !"trying to assign to __code pointer" );
6994 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
6996 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
6998 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
7000 call_libraryfunc ("__gptrput1");
7004 assert( !"unhandled pointer type" );
7009 /*-----------------------------------------------------------------*/
7010 /* genUnpackBits - generates code for unpacking bits */
7011 /*-----------------------------------------------------------------*/
7012 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
7014 int rsize; /* result size */
7015 sym_link *etype; /* bitfield type information */
7016 int blen; /* bitfield length */
7017 int bstr; /* bitfield starting bit within byte */
7020 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7021 etype = getSpec(operandType(result));
7022 rsize = getSize (operandType (result));
7023 blen = SPEC_BLEN (etype);
7024 bstr = SPEC_BSTR (etype);
7026 /* single bit field case */
7028 if (ifx) { /* that is for an if statement */
7031 resolveIfx(&rIfx,ifx);
7032 if (ptype == -1) /* direct */
7033 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
7035 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
7036 emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
7037 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
7041 assert (!pic14_sameRegs (AOP(result), AOP(left)));
7042 for (i=0; i < AOP_SIZE(result); i++)
7043 emitpcode (POC_CLRF, popGet (AOP(result), i));
7048 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
7049 /* adjust result below */
7056 emitPtrByteGet (left, ptype, FALSE);
7057 emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
7059 /* adjust result below */
7063 assert( !"unhandled pointer type" );
7066 /* move sign-/zero extended bit to result */
7067 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
7068 emitpcode (POC_INCF, popGet (AOP(result), 0));
7070 emitpcode (POC_DECF, popGet (AOP(result), 0));
7072 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
7076 else if (blen <= 8 && ((blen + bstr) <= 8))
7081 for (i=0; i < AOP_SIZE(result); i++)
7082 emitpcode (POC_CLRF, popGet (AOP(result), i));
7087 mov2w(AOP(left), 0);
7094 emitPtrByteGet (left, ptype, FALSE);
7098 assert( !"unhandled pointer type" );
7102 emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
7103 movwf(AOP(result), 0);
7104 AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
7106 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
7108 /* signed bitfield */
7109 assert (bstr + blen > 0);
7110 emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
7111 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
7112 emitpcode(POC_IORWF, popGet(AOP(result),0));
7114 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
7118 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
7122 /*-----------------------------------------------------------------*/
7123 /* genDataPointerGet - generates code when ptr offset is known */
7124 /*-----------------------------------------------------------------*/
7125 static void genDataPointerGet (operand *left,
7129 int size , offset = 0;
7132 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7135 /* optimization - most of the time, left and result are the same
7136 * address, but different types. for the pic code, we could omit
7139 aopOp(result,ic,TRUE);
7141 if (pic14_sameRegs (AOP(left), AOP(result)))
7144 DEBUGpic14_AopType(__LINE__,left,NULL,result);
7146 //emitpcode(POC_MOVFW, popGet(AOP(left),0));
7148 size = AOP_SIZE(result);
7149 if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
7153 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
7154 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7158 freeAsmop(left,NULL,ic,TRUE);
7159 freeAsmop(result,NULL,ic,TRUE);
7163 /*-----------------------------------------------------------------*/
7164 /* genNearPointerGet - pic14_emitcode for near pointer fetch */
7165 /*-----------------------------------------------------------------*/
7166 static void genNearPointerGet (operand *left,
7171 sym_link *ltype = operandType(left);
7172 sym_link *rtype = operandType(result);
7173 sym_link *retype= getSpec(rtype); /* bitfield type information */
7177 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7180 aopOp(left,ic,FALSE);
7182 /* if left is rematerialisable and
7183 result is not bit variable type and
7184 the left is pointer to data space i.e
7185 lower 128 bytes of space */
7186 if (AOP_TYPE(left) == AOP_PCODE && //AOP_TYPE(left) == AOP_IMMD &&
7187 !IS_BITVAR(retype) &&
7188 PIC_IS_DATA_PTR(ltype)) {
7189 genDataPointerGet (left,result,ic);
7193 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7194 aopOp (result,ic,FALSE);
7196 /* Check if can access directly instead of via a pointer */
7197 if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
7198 && AOP_SIZE(result) == 1)
7203 if (IS_BITFIELD(getSpec(operandType(result))))
7205 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
7209 /* If the pointer value is not in a the FSR then need to put it in */
7210 /* Must set/reset IRP bit for use with FSR. */
7215 /* if bitfield then unpack the bits */
7217 /* we have can just get the values */
7218 int size = AOP_SIZE(result);
7221 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7225 emitpcode(POC_MOVWF,popGet(AOP(left),0));
7227 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
7228 if (AOP_TYPE(result) == AOP_LIT) {
7229 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
7231 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
7233 if (size && !direct)
7234 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
7239 /* now some housekeeping stuff */
7241 /* we had to allocate for this iCode */
7242 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7243 freeAsmop(NULL,aop,ic,TRUE);
7245 /* we did not allocate which means left
7246 already in a pointer register, then
7247 if size > 0 && this could be used again
7248 we have to point it back to where it
7250 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7251 if (AOP_SIZE(result) > 1 &&
7252 !OP_SYMBOL(left)->remat &&
7253 ( OP_SYMBOL(left)->liveTo > ic->seq ||
7255 int size = AOP_SIZE(result) - 1;
7257 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
7263 freeAsmop(left,NULL,ic,TRUE);
7264 freeAsmop(result,NULL,ic,TRUE);
7268 /*-----------------------------------------------------------------*/
7269 /* genGenPointerGet - gget value from generic pointer space */
7270 /*-----------------------------------------------------------------*/
7271 static void genGenPointerGet (operand *left,
7272 operand *result, iCode *ic)
7275 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7276 aopOp(left,ic,FALSE);
7277 aopOp(result,ic,FALSE);
7280 DEBUGpic14_AopType(__LINE__,left,NULL,result);
7282 if (IS_BITFIELD(getSpec(operandType(result))))
7284 genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
7289 /* emit call to __gptrget */
7290 char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
7291 int size = AOP_SIZE(result);
7294 assert (size > 0 && size <= 4);
7296 /* pass arguments */
7297 assert (AOP_SIZE(left) == 3);
7298 mov2w(AOP(left), 0);
7299 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
7300 mov2w(AOP(left), 1);
7301 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
7302 mov2w(AOP(left), 2);
7303 call_libraryfunc (func[size]);
7306 movwf (AOP(result), --size);
7308 emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
7309 movwf (AOP(result), size);
7313 freeAsmop(left,NULL,ic,TRUE);
7314 freeAsmop(result,NULL,ic,TRUE);
7318 /*-----------------------------------------------------------------*/
7319 /* genConstPointerGet - get value from const generic pointer space */
7320 /*-----------------------------------------------------------------*/
7321 static void genConstPointerGet (operand *left,
7322 operand *result, iCode *ic)
7324 //sym_link *retype = getSpec(operandType(result));
7326 symbol *albl, *blbl;//, *clbl;
7333 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7334 aopOp(left,ic,FALSE);
7335 aopOp(result,ic,FALSE);
7337 size = AOP_SIZE(result);
7339 DEBUGpic14_AopType(__LINE__,left,NULL,result);
7341 DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
7343 lit = op_isLitLike (left);
7344 poc = lit ? POC_MOVLW : POC_MOVFW;
7346 if (IS_BITFIELD(getSpec(operandType(result))))
7348 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
7353 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
7354 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
7355 assert (size > 0 && size <= 4);
7358 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
7360 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
7361 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
7362 call_libraryfunc (func[size]);
7364 movwf(AOP(result),size-1);
7365 for (i = 1; i < size; i++)
7367 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
7368 movwf(AOP(result),size - 1 - i);
7373 freeAsmop(left,NULL,ic,TRUE);
7374 freeAsmop(result,NULL,ic,TRUE);
7377 /*-----------------------------------------------------------------*/
7378 /* genPointerGet - generate code for pointer get */
7379 /*-----------------------------------------------------------------*/
7380 static void genPointerGet (iCode *ic)
7382 operand *left, *result ;
7383 sym_link *type, *etype;
7387 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7390 result = IC_RESULT(ic) ;
7392 /* depending on the type of pointer we need to
7393 move it to the correct pointer register */
7394 type = operandType(left);
7395 etype = getSpec(type);
7397 if (IS_PTR_CONST(type))
7398 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
7400 /* if left is of type of pointer then it is simple */
7401 if (IS_PTR(type) && !IS_FUNC(type->next))
7402 p_type = DCL_TYPE(type);
7404 /* we have to go by the storage class */
7405 p_type = PTR_TYPE(SPEC_OCLS(etype));
7407 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
7409 if (SPEC_OCLS(etype)->codesp ) {
7410 DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
7411 //p_type = CPOINTER ;
7414 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
7415 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
7416 /*p_type = FPOINTER ;*/
7418 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
7419 DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
7420 /* p_type = PPOINTER; */
7422 if (SPEC_OCLS(etype) == idata )
7423 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
7424 /* p_type = IPOINTER; */
7426 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
7427 /* p_type = POINTER ; */
7430 /* now that we have the pointer type we assign
7431 the pointer values */
7437 genNearPointerGet (left,result,ic);
7441 genPagedPointerGet(left,result,ic);
7445 genFarPointerGet (left,result,ic);
7449 genConstPointerGet (left,result,ic);
7453 genGenPointerGet (left,result,ic);
7456 assert ( !"unhandled pointer type" );
7462 /*-----------------------------------------------------------------*/
7463 /* genPackBits - generates code for packed bit storage */
7464 /*-----------------------------------------------------------------*/
7465 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
7467 int blen; /* bitfield length */
7468 int bstr; /* bitfield starting bit within byte */
7469 int litval; /* source literal value (if AOP_LIT) */
7470 unsigned char mask; /* bitmask within current byte */
7473 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7475 blen = SPEC_BLEN (etype);
7476 bstr = SPEC_BSTR (etype);
7478 /* If the bitfield length is less than a byte and does not cross byte boundaries */
7479 if ((blen <= 8) && ((bstr + blen) <= 8))
7481 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7482 (unsigned char) (0xFF >> (8 - bstr)));
7484 if (AOP_TYPE (right) == AOP_LIT)
7486 /* Case with a bitfield length <8 and literal source */
7487 int lit = (int) ulFromVal (AOP (right)->aopu.aop_lit);
7494 if (AOP(result)->type == AOP_PCODE)
7495 pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
7497 pcop = popGet(AOP(result),0);
7498 emitpcode(lit?POC_BSF:POC_BCF,pcop);
7504 emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
7508 assert( !"trying to assign to bitfield via pointer to __code space" );
7512 emitPtrByteGet(result, p_type, FALSE);
7514 emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
7516 emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
7518 emitPtrByteSet(result, p_type, TRUE);
7522 assert( !"unhandled pointer type" );
7524 } // switch (p_type)
7527 litval = lit << bstr;
7528 litval &= (~mask) & 0x00ff;
7533 mov2w (AOP(result), 0);
7534 if ((litval|mask) != 0x00ff)
7535 emitpcode(POC_ANDLW, popGetLit (mask));
7537 emitpcode(POC_IORLW, popGetLit (litval));
7538 movwf (AOP(result), 0);
7544 emitPtrByteGet(result, p_type, FALSE);
7545 if ((litval|mask) != 0x00ff)
7546 emitpcode(POC_ANDLW, popGetLit (mask));
7548 emitpcode(POC_IORLW, popGetLit (litval));
7549 emitPtrByteSet(result, p_type, TRUE);
7553 assert( !"trying to assign to bitfield via pointer to __code space" );
7557 assert( !"unhandled pointer type" );
7564 /* right is no literal */
7569 /* Note more efficient code, of pre clearing bit then only setting it if required,
7570 * can only be done if it is known that the result is not a SFR */
7571 emitpcode(POC_RRFW,popGet(AOP(right),0));
7573 emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
7575 emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
7581 emitPtrByteGet (result, p_type, FALSE);
7582 emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
7583 emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
7584 emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
7585 emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
7586 emitPtrByteSet (result, p_type, TRUE);
7590 assert( !"trying to assign to bitfield via pointer to __code space" );
7594 assert( !"unhandled pointer type" );
7599 /* Case with a bitfield 1 < length <= 8 and arbitrary source */
7600 pCodeOp *temp = popGetTempReg ();
7602 mov2w (AOP(right), 0);
7604 emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
7606 emitpcode(POC_MOVWF, temp);
7608 AccLsh (temp, bstr);
7614 mov2w (AOP(result), 0);
7615 emitpcode(POC_ANDLW, popGetLit (mask));
7616 emitpcode(POC_IORFW, temp);
7617 movwf (AOP(result), 0);
7623 emitPtrByteGet (result, p_type, FALSE);
7624 emitpcode(POC_ANDLW, popGetLit (mask));
7625 emitpcode(POC_IORFW, temp);
7626 emitPtrByteSet (result, p_type, TRUE);
7630 assert( !"trying to assign to bitfield via pointer to __code space" );
7634 assert( !"unhandled pointer type" );
7638 popReleaseTempReg (temp);
7640 } // if (AOP(right)->type != AOP_LIT)
7642 } // if (blen <= 8 && ((blen + bstr) <= 8))
7644 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
7647 /*-----------------------------------------------------------------*/
7648 /* genDataPointerSet - remat pointer to data space */
7649 /*-----------------------------------------------------------------*/
7650 static void genDataPointerSet(operand *right,
7654 int size, offset = 0 ;
7658 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7659 aopOp(right,ic,FALSE);
7660 aopOp(result,ic,FALSE);
7662 assert (IS_SYMOP(result));
7663 assert (IS_PTR(OP_SYM_TYPE(result)));
7665 if (AOP_TYPE(right) == AOP_LIT)
7668 size = AOP_SIZE(right);
7669 ressize = getSize(OP_SYM_ETYPE(result));
7670 if (size > ressize) size = ressize;
7671 //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
7673 //assert( !"what's going on here?" );
7676 if ( AOP_TYPE(result) == AOP_PCODE) {
7677 fprintf(stderr,"genDataPointerSet %s, %d\n",
7678 AOP(result)->aopu.pcop->name,
7679 PCOI(AOP(result)->aopu.pcop)->offset);
7683 // tsd, was l+1 - the underline `_' prefix was being stripped
7685 emitpComment ("%s:%u: size=%d/%d, offset=%d, AOP_TYPE(res)=%d", __FILE__,__LINE__, size, ressize, offset, AOP_TYPE(result));
7687 if (AOP_TYPE(right) == AOP_LIT) {
7688 unsigned int lit = pic14aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
7689 //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
7691 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
7692 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
7694 emitpcode(POC_CLRF, popGet(AOP(result), offset));
7697 //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
7698 emitpcode(POC_MOVFW, popGet(AOP(right), offset));
7699 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
7705 freeAsmop(right,NULL,ic,TRUE);
7706 freeAsmop(result,NULL,ic,TRUE);
7709 /*-----------------------------------------------------------------*/
7710 /* genNearPointerSet - pic14_emitcode for near pointer put */
7711 /*-----------------------------------------------------------------*/
7712 static void genNearPointerSet (operand *right,
7717 sym_link *ptype = operandType(result);
7718 sym_link *retype = getSpec(operandType(right));
7719 sym_link *letype = getSpec(ptype);
7724 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7725 aopOp(result,ic,FALSE);
7728 /* if the result is rematerializable &
7729 in data space & not a bit variable */
7730 //if (AOP_TYPE(result) == AOP_IMMD &&
7731 if (AOP_TYPE(result) == AOP_PCODE &&
7732 PIC_IS_DATA_PTR(ptype) &&
7733 !IS_BITVAR (retype) &&
7734 !IS_BITVAR (letype)) {
7735 genDataPointerSet (right,result,ic);
7736 freeAsmop(result,NULL,ic,TRUE);
7741 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7742 aopOp(right,ic,FALSE);
7743 DEBUGpic14_AopType(__LINE__,NULL,right,result);
7745 /* Check if can access directly instead of via a pointer */
7746 if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
7750 if (IS_BITFIELD (letype))
7752 genPackBits (letype, result, right, direct?-1:POINTER);
7756 /* If the pointer value is not in a the FSR then need to put it in */
7757 /* Must set/reset IRP bit for use with FSR. */
7758 /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
7763 /* we have can just get the values */
7764 int size = AOP_SIZE(right);
7767 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7769 char *l = aopGet(AOP(right),offset,FALSE,TRUE);
7771 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
7773 if (AOP_TYPE(right) == AOP_LIT) {
7774 emitpcode(POC_MOVLW,popGet(AOP(right),offset));
7776 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
7779 emitpcode(POC_MOVWF,popGet(AOP(result),0));
7781 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
7783 if (size && !direct)
7784 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
7789 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7790 /* now some housekeeping stuff */
7792 /* we had to allocate for this iCode */
7793 freeAsmop(NULL,aop,ic,TRUE);
7795 /* we did not allocate which means left
7796 already in a pointer register, then
7797 if size > 0 && this could be used again
7798 we have to point it back to where it
7800 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7801 if (AOP_SIZE(right) > 1 &&
7802 !OP_SYMBOL(result)->remat &&
7803 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7805 int size = AOP_SIZE(right) - 1;
7807 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
7811 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7814 freeAsmop(right,NULL,ic,TRUE);
7815 freeAsmop(result,NULL,ic,TRUE);
7818 /*-----------------------------------------------------------------*/
7819 /* genGenPointerSet - set value from generic pointer space */
7820 /*-----------------------------------------------------------------*/
7821 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
7823 sym_link *retype = getSpec(operandType(result));
7826 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7827 aopOp(right,ic,FALSE);
7828 aopOp(result,ic,FALSE);
7831 DEBUGpic14_AopType(__LINE__,right,NULL,result);
7833 if (IS_BITFIELD(retype))
7835 genPackBits (retype, result, right, GPOINTER);
7840 /* emit call to __gptrput */
7841 char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
7842 int size = AOP_SIZE(right);
7845 /* The following assertion fails for
7846 * struct foo { char a; char b; } bar;
7847 * void demo(struct foo *dst, char c) { dst->b = c; }
7848 * as size will be 1 (sizeof(c)), whereas dst->b will be accessed
7849 * using (((char *)dst)+1), whose OP_SYM_ETYPE still is struct foo
7851 * The frontend seems to guarantee that IC_LEFT has the correct size,
7852 * it works fine both for larger and smaller types of `char c'.
7854 //assert (size == getSize(OP_SYM_ETYPE(result)));
7855 assert (size > 0 && size <= 4);
7857 /* pass arguments */
7858 /* - value (MSB in Gstack_base_addr-2, growing downwards) */
7864 mov2w_op (right, off);
7865 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
7870 assert (AOP_SIZE(result) == 3);
7871 mov2w(AOP(result), 0);
7872 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
7873 mov2w(AOP(result), 1);
7874 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
7875 mov2w(AOP(result), 2);
7876 call_libraryfunc (func[size]);
7879 freeAsmop(right,NULL,ic,TRUE);
7880 freeAsmop(result,NULL,ic,TRUE);
7883 /*-----------------------------------------------------------------*/
7884 /* genPointerSet - stores the value into a pointer location */
7885 /*-----------------------------------------------------------------*/
7886 static void genPointerSet (iCode *ic)
7888 operand *right, *result ;
7889 sym_link *type, *etype;
7893 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7895 right = IC_RIGHT(ic);
7896 result = IC_RESULT(ic) ;
7898 /* depending on the type of pointer we need to
7899 move it to the correct pointer register */
7900 type = operandType(result);
7901 etype = getSpec(type);
7902 /* if left is of type of pointer then it is simple */
7903 if (IS_PTR(type) && !IS_FUNC(type->next)) {
7904 p_type = DCL_TYPE(type);
7907 /* we have to go by the storage class */
7908 p_type = PTR_TYPE(SPEC_OCLS(etype));
7910 /* if (SPEC_OCLS(etype)->codesp ) { */
7911 /* p_type = CPOINTER ; */
7914 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7915 /* p_type = FPOINTER ; */
7917 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7918 /* p_type = PPOINTER ; */
7920 /* if (SPEC_OCLS(etype) == idata ) */
7921 /* p_type = IPOINTER ; */
7923 /* p_type = POINTER ; */
7926 /* now that we have the pointer type we assign
7927 the pointer values */
7933 genNearPointerSet (right,result,ic);
7937 genPagedPointerSet (right,result,ic);
7941 genFarPointerSet (right,result,ic);
7945 genGenPointerSet (right,result,ic);
7949 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7950 "genPointerSet: illegal pointer type");
7954 /*-----------------------------------------------------------------*/
7955 /* genIfx - generate code for Ifx statement */
7956 /*-----------------------------------------------------------------*/
7957 static void genIfx (iCode *ic, iCode *popIc)
7959 operand *cond = IC_COND(ic);
7963 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7965 aopOp(cond,ic,FALSE);
7967 /* get the value into acc */
7968 if (AOP_TYPE(cond) != AOP_CRY)
7969 pic14_toBoolean(cond);
7973 /* if there was something to be popped then do it */
7979 /* This assumes that CARRY is set iff cond is true */
7982 assert (!IC_FALSE(ic));
7983 emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
7985 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
7987 assert (IC_FALSE(ic));
7988 emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
7990 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
7994 static int hasWarned = 0;
7997 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
8004 /* now Z is set iff !cond */
8007 assert (!IC_FALSE(ic));
8009 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
8012 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
8018 /* the result is now in the accumulator */
8019 freeAsmop(cond,NULL,ic,TRUE);
8022 /*-----------------------------------------------------------------*/
8023 /* genAddrOf - generates code for address of */
8024 /*-----------------------------------------------------------------*/
8025 static void genAddrOf (iCode *ic)
8027 operand *right, *result, *left;
8031 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8034 //aopOp(IC_RESULT(ic),ic,FALSE);
8036 aopOp((left=IC_LEFT(ic)),ic,FALSE);
8037 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
8038 aopOp((result=IC_RESULT(ic)),ic,TRUE);
8040 DEBUGpic14_AopType(__LINE__,left,right,result);
8041 assert (IS_SYMOP (left));
8043 /* sanity check: generic pointers to code space are not yet supported,
8044 * pionters to codespace must not be assigned addresses of __data values. */
8046 fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
8047 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)));
8048 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)));
8049 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)));
8050 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)));
8053 if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
8054 fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
8055 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
8056 OP_SYMBOL(left)->name);
8057 } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
8058 fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
8059 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
8060 OP_SYMBOL(left)->name);
8063 size = AOP_SIZE(IC_RESULT(ic));
8064 if (IS_GENPTR(OP_SYM_TYPE(result))) {
8066 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
8071 /* fixing bug #863624, reported from (errolv) */
8072 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
8073 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
8076 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
8077 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8082 if (IS_GENPTR(OP_SYM_TYPE(result)))
8084 /* provide correct tag */
8085 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
8086 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
8087 movwf (AOP(result), 2);
8090 freeAsmop(left,NULL,ic,FALSE);
8091 freeAsmop(result,NULL,ic,TRUE);
8096 /*-----------------------------------------------------------------*/
8097 /* genFarFarAssign - assignment when both are in far space */
8098 /*-----------------------------------------------------------------*/
8099 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
8101 int size = AOP_SIZE(right);
8104 /* first push the right side on to the stack */
8106 l = aopGet(AOP(right),offset++,FALSE,FALSE);
8108 pic14_emitcode ("push","acc");
8111 freeAsmop(right,NULL,ic,FALSE);
8112 /* now assign DPTR to result */
8113 aopOp(result,ic,FALSE);
8114 size = AOP_SIZE(result);
8116 pic14_emitcode ("pop","acc");
8117 aopPut(AOP(result),"a",--offset);
8119 freeAsmop(result,NULL,ic,FALSE);
8124 /*-----------------------------------------------------------------*/
8125 /* genAssign - generate code for assignment */
8126 /*-----------------------------------------------------------------*/
8127 static void genAssign (iCode *ic)
8129 operand *result, *right;
8130 int size, offset,know_W;
8131 unsigned long lit = 0L;
8133 result = IC_RESULT(ic);
8134 right = IC_RIGHT(ic) ;
8137 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8139 /* if they are the same */
8140 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
8143 aopOp(right,ic,FALSE);
8144 aopOp(result,ic,TRUE);
8146 DEBUGpic14_AopType(__LINE__,NULL,right,result);
8148 /* if they are the same registers */
8149 if (pic14_sameRegs(AOP(right),AOP(result)))
8152 /* special case: assign from __code */
8153 if (!IS_ITEMP(right) /* --> iTemps never reside in __code */
8154 && IS_SYMOP (right) /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
8155 && !IS_FUNC(OP_SYM_TYPE(right)) /* --> we would want its address instead of the first instruction */
8156 && !IS_CODEPTR(OP_SYM_TYPE(right)) /* --> get symbols address instread */
8157 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
8159 emitpComment ("genAssign from CODESPACE");
8160 genConstPointerGet (right, result, ic);
8164 /* just for symmetry reasons... */
8165 if (!IS_ITEMP(result)
8166 && IS_SYMOP (result)
8167 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
8169 assert ( !"cannot write to CODESPACE" );
8172 /* if the result is a bit */
8173 if (AOP_TYPE(result) == AOP_CRY) {
8175 /* if the right size is a literal then
8176 we know what the value is */
8177 if (AOP_TYPE(right) == AOP_LIT) {
8179 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
8180 popGet(AOP(result),0));
8182 if (((int) operandLitValue(right)))
8183 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
8184 AOP(result)->aopu.aop_dir,
8185 AOP(result)->aopu.aop_dir);
8187 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
8188 AOP(result)->aopu.aop_dir,
8189 AOP(result)->aopu.aop_dir);
8193 /* the right is also a bit variable */
8194 if (AOP_TYPE(right) == AOP_CRY) {
8195 emitpcode(POC_BCF, popGet(AOP(result),0));
8196 emitpcode(POC_BTFSC, popGet(AOP(right),0));
8197 emitpcode(POC_BSF, popGet(AOP(result),0));
8199 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
8200 AOP(result)->aopu.aop_dir,
8201 AOP(result)->aopu.aop_dir);
8202 pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
8203 AOP(right)->aopu.aop_dir,
8204 AOP(right)->aopu.aop_dir);
8205 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
8206 AOP(result)->aopu.aop_dir,
8207 AOP(result)->aopu.aop_dir);
8212 emitpcode(POC_BCF, popGet(AOP(result),0));
8213 pic14_toBoolean(right);
8215 emitpcode(POC_BSF, popGet(AOP(result),0));
8216 //aopPut(AOP(result),"a",0);
8220 /* bit variables done */
8222 size = AOP_SIZE(result);
8224 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
8225 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8226 if(aopIdx(AOP(result),0) == 4) {
8227 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8228 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8229 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8232 DEBUGpic14_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
8238 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8239 if(AOP_TYPE(right) == AOP_LIT) {
8240 lit = (unsigned long)pic14aopLiteral(AOP(right)->aopu.aop_lit, offset) & 0x0ff;
8242 if(know_W != (int)(lit&0xff))
8243 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
8245 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8247 emitpcode(POC_CLRF, popGet(AOP(result),offset));
8249 } else if (AOP_TYPE(right) == AOP_CRY) {
8250 emitpcode(POC_CLRF, popGet(AOP(result),offset));
8252 emitpcode(POC_BTFSS, popGet(AOP(right),0));
8253 emitpcode(POC_INCF, popGet(AOP(result),0));
8256 mov2w_op (right, offset);
8257 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8265 freeAsmop (right,NULL,ic,FALSE);
8266 freeAsmop (result,NULL,ic,TRUE);
8269 /*-----------------------------------------------------------------*/
8270 /* genJumpTab - genrates code for jump table */
8271 /*-----------------------------------------------------------------*/
8272 static void genJumpTab (iCode *ic)
8278 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8280 aopOp(IC_JTCOND(ic),ic,FALSE);
8281 /* get the condition into accumulator */
8282 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
8284 /* multiply by three */
8285 pic14_emitcode("add","a,acc");
8286 pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
8288 jtab = newiTempLabel(NULL);
8289 pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
8290 pic14_emitcode("jmp","@a+dptr");
8291 pic14_emitcode("","%05d_DS_:",jtab->key+100);
8293 emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
8294 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
8295 emitpcode(POC_MOVLW, popGetLabel(jtab->key));
8296 emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
8298 emitpcode(POC_INCF, popCopyReg(&pc_pclath));
8299 emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
8300 emitpLabel(jtab->key);
8302 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
8304 /* now generate the jump labels */
8305 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
8306 jtab = setNextItem(IC_JTLABELS(ic))) {
8307 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
8308 emitpcode(POC_GOTO,popGetLabel(jtab->key));
8314 /*-----------------------------------------------------------------*/
8315 /* genMixedOperation - gen code for operators between mixed types */
8316 /*-----------------------------------------------------------------*/
8318 TSD - Written for the PIC port - but this unfortunately is buggy.
8319 This routine is good in that it is able to efficiently promote
8320 types to different (larger) sizes. Unfortunately, the temporary
8321 variables that are optimized out by this routine are sometimes
8322 used in other places. So until I know how to really parse the
8323 iCode tree, I'm going to not be using this routine :(.
8325 static int genMixedOperation (iCode *ic)
8329 operand *result = IC_RESULT(ic);
8330 sym_link *ctype = operandType(IC_LEFT(ic));
8331 operand *right = IC_RIGHT(ic);
8337 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
8339 pic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
8345 nextright = IC_RIGHT(nextic);
8346 nextleft = IC_LEFT(nextic);
8347 nextresult = IC_RESULT(nextic);
8349 aopOp(right,ic,FALSE);
8350 aopOp(result,ic,FALSE);
8351 aopOp(nextright, nextic, FALSE);
8352 aopOp(nextleft, nextic, FALSE);
8353 aopOp(nextresult, nextic, FALSE);
8355 if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
8361 pic14_emitcode(";remove right +","");
8363 } else if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
8369 pic14_emitcode(";remove left +","");
8373 big = AOP_SIZE(nextleft);
8374 small = AOP_SIZE(nextright);
8376 switch(nextic->op) {
8379 pic14_emitcode(";optimize a +","");
8380 /* if unsigned or not an integral type */
8381 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
8382 pic14_emitcode(";add a bit to something","");
8385 pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
8387 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
8388 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
8389 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
8391 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
8399 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8400 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8401 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8404 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8406 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
8407 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
8408 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
8409 pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8410 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
8413 pic14_emitcode("rlf","known_zero,w");
8420 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8421 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8422 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8424 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8434 freeAsmop(right,NULL,ic,TRUE);
8435 freeAsmop(result,NULL,ic,TRUE);
8436 freeAsmop(nextright,NULL,ic,TRUE);
8437 freeAsmop(nextleft,NULL,ic,TRUE);
8439 nextic->generated = 1;
8446 /*-----------------------------------------------------------------*/
8447 /* genCast - gen code for casting */
8448 /*-----------------------------------------------------------------*/
8449 static void genCast (iCode *ic)
8451 operand *result = IC_RESULT(ic);
8452 sym_link *restype = operandType(result);
8453 sym_link *rtype = operandType(IC_RIGHT(ic));
8454 operand *right = IC_RIGHT(ic);
8458 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
8459 /* if they are equivalent then do nothing */
8460 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
8463 aopOp(right,ic,FALSE) ;
8464 aopOp(result,ic,FALSE);
8466 DEBUGpic14_AopType(__LINE__,NULL,right,result);
8468 /* if the result is a bit */
8469 if (AOP_TYPE(result) == AOP_CRY) {
8470 assert(!"assigning to bit variables is not supported");
8473 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
8475 size = AOP_SIZE(result);
8477 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
8479 emitpcode(POC_CLRF, popGet(AOP(result),0));
8480 emitpcode(POC_BTFSC, popGet(AOP(right),0));
8481 emitpcode(POC_INCF, popGet(AOP(result),0));
8484 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
8489 if (IS_PTR(restype))
8491 operand *result = IC_RESULT(ic);
8492 //operand *left = IC_LEFT(ic);
8493 operand *right = IC_RIGHT(ic);
8496 /* copy common part */
8497 int max, size = AOP_SIZE(result);
8498 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
8499 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
8501 /* warn if we discard generic opinter tag */
8502 if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
8504 //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
8510 mov2w_op (right, size);
8511 movwf (AOP(result), size);
8514 /* upcast into generic pointer type? */
8515 if (IS_GENPTR(restype)
8516 && (size < AOP_SIZE(result))
8517 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
8519 //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
8522 switch (DCL_TYPE(rtype))
8524 case POINTER: /* __data */
8525 case FPOINTER: /* __data */
8526 assert (AOP_SIZE(right) == 2);
8530 case CPOINTER: /* __code */
8531 assert (AOP_SIZE(right) == 2);
8535 case GPOINTER: /* unknown destination, __data or __code */
8536 /* assume __data space (address of immediate) */
8537 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
8538 if (AOP(right)->code)
8545 assert (!"unhandled pointer type");
8548 /* convert other values into pointers to __data space */
8552 assert (AOP_SIZE(result) == 3);
8554 emitpcode(POC_CLRF, popGet(AOP(result), 2));
8556 emitpcode(POC_MOVLW, popGetLit(tag));
8557 movwf(AOP(result), 2);
8560 addSign(result, max, 0);
8565 /* if they are the same size : or less */
8566 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8568 /* if they are in the same place */
8569 if (pic14_sameRegs(AOP(right),AOP(result)))
8572 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
8573 if (IS_PTR_CONST(rtype))
8574 DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
8575 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
8576 DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
8578 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
8579 emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
8580 emitpcode(POC_MOVWF, popGet(AOP(result),0));
8581 emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
8582 emitpcode(POC_MOVWF, popGet(AOP(result),1));
8583 if(AOP_SIZE(result) <2)
8584 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
8588 /* if they in different places then copy */
8589 size = AOP_SIZE(result);
8592 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8593 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8595 //aopPut(AOP(result),
8596 // aopGet(AOP(right),offset,FALSE,FALSE),
8605 /* so we now know that the size of destination is greater
8606 than the size of the source.
8607 Now, if the next iCode is an operator then we might be
8608 able to optimize the operation without performing a cast.
8610 if(0 && genMixedOperation(ic)) {
8611 /* XXX: cannot optimize: must copy regs! */
8615 /* we move to result for the size of source */
8616 size = AOP_SIZE(right);
8619 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8620 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8624 addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
8627 freeAsmop(right,NULL,ic,TRUE);
8628 freeAsmop(result,NULL,ic,TRUE);
8632 /*-----------------------------------------------------------------*/
8633 /* genDjnz - generate decrement & jump if not zero instrucion */
8634 /*-----------------------------------------------------------------*/
8635 static int genDjnz (iCode *ic, iCode *ifx)
8639 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8644 /* if the if condition has a false label
8645 then we cannot save */
8649 /* if the minus is not of the form
8651 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8652 !IS_OP_LITERAL(IC_RIGHT(ic)))
8655 if (operandLitValue(IC_RIGHT(ic)) != 1)
8658 /* if the size of this greater than one then no
8660 if (getSize(operandType(IC_RESULT(ic))) > 1)
8663 /* otherwise we can save BIG */
8664 lbl = newiTempLabel(NULL);
8665 lbl1= newiTempLabel(NULL);
8667 aopOp(IC_RESULT(ic),ic,FALSE);
8669 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
8670 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
8672 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8677 /*-----------------------------------------------------------------*/
8678 /* genReceive - generate code for a receive iCode */
8679 /*-----------------------------------------------------------------*/
8680 static void genReceive (iCode *ic)
8683 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8685 if (isOperandInFarSpace(IC_RESULT(ic)) &&
8686 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8687 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8689 int size = getSize(operandType(IC_RESULT(ic)));
8690 int offset = fReturnSizePic - size;
8692 pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
8693 fReturn[fReturnSizePic - offset - 1] : "acc"));
8696 aopOp(IC_RESULT(ic),ic,FALSE);
8697 size = AOP_SIZE(IC_RESULT(ic));
8700 pic14_emitcode ("pop","acc");
8701 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8706 aopOp(IC_RESULT(ic),ic,FALSE);
8708 GpsuedoStkPtr = ic->parmBytes; // address used arg on stack
8709 assignResultValue(IC_RESULT(ic));
8712 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8715 /*-----------------------------------------------------------------*/
8716 /* genDummyRead - generate code for dummy read of volatiles */
8717 /*-----------------------------------------------------------------*/
8719 genDummyRead (iCode * ic)
8722 pic14_emitcode ("; genDummyRead","");
8723 pic14_emitcode ("; not implemented","");
8728 /*-----------------------------------------------------------------*/
8729 /* genpic14Code - generate code for pic14 based controllers */
8730 /*-----------------------------------------------------------------*/
8732 * At this point, ralloc.c has gone through the iCode and attempted
8733 * to optimize in a way suitable for a PIC. Now we've got to generate
8734 * PIC instructions that correspond to the iCode.
8736 * Once the instructions are generated, we'll pass through both the
8737 * peep hole optimizer and the pCode optimizer.
8738 *-----------------------------------------------------------------*/
8740 void genpic14Code (iCode *lic)
8747 lineHead = lineCurr = NULL;
8749 pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
8752 /* if debug information required */
8753 if (options.debug && debugFile && currFunc) {
8754 debugFile->writeFunction (currFunc, lic);
8758 for (ic = lic ; ic ; ic = ic->next ) {
8760 //DEBUGpic14_emitcode(";ic","");
8761 //fprintf (stderr, "in ic loop\n");
8762 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
8763 //ic->lineno, printCLine(ic->filename, ic->lineno));
8765 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
8767 //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
8768 cline = printCLine (ic->filename, ic->lineno);
8769 if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
8770 addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
8771 //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
8774 if (options.iCodeInAsm) {
8775 const char *iLine = printILine(ic);
8776 emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
8779 /* if the result is marked as
8780 spilt and rematerializable or code for
8781 this has already been generated then
8783 if (resultRemat(ic) || ic->generated )
8786 /* depending on the operation */
8805 /* IPOP happens only when trying to restore a
8806 spilt live range, if there is an ifx statement
8807 following this pop then the if statement might
8808 be using some of the registers being popped which
8809 would destory the contents of the register so
8810 we need to check for this condition and handle it */
8812 ic->next->op == IFX &&
8813 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
8814 genIfx (ic->next,ic);
8832 genEndFunction (ic);
8852 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8869 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
8873 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8880 /* note these two are xlated by algebraic equivalence
8881 during parsing SDCC.y */
8882 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8883 "got '>=' or '<=' shouldn't have come here");
8887 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8899 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8903 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8907 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8934 case GET_VALUE_AT_ADDRESS:
8939 if (POINTER_SET(ic))
8966 addSet(&_G.sendSet,ic);
8969 case DUMMY_READ_VOLATILE:
8974 fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
8981 /* now we are ready to call the
8982 peep hole optimizer */
8983 if (!options.nopeep) {
8984 peepHole (&lineHead);
8986 /* now do the actual printing */
8987 printLine (lineHead,codeOutBuf);
8990 DFPRINTF((stderr,"printing pBlock\n\n"));
8991 printpBlock(stdout,pb);
8997 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
8998 * (meaning: representing its own address) or not (referencing its contents).
8999 * This can only be decided based on the operand's type. */
9001 aop_isLitLike (asmop *aop)
9004 if (aop->type == AOP_LIT) return 1;
9005 if (aop->type == AOP_IMMD) return 1;
9006 if ((aop->type == AOP_PCODE) &&
9007 ((aop->aopu.pcop->type == PO_LITERAL)))
9009 /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
9010 * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
9017 op_isLitLike (operand *op)
9020 if (aop_isLitLike (AOP(op))) return 1;
9021 if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
9022 if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;