1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for pic
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 PIC port - Scott Dattalo scott@dattalo.com (2000)
8 cont'd - Raphael Neider <rneider AT web.de> (2005)
10 This program is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the
12 Free Software Foundation; either version 2, or (at your option) any
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 In other words, you are welcome to use, share and improve this program.
25 You are forbidden to forbid anyone else to use, share and improve
26 what you give them. Help stamp out software-hoarding!
29 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
30 Made everything static
31 -------------------------------------------------------------------------*/
34 * This is the down and dirty file with all kinds of
35 * kludgy & hacky stuff. This is what it is all about
36 * CODE GENERATION for a specific MCU . some of the
37 * routines may be reusable, will have to see.
46 extern struct dbuf_s *codeOutBuf;
50 static pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
51 static pCodeOp *popRegFromString(char *str, int size, int offset);
52 static int aop_isLitLike(asmop *aop);
54 /* The PIC port(s) need not differentiate between POINTER and FPOINTER. */
55 #define PIC_IS_DATA_PTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
58 * max_key keeps track of the largest label number used in
59 * a function. This is then used to adjust the label offset
60 * for the next function.
62 static int max_key = 0;
63 static int labelOffset = 0;
64 static int GpsuedoStkPtr = 0;
65 static int pic14_inISR = 0;
67 static char *zero = "0x00";
68 static char *one = "0x01";
69 static char *spname = "sp";
71 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
72 static char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
73 static char **fReturn = fReturnpic14;
84 * Resolved ifx structure. This structure stores information
85 * about an iCode ifx that makes it easier to generate code.
87 typedef struct resolvedIfx {
88 symbol *lbl; /* pointer to a label */
89 int condition; /* true or false ifx */
90 int generated; /* set true when the code associated with the ifx
94 static lineNode *lineHead = NULL;
95 static lineNode *lineCurr = NULL;
98 /*-----------------------------------------------------------------*/
99 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
100 /* exponent of 2 is returned, otherwise -1 is */
102 /* note that this is similar to the function `powof2' in SDCCsymt */
106 /*-----------------------------------------------------------------*/
107 static int my_powof2 (unsigned long num)
110 if( (num & (num-1)) == 0) {
123 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
126 DEBUGpic14_emitcode ("; ","line = %d result %s=%s, size=%d, left %s=%s, size=%d, right %s=%s, size=%d",
128 ((result) ? AopType(AOP_TYPE(result)) : "-"),
129 ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
130 ((result) ? AOP_SIZE(result) : 0),
131 ((left) ? AopType(AOP_TYPE(left)) : "-"),
132 ((left) ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
133 ((left) ? AOP_SIZE(left) : 0),
134 ((right) ? AopType(AOP_TYPE(right)) : "-"),
135 ((right) ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
136 ((right) ? AOP_SIZE(right) : 0));
140 static void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
143 DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
145 ((result) ? AopType(AOP_TYPE(result)) : "-"),
146 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
147 ((left) ? AopType(AOP_TYPE(left)) : "-"),
148 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
149 ((right) ? AopType(AOP_TYPE(right)) : "-"),
150 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
154 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
157 char lb[INITIAL_INLINEASM];
158 unsigned char *lbp = (unsigned char *)lb;
160 if(!debug_verbose && !options.debug)
167 sprintf(lb,"%s\t",inst);
169 sprintf(lb,"%s",inst);
170 vsprintf(lb+(strlen(lb)),fmt,ap);
174 while (isspace(*lbp)) lbp++;
177 lineCurr = (lineCurr ?
178 connectLine(lineCurr,newLineNode(lb)) :
179 (lineHead = newLineNode(lb)));
180 lineCurr->isInline = _G.inLine;
181 lineCurr->isDebug = _G.debugLine;
183 addpCode2pBlock(pb,newpCodeCharP(lb));
188 static void Safe_vsnprintf (char *buf, size_t size, const char *fmt, va_list ap)
190 #if defined (HAVE_VSNPRINTF)
191 vsnprintf (buf, size, fmt, ap);
192 #elif defined (HAVE_VSPRINTF)
193 vsprintf (buf, size, fmt, ap);
194 if (strlen (buf) >= size)
196 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
198 #elif defined (HAVE_SNPRINTF)
199 snprintf (buf, size, "vs(n)printf required");
200 #elif defined (HAVE_SRINTF)
201 sprintf (buf, "vs(n)printf required");
202 if (strlen (buf) >= size)
204 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
207 assert ( !"neither vsnprintf nor vsprintf is present -- unable to proceed" );
211 void emitpComment (const char *fmt, ...)
218 Safe_vsnprintf (buffer, 4096, fmt, va);
219 //fprintf (stderr, "%s\n" ,buffer);
220 addpCode2pBlock (pb, newpCodeCharP (buffer));
223 Safe_vsnprintf (buffer, 4096, fmt, va);
224 fprintf (stderr, "No current pBlock -- discarding comment [%s]\n", buffer);
230 void emitpLabel(int key)
232 addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
235 /* gen.h defines a macro emitpcode that should be used to call emitpcode
236 * as this allows for easy debugging (ever asked the question: where was
237 * this instruction geenrated? Here is the answer... */
238 void emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
241 addpCode2pBlock(pb,newpCode(poc,pcop));
243 static int has_warned = 0;
245 DEBUGpic14_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
248 fprintf( stderr, "WARNING: encountered NULL pcop--this is probably a compiler bug...\n" );
253 static void emitpcodeNULLop(PIC_OPCODE poc)
256 addpCode2pBlock(pb,newpCode(poc,NULL));
261 /*-----------------------------------------------------------------*/
262 /* pic14_emitcode - writes the code into a file : for now it is simple */
263 /*-----------------------------------------------------------------*/
264 void pic14_emitcode (char *inst,char *fmt, ...)
267 char lb[INITIAL_INLINEASM];
274 sprintf(lb,"%s\t",inst);
276 sprintf(lb,"%s",inst);
277 vsprintf(lb+(strlen(lb)),fmt,ap);
281 while (isspace(*lbp)) lbp++;
284 lineCurr = (lineCurr ?
285 connectLine(lineCurr,newLineNode(lb)) :
286 (lineHead = newLineNode(lb)));
287 lineCurr->isInline = _G.inLine;
288 lineCurr->isDebug = _G.debugLine;
289 lineCurr->isLabel = (lbp[strlen (lbp) - 1] == ':');
292 addpCode2pBlock(pb,newpCodeCharP(lb));
297 /*-----------------------------------------------------------------*/
298 /* pic14_emitDebuggerSymbol - associate the current code location */
299 /* with a debugger symbol */
300 /*-----------------------------------------------------------------*/
302 pic14_emitDebuggerSymbol (char * debugSym)
305 pic14_emitcode ("", ";%s ==.", debugSym);
309 /*-----------------------------------------------------------------*/
310 /* newAsmop - creates a new asmOp */
311 /*-----------------------------------------------------------------*/
312 static asmop *newAsmop (short type)
316 aop = Safe_calloc(1,sizeof(asmop));
321 /*-----------------------------------------------------------------*/
322 /* resolveIfx - converts an iCode ifx into a form more useful for */
323 /* generating code */
324 /*-----------------------------------------------------------------*/
325 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
330 // DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
332 resIfx->condition = 1; /* assume that the ifx is true */
333 resIfx->generated = 0; /* indicate that the ifx has not been used */
336 resIfx->lbl = NULL; /* this is wrong: newiTempLabel(NULL); / * oops, there is no ifx. so create a label */
338 DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
339 __FUNCTION__,__LINE__,resIfx->lbl->key);
343 resIfx->lbl = IC_TRUE(ifx);
345 resIfx->lbl = IC_FALSE(ifx);
346 resIfx->condition = 0;
350 DEBUGpic14_emitcode("; ***","ifx true is non-null");
352 DEBUGpic14_emitcode("; ***","ifx false is non-null");
356 // DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
359 /*-----------------------------------------------------------------*/
360 /* pointerCode - returns the code for a pointer type */
361 /*-----------------------------------------------------------------*/
363 static int pointerCode (sym_link *etype)
366 return PTR_TYPE(SPEC_OCLS(etype));
371 /*-----------------------------------------------------------------*/
372 /* aopForSym - for a true symbol */
373 /*-----------------------------------------------------------------*/
374 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
377 memmap *space= SPEC_OCLS(sym->etype);
379 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
380 /* if already has one */
384 //DEBUGpic14_emitcode(";","%d",__LINE__);
385 /* if it is in direct space */
386 if (IN_DIRSPACE(space)) {
387 sym->aop = aop = newAsmop (AOP_DIR);
388 aop->aopu.aop_dir = sym->rname ;
389 aop->size = getSize(sym->type);
390 DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
394 /* special case for a function */
395 if (IS_FUNC(sym->type)) {
397 sym->aop = aop = newAsmop(AOP_PCODE);
398 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
399 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
400 PCOI(aop->aopu.pcop)->_function = 1;
401 PCOI(aop->aopu.pcop)->index = 0;
402 aop->size = FPTRSIZE;
404 sym->aop = aop = newAsmop(AOP_IMMD);
405 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
406 strcpy(aop->aopu.aop_immd,sym->rname);
407 aop->size = FPTRSIZE;
409 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
413 if (IS_ARRAY(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 = 0;
418 PCOI(aop->aopu.pcop)->index = 0;
419 aop->size = getSize(sym->etype) * DCL_ELEM(sym->type);
421 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
425 /* only remaining is far space */
426 /* in which case DPTR gets the address */
427 sym->aop = aop = newAsmop(AOP_PCODE);
429 aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
430 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
431 PCOI(aop->aopu.pcop)->index = 0;
433 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
434 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
436 allocDirReg (IC_LEFT(ic));
438 aop->size = FPTRSIZE;
440 /* if it is in code space */
441 if (IN_CODESPACE(space))
447 /*-----------------------------------------------------------------*/
448 /* aopForRemat - rematerialzes an object */
449 /*-----------------------------------------------------------------*/
450 static asmop *aopForRemat (operand *op) // x symbol *sym)
452 symbol *sym = OP_SYMBOL(op);
454 asmop *aop = newAsmop(AOP_PCODE);
458 ic = sym->rematiCode;
460 DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
461 if(IS_OP_POINTER(op)) {
462 DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
466 val += (int) operandLitValue(IC_RIGHT(ic));
467 } else if (ic->op == '-') {
468 val -= (int) operandLitValue(IC_RIGHT(ic));
472 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
475 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
476 aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
477 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
478 PCOI(aop->aopu.pcop)->index = val;
480 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
481 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
482 val, IS_PTR_CONST(operandType(op)));
484 // DEBUGpic14_emitcode(";","aop type %s",AopType(AOP_TYPE(IC_LEFT(ic))));
486 allocDirReg (IC_LEFT(ic));
491 static int aopIdx (asmop *aop, int offset)
496 if(aop->type != AOP_REG)
499 return aop->aopu.aop_reg[offset]->rIdx;
502 /*-----------------------------------------------------------------*/
503 /* regsInCommon - two operands have some registers in common */
504 /*-----------------------------------------------------------------*/
505 static bool regsInCommon (operand *op1, operand *op2)
510 /* if they have registers in common */
511 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
514 sym1 = OP_SYMBOL(op1);
515 sym2 = OP_SYMBOL(op2);
517 if (sym1->nRegs == 0 || sym2->nRegs == 0)
520 for (i = 0 ; i < sym1->nRegs ; i++) {
525 for (j = 0 ; j < sym2->nRegs ;j++ ) {
529 if (sym2->regs[j] == sym1->regs[i])
537 /*-----------------------------------------------------------------*/
538 /* operandsEqu - equivalent */
539 /*-----------------------------------------------------------------*/
540 static bool operandsEqu ( operand *op1, operand *op2)
544 /* if they not symbols */
545 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
548 sym1 = OP_SYMBOL(op1);
549 sym2 = OP_SYMBOL(op2);
551 /* if both are itemps & one is spilt
552 and the other is not then false */
553 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
554 sym1->isspilt != sym2->isspilt )
557 /* if they are the same */
561 if (sym1->rname[0] && sym2->rname[0]
562 && strcmp (sym1->rname, sym2->rname) == 0)
566 /* if left is a tmp & right is not */
570 (sym1->usl.spillLoc == sym2))
577 (sym2->usl.spillLoc == sym1))
583 /*-----------------------------------------------------------------*/
584 /* pic14_sameRegs - two asmops have the same registers */
585 /*-----------------------------------------------------------------*/
586 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
593 if (aop1->type != AOP_REG ||
594 aop2->type != AOP_REG )
597 if (aop1->size != aop2->size )
600 for (i = 0 ; i < aop1->size ; i++ )
601 if (aop1->aopu.aop_reg[i] !=
602 aop2->aopu.aop_reg[i] )
608 /*-----------------------------------------------------------------*/
609 /* aopOp - allocates an asmop for an operand : */
610 /*-----------------------------------------------------------------*/
611 void aopOp (operand *op, iCode *ic, bool result)
620 /* if this a literal */
621 if (IS_OP_LITERAL(op)) {
622 op->aop = aop = newAsmop(AOP_LIT);
623 aop->aopu.aop_lit = op->operand.valOperand;
624 aop->size = getSize(operandType(op));
629 sym_link *type = operandType(op);
630 if(IS_PTR_CONST(type))
631 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
634 /* if already has a asmop then continue */
638 /* if the underlying symbol has a aop */
639 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
640 DEBUGpic14_emitcode(";","%d",__LINE__);
641 op->aop = OP_SYMBOL(op)->aop;
645 /* if this is a true symbol */
646 if (IS_TRUE_SYMOP(op)) {
647 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
648 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
652 /* this is a temporary : this has
658 e) can be a return use only */
663 /* if the type is a conditional */
664 if (sym->regType == REG_CND) {
665 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
670 /* if it is spilt then two situations
672 b) has a spill location */
673 if (sym->isspilt || sym->nRegs == 0) {
675 DEBUGpic14_emitcode(";","%d",__LINE__);
676 /* rematerialize it NOW */
679 sym->aop = op->aop = aop = aopForRemat (op);
680 aop->size = getSize(sym->type);
681 //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
686 if(sym->isptr) { // && sym->uptr
687 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
688 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
690 //PCOI(aop->aopu.pcop)->_const = 0;
691 //PCOI(aop->aopu.pcop)->index = 0;
693 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
694 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
696 //allocDirReg (IC_LEFT(ic));
698 aop->size = getSize(sym->type);
699 DEBUGpic14_emitcode(";","%d",__LINE__);
706 aop = op->aop = sym->aop = newAsmop(AOP_STR);
707 aop->size = getSize(sym->type);
708 for ( i = 0 ; i < fReturnSizePic ; i++ )
709 aop->aopu.aop_str[i] = fReturn[i];
711 DEBUGpic14_emitcode(";","%d",__LINE__);
716 /* else spill location */
717 if (sym->usl.spillLoc)
719 asmop *oldAsmOp = NULL;
721 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
723 /* force a new aop if sizes differ */
724 oldAsmOp = sym->usl.spillLoc->aop;
725 sym->usl.spillLoc->aop = NULL;
727 DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
728 __FUNCTION__,__LINE__,
729 sym->usl.spillLoc->rname,
730 sym->rname, sym->usl.spillLoc->offset);
732 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
733 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
735 /* Don't reuse the new aop, go with the last one */
736 sym->usl.spillLoc->aop = oldAsmOp;
738 //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
739 aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname,
741 sym->usl.spillLoc->offset);
742 aop->size = getSize(sym->type);
749 sym_link *type = operandType(op);
750 if(IS_PTR_CONST(type))
751 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
754 /* must be in a register */
755 DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
756 sym->aop = op->aop = aop = newAsmop(AOP_REG);
757 aop->size = sym->nRegs;
758 for ( i = 0 ; i < sym->nRegs ;i++)
759 aop->aopu.aop_reg[i] = sym->regs[i];
762 /*-----------------------------------------------------------------*/
763 /* freeAsmop - free up the asmop given to an operand */
764 /*----------------------------------------------------------------*/
765 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
779 /* all other cases just dealloc */
783 OP_SYMBOL(op)->aop = NULL;
784 /* if the symbol has a spill */
786 SPIL_LOC(op)->aop = NULL;
791 /*-----------------------------------------------------------------*/
792 /* pic14aopLiteral - string from a literal value */
793 /*-----------------------------------------------------------------*/
794 static unsigned int pic14aopLiteral (value *val, int offset)
801 /* if it is a float then it gets tricky */
802 /* otherwise it is fairly simple */
803 if (!IS_FLOAT(val->type)) {
804 unsigned long v = ulFromVal (val);
806 return ( (v >> (offset * 8)) & 0xff);
809 /* it is type float */
810 fl.f = (float) floatFromVal(val);
811 #ifdef WORDS_BIGENDIAN
812 return fl.c[3-offset];
818 /*-----------------------------------------------------------------*/
819 /* aopGet - for fetching value of the aop */
820 /*-----------------------------------------------------------------*/
821 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
826 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
827 /* offset is greater than
830 if (offset > (aop->size - 1) &&
831 aop->type != AOP_LIT)
834 /* depending on type */
839 sprintf (s,"%s",aop->aopu.aop_immd);
842 sprintf(s,"(%s >> %d)",
848 DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
849 rs = Safe_calloc(1,strlen(s)+1);
855 sprintf(s,"(%s + %d)",
858 DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
860 sprintf(s,"%s",aop->aopu.aop_dir);
861 rs = Safe_calloc(1,strlen(s)+1);
867 // return aop->aopu.aop_reg[offset]->dname;
869 return aop->aopu.aop_reg[offset]->name;
872 //pic14_emitcode(";","%d",__LINE__);
873 return aop->aopu.aop_dir;
876 sprintf(s, "0x%02x", pic14aopLiteral (aop->aopu.aop_lit, offset));
882 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
885 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
887 return aop->aopu.aop_str[offset];
891 pCodeOp *pcop = aop->aopu.pcop;
892 DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
894 if (pcop->type == PO_IMMEDIATE) {
895 offset += PCOI(pcop)->index;
898 DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
899 sprintf(s,"(%s+%d)", pcop->name,offset);
901 DEBUGpic14_emitcode(";","%s",pcop->name);
902 sprintf(s,"%s", pcop->name);
905 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
908 rs = Safe_calloc(1,strlen(s)+1);
914 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
915 "aopget got unsupported aop->type");
920 /*-----------------------------------------------------------------*/
921 /* popGetTempReg - create a new temporary pCodeOp */
922 /*-----------------------------------------------------------------*/
923 static pCodeOp *popGetTempReg(void)
928 pcop = newpCodeOp(NULL, PO_GPR_TEMP);
929 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
930 PCOR(pcop)->r->wasUsed=1;
931 PCOR(pcop)->r->isFree=0;
937 /*-----------------------------------------------------------------*/
938 /* popReleaseTempReg - create a new temporary pCodeOp */
939 /*-----------------------------------------------------------------*/
940 static void popReleaseTempReg(pCodeOp *pcop)
943 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
944 PCOR(pcop)->r->isFree = 1;
947 /*-----------------------------------------------------------------*/
948 /* popGetLabel - create a new pCodeOp of type PO_LABEL */
949 /*-----------------------------------------------------------------*/
950 pCodeOp *popGetLabel(unsigned int key)
953 DEBUGpic14_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, labelOffset);
955 if(key>(unsigned int)max_key)
958 return newpCodeOpLabel(NULL,key+100+labelOffset);
961 /*-------------------------------------------------------------------*/
962 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
963 /*-------------------------------------------------------------------*/
964 static pCodeOp *popGetHighLabel(unsigned int key)
967 pcop = popGetLabel(key);
968 PCOLAB(pcop)->offset = 1;
972 /*-----------------------------------------------------------------*/
973 /* popGetLit - asm operator to pcode operator conversion */
974 /*-----------------------------------------------------------------*/
975 pCodeOp *popGetLit(unsigned int lit)
978 return newpCodeOpLit((unsigned char)lit);
981 /*-----------------------------------------------------------------*/
982 /* popGetImmd - asm operator to pcode immediate conversion */
983 /*-----------------------------------------------------------------*/
984 static pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
987 return newpCodeOpImmd(name, offset,index, 0, is_func);
990 /*-----------------------------------------------------------------*/
991 /* popGetWithString - asm operator to pcode operator conversion */
992 /*-----------------------------------------------------------------*/
993 static pCodeOp *popGetWithString(char *str, int isExtern)
999 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1003 pcop = newpCodeOp(str,PO_STR);
1004 PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1009 pCodeOp *popGetExternal (char *str, int isReg)
1014 pcop = newpCodeOpRegFromStr(str);
1016 pcop = popGetWithString (str, 1);
1022 for (sym = setFirstItem (externs); sym; sym = setNextItem (externs))
1024 if (!strcmp (str, sym->rname)) break;
1029 sym = newSymbol(str, 0);
1030 strncpy(sym->rname, str, SDCC_NAME_MAX);
1031 addSet (&externs, sym);
1038 /*-----------------------------------------------------------------*/
1039 /* popRegFromString - */
1040 /*-----------------------------------------------------------------*/
1041 static pCodeOp *popRegFromString(char *str, int size, int offset)
1044 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1045 pcop->type = PO_DIR;
1047 DEBUGpic14_emitcode(";","%d",__LINE__);
1052 pcop->name = Safe_calloc(1,strlen(str)+1);
1053 strcpy(pcop->name,str);
1055 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1057 PCOR(pcop)->r = dirregWithName(pcop->name);
1058 if(PCOR(pcop)->r == NULL) {
1059 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1060 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1061 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1063 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1065 PCOR(pcop)->instance = offset;
1070 /*-----------------------------------------------------------------*/
1071 /*-----------------------------------------------------------------*/
1072 static pCodeOp *popRegFromIdx(int rIdx)
1076 DEBUGpic14_emitcode ("; ***","%s,%d , rIdx=0x%x",
1077 __FUNCTION__,__LINE__,rIdx);
1079 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1081 PCOR(pcop)->rIdx = rIdx;
1082 PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1083 PCOR(pcop)->r->isFree = 0;
1084 PCOR(pcop)->r->wasUsed = 1;
1086 pcop->type = PCOR(pcop)->r->pc_type;
1092 /*-----------------------------------------------------------------*/
1093 /* popGet - asm operator to pcode operator conversion */
1094 /*-----------------------------------------------------------------*/
1095 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1097 //char *s = buffer ;
1102 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1103 /* offset is greater than
1109 /* XXX: still needed for BIT operands (AOP_CRY) */
1110 if (offset > (aop->size - 1) &&
1111 aop->type != AOP_LIT &&
1112 aop->type != AOP_PCODE)
1114 printf( "%s: (offset[%d] > AOP_SIZE(op)[%d]-1) && AOP_TYPE(op) != AOP_LIT)\n", __FUNCTION__, offset, aop->size);
1115 return NULL; //zero;
1118 /* depending on type */
1119 switch (aop->type) {
1122 DEBUGpic14_emitcode(";","%d",__LINE__);
1123 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1126 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1128 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1129 pcop->type = PO_DIR;
1131 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1132 strcpy(pcop->name,aop->aopu.aop_dir);
1133 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1134 if(PCOR(pcop)->r == NULL) {
1135 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1136 PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1137 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1139 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1141 PCOR(pcop)->instance = offset;
1149 assert (offset < aop->size);
1150 rIdx = aop->aopu.aop_reg[offset]->rIdx;
1152 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1153 PCOR(pcop)->rIdx = rIdx;
1154 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1155 PCOR(pcop)->r->wasUsed=1;
1156 PCOR(pcop)->r->isFree=0;
1158 PCOR(pcop)->instance = offset;
1159 pcop->type = PCOR(pcop)->r->pc_type;
1160 //rs = aop->aopu.aop_reg[offset]->name;
1161 DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1166 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1167 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1168 //if(PCOR(pcop)->r == NULL)
1169 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1173 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1176 DEBUGpic14_emitcode(";","%d %s",__LINE__,aop->aopu.aop_str[offset]);
1177 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1179 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1180 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1181 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1182 pcop->type = PCOR(pcop)->r->pc_type;
1183 pcop->name = PCOR(pcop)->r->name;
1190 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1192 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1193 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1194 switch (aop->aopu.pcop->type)
1197 pcop = pCodeOpCopy (aop->aopu.pcop);
1198 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1199 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1200 PCOI(pcop)->index += offset;
1201 //PCOI(pcop)->offset = 0;
1204 pcop = pCodeOpCopy (aop->aopu.pcop);
1205 PCOR(pcop)->instance = offset;
1208 assert ( !"unhandled pCode type" );
1214 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1215 "popGet got unsupported aop->type");
1219 /*-----------------------------------------------------------------*/
1220 /* popGetAddr - access the low/high word of a symbol (immediate) */
1221 /* (for non-PO_IMMEDIATEs this is the same as popGet) */
1222 /*-----------------------------------------------------------------*/
1223 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1225 if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1227 pCodeOp *pcop = aop->aopu.pcop;
1228 assert (offset <= GPTRSIZE);
1230 /* special case: index >= 2 should return GPOINTER-style values */
1233 pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1237 pcop = pCodeOpCopy (pcop);
1238 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1239 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1240 PCOI(pcop)->offset += offset;
1241 PCOI(pcop)->index += index;
1242 //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);
1245 return popGet (aop, offset + index);
1249 /*-----------------------------------------------------------------*/
1250 /* aopPut - puts a string for a aop */
1251 /*-----------------------------------------------------------------*/
1252 void aopPut (asmop *aop, char *s, int offset)
1257 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1259 if (aop->size && offset > ( aop->size - 1)) {
1260 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1261 "aopPut got offset > aop->size");
1265 /* will assign value to value */
1266 /* depending on where it is ofcourse */
1267 switch (aop->type) {
1270 sprintf(d,"(%s + %d)",
1271 aop->aopu.aop_dir,offset);
1272 fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1275 sprintf(d,"%s",aop->aopu.aop_dir);
1278 DEBUGpic14_emitcode(";","%d",__LINE__);
1280 pic14_emitcode("movf","%s,w",s);
1281 pic14_emitcode("movwf","%s",d);
1284 pic14_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
1285 if(offset >= aop->size) {
1286 emitpcode(POC_CLRF,popGet(aop,offset));
1289 emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
1292 emitpcode(POC_MOVWF,popGet(aop,offset));
1298 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1301 strcmp(s,"r0") == 0 ||
1302 strcmp(s,"r1") == 0 ||
1303 strcmp(s,"r2") == 0 ||
1304 strcmp(s,"r3") == 0 ||
1305 strcmp(s,"r4") == 0 ||
1306 strcmp(s,"r5") == 0 ||
1307 strcmp(s,"r6") == 0 ||
1308 strcmp(s,"r7") == 0 )
1309 pic14_emitcode("mov","%s,%s ; %d",
1310 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1314 if(strcmp(s,"W")==0 )
1315 pic14_emitcode("movf","%s,w ; %d",s,__LINE__);
1317 pic14_emitcode("movwf","%s",
1318 aop->aopu.aop_reg[offset]->name);
1320 if(strcmp(s,zero)==0) {
1321 emitpcode(POC_CLRF,popGet(aop,offset));
1323 } else if(strcmp(s,"W")==0) {
1324 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1325 pcop->type = PO_GPR_REGISTER;
1327 PCOR(pcop)->rIdx = -1;
1328 PCOR(pcop)->r = NULL;
1330 DEBUGpic14_emitcode(";","%d",__LINE__);
1331 pcop->name = Safe_strdup(s);
1332 emitpcode(POC_MOVFW,pcop);
1333 emitpcode(POC_MOVWF,popGet(aop,offset));
1334 } else if(strcmp(s,one)==0) {
1335 emitpcode(POC_CLRF,popGet(aop,offset));
1336 emitpcode(POC_INCF,popGet(aop,offset));
1338 emitpcode(POC_MOVWF,popGet(aop,offset));
1344 if (strcmp(s,"a") == 0)
1345 pic14_emitcode("push","acc");
1347 pic14_emitcode("push","%s",s);
1352 /* if bit variable */
1353 if (!aop->aopu.aop_dir) {
1354 pic14_emitcode("clr","a");
1355 pic14_emitcode("rlc","a");
1358 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1361 pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1364 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1366 lbl = newiTempLabel(NULL);
1368 if (strcmp(s,"a")) {
1371 pic14_emitcode("clr","c");
1372 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1373 pic14_emitcode("cpl","c");
1374 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1375 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1382 if (strcmp(aop->aopu.aop_str[offset],s))
1383 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1387 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1388 "aopPut got unsupported aop->type");
1394 /*-----------------------------------------------------------------*/
1395 /* mov2w_op - generate either a MOVLW or MOVFW based operand type */
1396 /*-----------------------------------------------------------------*/
1397 static void mov2w_op (operand *op, int offset)
1402 /* for PO_IMMEDIATEs: use address or value? */
1403 if (op_isLitLike (op))
1405 /* access address of op */
1406 if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
1407 if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
1409 if (offset == GPTRSIZE-1)
1410 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1412 emitpcode (POC_MOVLW, popGetLit (0));
1415 emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
1417 /* access value stored in op */
1418 mov2w (AOP(op), offset);
1423 /*-----------------------------------------------------------------*/
1424 /* mov2w - generate either a MOVLW or MOVFW based operand type */
1425 /*-----------------------------------------------------------------*/
1426 void mov2w (asmop *aop, int offset)
1432 DEBUGpic14_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
1434 if ( aop_isLitLike (aop) )
1435 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1437 emitpcode(POC_MOVFW,popGet(aop,offset));
1441 static void movwf (asmop *op, int offset)
1443 emitpcode (POC_MOVWF, popGet(op, offset));
1446 static pCodeOp *get_argument_pcop (int idx)
1448 assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1449 return popRegFromIdx (Gstack_base_addr - (idx - 1));
1452 static pCodeOp *get_return_val_pcop (int offset)
1454 assert (offset > 0 && "the most significant byte is returned via WREG");
1455 return popRegFromIdx (Gstack_base_addr - (offset - 1));
1458 static void pass_argument (operand *op, int offset, int idx)
1461 mov2w_op (op, offset);
1463 emitpcode(POC_MOVWF, get_argument_pcop (idx));
1466 static void get_returnvalue (operand *op, int offset, int idx)
1469 emitpcode(POC_MOVFW, get_return_val_pcop (idx));
1470 movwf(AOP(op), offset);
1473 static void call_libraryfunc (char *name)
1477 /* library code might reside in different page... */
1478 emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1479 /* call the library function */
1480 emitpcode (POC_CALL, popGetExternal (name, 0));
1481 /* might return from different page... */
1482 emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1484 /* create symbol, mark it as `extern' */
1485 sym = findSym(SymbolTab, NULL, name);
1487 sym = newSymbol(name, 0);
1488 strncpy(sym->rname, name, SDCC_NAME_MAX);
1489 addSym(SymbolTab, sym, sym->rname, 0, 0, 0);
1490 addSet(&externs, sym);
1495 /*-----------------------------------------------------------------*/
1496 /* pic14_getDataSize - get the operand data size */
1497 /*-----------------------------------------------------------------*/
1498 int pic14_getDataSize(operand *op)
1502 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1505 size = getSize(OP_SYM_ETYPE(op));
1507 //return AOP_SIZE(op);
1509 // tsd- in the pic port, the genptr size is 1, so this code here
1510 // fails. ( in the 8051 port, the size was 4).
1512 size = AOP_SIZE(op);
1513 if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)))
1515 sym_link *type = operandType(op);
1516 if (IS_GENPTR(type))
1518 /* generic pointer; arithmetic operations
1519 * should ignore the high byte (pointer type).
1522 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1529 /*-----------------------------------------------------------------*/
1530 /* pic14_outAcc - output Acc */
1531 /*-----------------------------------------------------------------*/
1532 void pic14_outAcc(operand *result)
1535 DEBUGpic14_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
1536 DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1539 size = pic14_getDataSize(result);
1541 emitpcode(POC_MOVWF,popGet(AOP(result),0));
1544 /* unsigned or positive */
1546 emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1551 /*-----------------------------------------------------------------*/
1552 /* pic14_outBitC - output a bit C */
1553 /*-----------------------------------------------------------------*/
1554 static void pic14_outBitC(operand *result)
1557 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1558 /* if the result is bit */
1559 if (AOP_TYPE(result) == AOP_CRY)
1560 aopPut(AOP(result),"c",0);
1562 pic14_emitcode("clr","a ; %d", __LINE__);
1563 pic14_emitcode("rlc","a");
1564 pic14_outAcc(result);
1568 /*-----------------------------------------------------------------*/
1569 /* pic14_toBoolean - emit code for orl a,operator(sizeop) */
1570 /*-----------------------------------------------------------------*/
1571 static void pic14_toBoolean(operand *oper)
1573 int size = AOP_SIZE(oper);
1576 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1581 /* MOVFW does not load the flags... */
1582 emitpcode(POC_MOVLW, popGetLit(0));
1585 emitpcode(POC_MOVFW,popGet(AOP(oper),0));
1589 while (offset < size) {
1590 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
1592 /* Z is set iff (oper == 0) */
1596 /*-----------------------------------------------------------------*/
1597 /* genNot - generate code for ! operation */
1598 /*-----------------------------------------------------------------*/
1599 static void genNot (iCode *ic)
1606 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1607 /* assign asmOps to operand & result */
1608 aopOp (IC_LEFT(ic),ic,FALSE);
1609 aopOp (IC_RESULT(ic),ic,TRUE);
1611 DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1612 /* if in bit space then a special case */
1613 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1614 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1615 emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
1616 emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
1618 emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
1619 emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
1620 emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
1625 size = AOP_SIZE(IC_LEFT(ic));
1626 mov2w (AOP(IC_LEFT(ic)),0);
1629 if (op_isLitLike (IC_LEFT(ic)))
1630 emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
1632 emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
1634 emitpcode(POC_MOVLW, popGetLit (0));
1636 emitpcode(POC_MOVLW, popGetLit (1));
1637 movwf(AOP(IC_RESULT(ic)), 0);
1639 for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
1641 emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
1646 /* release the aops */
1647 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1648 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1652 /*-----------------------------------------------------------------*/
1653 /* genCpl - generate code for complement */
1654 /*-----------------------------------------------------------------*/
1655 static void genCpl (iCode *ic)
1657 operand *left, *result;
1662 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1663 aopOp((left = IC_LEFT(ic)),ic,FALSE);
1664 aopOp((result=IC_RESULT(ic)),ic,TRUE);
1666 /* if both are in bit space then
1668 if (AOP_TYPE(result) == AOP_CRY &&
1669 AOP_TYPE(left) == AOP_CRY ) {
1671 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir);
1672 pic14_emitcode("cpl","c");
1673 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir);
1677 size = AOP_SIZE(result);
1678 if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
1680 emitpcode(POC_COMFW,popGet(AOP(left),offset));
1681 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
1684 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
1688 /* release the aops */
1689 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1690 freeAsmop(result,NULL,ic,TRUE);
1693 /*-----------------------------------------------------------------*/
1694 /* genUminusFloat - unary minus for floating points */
1695 /*-----------------------------------------------------------------*/
1696 static void genUminusFloat(operand *op,operand *result)
1698 int size ,offset =0 ;
1703 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1704 /* for this we just need to flip the
1705 first it then copy the rest in place */
1706 size = AOP_SIZE(op) - 1;
1707 l = aopGet(AOP(op),3,FALSE,FALSE);
1711 pic14_emitcode("cpl","acc.7");
1712 aopPut(AOP(result),"a",3);
1716 aopGet(AOP(op),offset,FALSE,FALSE),
1722 /*-----------------------------------------------------------------*/
1723 /* genUminus - unary minus code generation */
1724 /*-----------------------------------------------------------------*/
1725 static void genUminus (iCode *ic)
1728 sym_link *optype, *rtype;
1732 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1734 aopOp(IC_LEFT(ic),ic,FALSE);
1735 aopOp(IC_RESULT(ic),ic,TRUE);
1737 /* if both in bit space then special
1739 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1740 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1742 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0));
1743 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
1744 emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0));
1749 optype = operandType(IC_LEFT(ic));
1750 rtype = operandType(IC_RESULT(ic));
1752 /* if float then do float stuff */
1753 if (IS_FLOAT(optype)) {
1754 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1758 /* otherwise subtract from zero by taking the 2's complement */
1759 size = AOP_SIZE(IC_LEFT(ic));
1761 for(i=0; i<size; i++) {
1762 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
1763 emitpcode(POC_COMF, popGet(AOP(IC_LEFT(ic)),i));
1765 emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
1766 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
1770 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0));
1771 for(i=1; i<size; i++) {
1773 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),i));
1777 /* release the aops */
1778 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1779 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1782 /*-----------------------------------------------------------------*/
1783 /* saverbank - saves an entire register bank on the stack */
1784 /*-----------------------------------------------------------------*/
1785 static void saverbank (int bank, iCode *ic, bool pushPsw)
1789 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
1795 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1796 if (options.useXstack) {
1799 r = getFreePtr(ic,&aop,FALSE);
1800 pic14_emitcode("mov","%s,_spx",r->name);
1804 for (i = 0 ; i < pic14_nRegs ;i++) {
1805 if (options.useXstack) {
1806 pic14_emitcode("inc","%s",r->name);
1807 //pic14_emitcode("mov","a,(%s+%d)",
1808 // regspic14[i].base,8*bank+regspic14[i].offset);
1809 pic14_emitcode("movx","@%s,a",r->name);
1811 pic14_emitcode("push","");// "(%s+%d)",
1812 //regspic14[i].base,8*bank+regspic14[i].offset);
1816 if (options.useXstack) {
1817 pic14_emitcode("mov","a,psw");
1818 pic14_emitcode("movx","@%s,a",r->name);
1819 pic14_emitcode("inc","%s",r->name);
1820 pic14_emitcode("mov","_spx,%s",r->name);
1821 freeAsmop (NULL,aop,ic,TRUE);
1824 pic14_emitcode("push","psw");
1826 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1832 /*-----------------------------------------------------------------*/
1833 /* saveRegisters - will look for a call and save the registers */
1834 /*-----------------------------------------------------------------*/
1835 static void saveRegisters(iCode *lic)
1843 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1845 for (ic = lic ; ic ; ic = ic->next)
1846 if (ic->op == CALL || ic->op == PCALL)
1850 fprintf(stderr,"found parameter push with no function call\n");
1854 /* if the registers have been saved already then
1856 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
1859 /* find the registers in use at this time
1860 and push them away to safety */
1861 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1866 //fprintf(stderr, "ERROR: saveRegisters did not do anything to save registers, please report this as a bug.\n");
1868 dtype = operandType(IC_LEFT(ic));
1869 if (currFunc && dtype &&
1870 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
1871 IFFUNC_ISISR(currFunc->type) &&
1874 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
1877 /*-----------------------------------------------------------------*/
1878 /* unsaveRegisters - pop the pushed registers */
1879 /*-----------------------------------------------------------------*/
1880 static void unsaveRegisters (iCode *ic)
1887 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1888 /* find the registers in use at this time
1889 and push them away to safety */
1890 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1893 if (options.useXstack) {
1894 pic14_emitcode("mov","r0,%s",spname);
1895 for (i = pic14_nRegs ; i >= 0 ; i--) {
1896 if (bitVectBitValue(rsave,i)) {
1897 pic14_emitcode("dec","r0");
1898 pic14_emitcode("movx","a,@r0");
1899 pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
1903 pic14_emitcode("mov","%s,r0",spname);
1905 //for (i = pic14_nRegs ; i >= 0 ; i--) {
1906 // if (bitVectBitValue(rsave,i))
1907 // pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
1913 /*-----------------------------------------------------------------*/
1915 /*-----------------------------------------------------------------*/
1916 static void pushSide(operand * oper, int size)
1920 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1922 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1923 if (AOP_TYPE(oper) != AOP_REG &&
1924 AOP_TYPE(oper) != AOP_DIR &&
1926 pic14_emitcode("mov","a,%s",l);
1927 pic14_emitcode("push","acc");
1929 pic14_emitcode("push","%s",l);
1934 /*-----------------------------------------------------------------*/
1935 /* assignResultValue - */
1936 /*-----------------------------------------------------------------*/
1937 static void assignResultValue(operand * oper)
1939 int size = AOP_SIZE(oper);
1944 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1946 DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
1948 /* assign MSB first (passed via WREG) */
1950 get_returnvalue (oper, size, offset + GpsuedoStkPtr);
1956 /*-----------------------------------------------------------------*/
1957 /* genIpush - genrate code for pushing this gets a little complex */
1958 /*-----------------------------------------------------------------*/
1959 static void genIpush (iCode *ic)
1963 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
1965 int size, offset = 0 ;
1969 /* if this is not a parm push : ie. it is spill push
1970 and spill push is always done on the local stack */
1971 if (!ic->parmPush) {
1973 /* and the item is spilt then do nothing */
1974 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1977 aopOp(IC_LEFT(ic),ic,FALSE);
1978 size = AOP_SIZE(IC_LEFT(ic));
1979 /* push it on the stack */
1981 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1986 pic14_emitcode("push","%s",l);
1991 /* this is a paramter push: in this case we call
1992 the routine to find the call and save those
1993 registers that need to be saved */
1996 /* then do the push */
1997 aopOp(IC_LEFT(ic),ic,FALSE);
2000 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2001 size = AOP_SIZE(IC_LEFT(ic));
2004 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2005 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
2006 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2008 pic14_emitcode("mov","a,%s",l);
2009 pic14_emitcode("push","acc");
2011 pic14_emitcode("push","%s",l);
2014 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2018 /*-----------------------------------------------------------------*/
2019 /* genIpop - recover the registers: can happen only for spilling */
2020 /*-----------------------------------------------------------------*/
2021 static void genIpop (iCode *ic)
2025 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2026 assert (!"genIpop -- unimplemented");
2031 /* if the temp was not pushed then */
2032 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2035 aopOp(IC_LEFT(ic),ic,FALSE);
2036 size = AOP_SIZE(IC_LEFT(ic));
2039 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2042 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2046 /*-----------------------------------------------------------------*/
2047 /* unsaverbank - restores the resgister bank from stack */
2048 /*-----------------------------------------------------------------*/
2049 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2053 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2059 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2061 if (options.useXstack) {
2063 r = getFreePtr(ic,&aop,FALSE);
2066 pic14_emitcode("mov","%s,_spx",r->name);
2067 pic14_emitcode("movx","a,@%s",r->name);
2068 pic14_emitcode("mov","psw,a");
2069 pic14_emitcode("dec","%s",r->name);
2072 pic14_emitcode ("pop","psw");
2075 for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2076 if (options.useXstack) {
2077 pic14_emitcode("movx","a,@%s",r->name);
2078 //pic14_emitcode("mov","(%s+%d),a",
2079 // regspic14[i].base,8*bank+regspic14[i].offset);
2080 pic14_emitcode("dec","%s",r->name);
2083 pic14_emitcode("pop",""); //"(%s+%d)",
2084 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2087 if (options.useXstack) {
2089 pic14_emitcode("mov","_spx,%s",r->name);
2090 freeAsmop(NULL,aop,ic,TRUE);
2096 /*-----------------------------------------------------------------*/
2097 /* genCall - generates a call statement */
2098 /*-----------------------------------------------------------------*/
2099 static void genCall (iCode *ic)
2108 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2110 /* if caller saves & we have not saved then */
2114 /* if we are calling a function that is not using
2115 the same register bank then we need to save the
2116 destination registers on the stack */
2117 dtype = operandType(IC_LEFT(ic));
2118 if (currFunc && dtype &&
2119 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2120 IFFUNC_ISISR(currFunc->type) &&
2123 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2125 /* if send set is not empty the assign */
2128 /* For the Pic port, there is no data stack.
2129 * So parameters passed to functions are stored
2130 * in registers. (The pCode optimizer will get
2131 * rid of most of these :).
2133 int psuedoStkPtr=-1;
2134 int firstTimeThruLoop = 1;
2136 _G.sendSet = reverseSet(_G.sendSet);
2138 /* First figure how many parameters are getting passed */
2139 for (sic = setFirstItem(_G.sendSet) ; sic ;
2140 sic = setNextItem(_G.sendSet)) {
2142 aopOp(IC_LEFT(sic),sic,FALSE);
2143 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2144 freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2147 for (sic = setFirstItem(_G.sendSet) ; sic ;
2148 sic = setNextItem(_G.sendSet)) {
2149 int size, offset = 0;
2151 aopOp(IC_LEFT(sic),sic,FALSE);
2152 size = AOP_SIZE(IC_LEFT(sic));
2155 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2156 AopType(AOP_TYPE(IC_LEFT(sic))));
2158 if(!firstTimeThruLoop) {
2159 /* If this is not the first time we've been through the loop
2160 * then we need to save the parameter in a temporary
2161 * register. The last byte of the last parameter is
2163 emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2166 firstTimeThruLoop=0;
2168 mov2w_op (IC_LEFT(sic), offset);
2171 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2176 sym = OP_SYMBOL(IC_LEFT(ic));
2177 name = sym->rname[0] ? sym->rname : sym->name;
2179 * As SDCC emits code as soon as it reaches the end of each
2180 * function's definition, prototyped functions that are implemented
2181 * after the current one are always considered EXTERN, which
2182 * introduces many unneccessary PAGESEL instructions.
2183 * XXX: Use a post pass to iterate over all `CALL _name' statements
2184 * and insert `PAGESEL _name' and `PAGESEL $' around the CALL
2185 * only iff there is no definition of the function in the whole
2186 * file (might include this in the PAGESEL pass).
2188 isExtern = IS_EXTERN(sym->etype) || pic14_inISR;
2190 /* Extern functions and ISRs maybe on a different page;
2191 * must call pagesel */
2192 emitpcode(POC_PAGESEL,popGetWithString(name,1));
2194 emitpcode(POC_CALL,popGetWithString(name,isExtern));
2196 /* May have returned from a different page;
2197 * must use pagesel to restore PCLATH before next
2198 * goto or call instruction */
2199 emitpcode(POC_PAGESEL,popGetWithString("$",0));
2202 /* if we need assign a result value */
2203 if ((IS_ITEMP(IC_RESULT(ic)) &&
2204 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2205 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2206 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2209 aopOp(IC_RESULT(ic),ic,FALSE);
2212 assignResultValue(IC_RESULT(ic));
2214 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2215 AopType(AOP_TYPE(IC_RESULT(ic))));
2217 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2220 /* if register bank was saved then pop them */
2222 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2224 /* if we hade saved some registers then unsave them */
2225 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2226 unsaveRegisters (ic);
2231 /*-----------------------------------------------------------------*/
2232 /* genPcall - generates a call by pointer statement */
2233 /*-----------------------------------------------------------------*/
2234 static void genPcall (iCode *ic)
2237 symbol *albl = newiTempLabel(NULL);
2238 symbol *blbl = newiTempLabel(NULL);
2245 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2246 /* if caller saves & we have not saved then */
2250 /* if we are calling a function that is not using
2251 the same register bank then we need to save the
2252 destination registers on the stack */
2253 dtype = operandType(IC_LEFT(ic));
2254 if (currFunc && dtype &&
2255 IFFUNC_ISISR(currFunc->type) &&
2256 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2257 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2260 aopOp(left,ic,FALSE);
2261 DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2263 poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2265 pushSide(IC_LEFT(ic), FPTRSIZE);
2267 /* if send set is not empty, assign parameters */
2270 DEBUGpic14_emitcode ("; ***","%s %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2271 /* no way to pass args - W always gets used to make the call */
2273 /* first idea - factor out a common helper function and call it.
2274 But don't know how to get it generated only once in its own block
2276 if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2279 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2280 DEBUGpic14_emitcode ("; ***","%s %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2281 buffer = Safe_calloc(1,strlen(rname)+16);
2282 sprintf(buffer, "%s_goto_helper", rname);
2283 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2287 emitpcode(POC_CALL,popGetLabel(albl->key));
2288 pcop = popGetLabel(blbl->key);
2289 emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
2290 emitpcode(POC_GOTO,pcop);
2291 emitpLabel(albl->key);
2293 emitpcode(poc,popGetAddr(AOP(left),1,0));
2294 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2295 emitpcode(poc,popGetAddr(AOP(left),0,0));
2296 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2298 emitpLabel(blbl->key);
2300 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2302 /* if we need to assign a result value */
2303 if ((IS_ITEMP(IC_RESULT(ic)) &&
2304 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2305 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2306 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2309 aopOp(IC_RESULT(ic),ic,FALSE);
2314 assignResultValue(IC_RESULT(ic));
2316 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2319 /* if register bank was saved then unsave them */
2320 if (currFunc && dtype &&
2321 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2322 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2324 /* if we hade saved some registers then
2327 unsaveRegisters (ic);
2331 /*-----------------------------------------------------------------*/
2332 /* resultRemat - result is rematerializable */
2333 /*-----------------------------------------------------------------*/
2334 static int resultRemat (iCode *ic)
2336 // DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2339 if (SKIP_IC(ic) || ic->op == IFX)
2342 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2343 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2344 if (sym->remat && !POINTER_SET(ic))
2352 /*-----------------------------------------------------------------*/
2353 /* inExcludeList - return 1 if the string is in exclude Reg list */
2354 /*-----------------------------------------------------------------*/
2355 static bool inExcludeList(char *s)
2357 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2360 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2361 if (options.excludeRegs[i] &&
2362 STRCASECMP(options.excludeRegs[i],"none") == 0)
2365 for ( i = 0 ; options.excludeRegs[i]; i++) {
2366 if (options.excludeRegs[i] &&
2367 STRCASECMP(s,options.excludeRegs[i]) == 0)
2374 /*-----------------------------------------------------------------*/
2375 /* genFunction - generated code for function entry */
2376 /*-----------------------------------------------------------------*/
2377 static void genFunction (iCode *ic)
2384 DEBUGpic14_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2386 labelOffset += (max_key+4);
2390 /* create the function header */
2391 pic14_emitcode(";","-----------------------------------------");
2392 pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2393 pic14_emitcode(";","-----------------------------------------");
2395 /* prevent this symbol from being emitted as 'extern' */
2396 pic14_stringInSet(sym->rname, &pic14_localFunctions, 1);
2398 pic14_emitcode("","%s:",sym->rname);
2399 addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2401 /* mark symbol as NOT extern (even if it was declared so previously) */
2402 assert(IS_SPEC(sym->etype));
2403 SPEC_EXTR(sym->etype) = 0;
2405 if (!SPEC_OCLS(sym->etype)) SPEC_OCLS(sym->etype) = code;
2406 addSetIfnotP(&SPEC_OCLS(sym->etype)->syms, sym);
2408 ftype = operandType(IC_LEFT(ic));
2410 /* if critical function then turn interrupts off */
2411 if (IFFUNC_ISCRITICAL(ftype))
2412 pic14_emitcode("clr","ea");
2414 /* here we need to generate the equates for the
2415 register bank if required */
2417 if (FUNC_REGBANK(ftype) != rbank) {
2420 rbank = FUNC_REGBANK(ftype);
2421 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2422 if (strcmp(regspic14[i].base,"0") == 0)
2423 pic14_emitcode("","%s = 0x%02x",
2425 8*rbank+regspic14[i].offset);
2427 pic14_emitcode ("","%s = %s + 0x%02x",
2430 8*rbank+regspic14[i].offset);
2435 /* if this is an interrupt service routine */
2437 if (IFFUNC_ISISR(sym->type)) {
2439 emitpcode(POC_MOVWF, popCopyReg(&pc_wsave));
2440 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2441 /* XXX: Why? Does this assume that ssave and psave reside
2442 * in a shared bank or bank0? We cannot guarantee the
2445 emitpcode(POC_CLRF, popCopyReg(&pc_status));
2446 emitpcode(POC_MOVWF, popCopyReg(&pc_ssave));
2447 //emitpcode(POC_MOVWF, popGetExternal("___sdcc_saved_status",1 ));
2448 emitpcode(POC_MOVFW, popCopyReg(&pc_pclath));
2449 /* during an interrupt PCLATH must be cleared before a goto or call statement */
2450 emitpcode(POC_CLRF, popCopyReg(&pc_pclath));
2451 emitpcode(POC_MOVWF, popCopyReg(&pc_psave));
2452 //emitpcode(POC_MOVWF, popGetExternal("___sdcc_saved_pclath", 1));
2453 emitpcode(POC_MOVFW, popCopyReg(&pc_fsr));
2454 emitpcode(POC_MOVWF, popGetExternal("___sdcc_saved_fsr", 1));
2456 pBlockConvert2ISR(pb);
2457 pic14_hasInterrupt = 1;
2459 /* if callee-save to be used for this function
2460 then save the registers being used in this function */
2461 if (IFFUNC_CALLEESAVES(sym->type)) {
2464 /* if any registers used */
2465 if (sym->regsUsed) {
2466 /* save the registers used */
2467 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2468 if (bitVectBitValue(sym->regsUsed,i)) {
2469 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2477 /* set the register bank to the desired value */
2478 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2479 pic14_emitcode("push","psw");
2480 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);
2483 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2485 if (options.useXstack) {
2486 pic14_emitcode("mov","r0,%s",spname);
2487 pic14_emitcode("mov","a,_bp");
2488 pic14_emitcode("movx","@r0,a");
2489 pic14_emitcode("inc","%s",spname);
2493 /* set up the stack */
2494 pic14_emitcode ("push","_bp"); /* save the callers stack */
2496 pic14_emitcode ("mov","_bp,%s",spname);
2499 /* adjust the stack for the function */
2504 werror(W_STACK_OVERFLOW,sym->name);
2506 if (i > 3 && sym->recvSize < 4) {
2508 pic14_emitcode ("mov","a,sp");
2509 pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2510 pic14_emitcode ("mov","sp,a");
2515 pic14_emitcode("inc","sp");
2520 pic14_emitcode ("mov","a,_spx");
2521 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2522 pic14_emitcode ("mov","_spx,a");
2527 /*-----------------------------------------------------------------*/
2528 /* genEndFunction - generates epilogue for functions */
2529 /*-----------------------------------------------------------------*/
2530 static void genEndFunction (iCode *ic)
2532 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2536 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2538 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2540 pic14_emitcode ("mov","%s,_bp",spname);
2543 /* if use external stack but some variables were
2544 added to the local stack then decrement the
2546 if (options.useXstack && sym->stack) {
2547 pic14_emitcode("mov","a,sp");
2548 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2549 pic14_emitcode("mov","sp,a");
2553 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2554 if (options.useXstack) {
2555 pic14_emitcode("mov","r0,%s",spname);
2556 pic14_emitcode("movx","a,@r0");
2557 pic14_emitcode("mov","_bp,a");
2558 pic14_emitcode("dec","%s",spname);
2562 pic14_emitcode ("pop","_bp");
2566 /* restore the register bank */
2567 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2568 pic14_emitcode ("pop","psw");
2570 if (IFFUNC_ISISR(sym->type)) {
2572 /* now we need to restore the registers */
2573 /* if this isr has no bank i.e. is going to
2574 run with bank 0 , then we need to save more
2576 if (!FUNC_REGBANK(sym->type)) {
2578 /* if this function does not call any other
2579 function then we can be economical and
2580 save only those registers that are used */
2581 if (! IFFUNC_HASFCALL(sym->type)) {
2584 /* if any registers used */
2585 if (sym->regsUsed) {
2586 /* save the registers used */
2587 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2588 if (bitVectBitValue(sym->regsUsed,i)) {
2589 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2595 /* this function has a function call; cannot
2596 determines register usage so we will have the
2598 unsaverbank(0,ic,FALSE);
2602 /* if debug then send end of function */
2603 if (options.debug && debugFile && currFunc) {
2604 debugFile->writeEndFunction (currFunc, ic, 1);
2607 emitpcode(POC_MOVFW, popGetExternal("___sdcc_saved_fsr", 1));
2608 emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
2609 //emitpcode(POC_MOVFW, popGetExternal("___sdcc_saved_pclath", 1));
2610 emitpcode(POC_MOVFW, popCopyReg(&pc_psave));
2611 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
2612 emitpcode(POC_CLRF, popCopyReg(&pc_status)); // see genFunction
2613 //emitpcode(POC_SWAPFW, popGetExternal("___sdcc_saved_status", 1));
2614 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
2615 emitpcode(POC_MOVWF, popCopyReg(&pc_status));
2616 emitpcode(POC_SWAPF, popCopyReg(&pc_wsave));
2617 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
2618 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
2619 emitpcodeNULLop(POC_RETFIE);
2622 if (IFFUNC_ISCRITICAL(sym->type))
2623 pic14_emitcode("setb","ea");
2625 if (IFFUNC_CALLEESAVES(sym->type)) {
2628 /* if any registers used */
2629 if (sym->regsUsed) {
2630 /* save the registers used */
2631 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2632 if (bitVectBitValue(sym->regsUsed,i)) {
2633 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2639 /* if debug then send end of function */
2640 if (options.debug && debugFile && currFunc) {
2641 debugFile->writeEndFunction (currFunc, ic, 1);
2644 pic14_emitcode ("return","");
2645 emitpcodeNULLop(POC_RETURN);
2647 /* Mark the end of a function */
2648 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
2653 /*-----------------------------------------------------------------*/
2654 /* genRet - generate code for return statement */
2655 /*-----------------------------------------------------------------*/
2656 static void genRet (iCode *ic)
2658 int size,offset = 0;
2662 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2663 /* if we have no return value then
2664 just generate the "ret" */
2668 /* we have something to return then
2669 move the return value into place */
2670 aopOp(IC_LEFT(ic),ic,FALSE);
2671 size = AOP_SIZE(IC_LEFT(ic));
2673 for (offset = 0; offset < size; offset++)
2675 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
2678 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2681 /* generate a jump to the return label
2682 if the next is not the return statement */
2683 if (!(ic->next && ic->next->op == LABEL &&
2684 IC_LABEL(ic->next) == returnLabel)) {
2686 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
2691 /*-----------------------------------------------------------------*/
2692 /* genLabel - generates a label */
2693 /*-----------------------------------------------------------------*/
2694 static void genLabel (iCode *ic)
2698 /* special case never generate */
2699 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2700 if (IC_LABEL(ic) == entryLabel)
2703 emitpLabel(IC_LABEL(ic)->key);
2704 pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
2707 /*-----------------------------------------------------------------*/
2708 /* genGoto - generates a goto */
2709 /*-----------------------------------------------------------------*/
2711 static void genGoto (iCode *ic)
2715 emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
2716 pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
2720 /*-----------------------------------------------------------------*/
2721 /* genMultbits :- multiplication of bits */
2722 /*-----------------------------------------------------------------*/
2723 static void genMultbits (operand *left,
2728 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2730 if(!pic14_sameRegs(AOP(result),AOP(right)))
2731 emitpcode(POC_BSF, popGet(AOP(result),0));
2733 emitpcode(POC_BTFSC,popGet(AOP(right),0));
2734 emitpcode(POC_BTFSS,popGet(AOP(left),0));
2735 emitpcode(POC_BCF, popGet(AOP(result),0));
2740 /*-----------------------------------------------------------------*/
2741 /* genMultOneByte : 8 bit multiplication & division */
2742 /*-----------------------------------------------------------------*/
2743 static void genMultOneByte (operand *left,
2747 char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
2755 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2756 DEBUGpic14_AopType(__LINE__,left,right,result);
2757 DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
2759 /* (if two literals, the value is computed before) */
2760 /* if one literal, literal on the right */
2761 if (AOP_TYPE(left) == AOP_LIT){
2767 assert (AOP_SIZE(left) == AOP_SIZE(right));
2769 size = min(AOP_SIZE(result),AOP_SIZE(left));
2770 offset = Gstack_base_addr - (2*size - 1);
2772 /* pass right operand as argument */
2773 for (i=0; i < size; i++)
2775 mov2w (AOP(right), i);
2776 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
2779 /* pass left operand as argument */
2780 for (i=0; i < size; i++)
2782 mov2w (AOP(left), i);
2783 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
2785 assert (offset == Gstack_base_addr);
2787 /* call library routine */
2788 assert (size > 0 && size <= 4);
2789 call_libraryfunc (func[size]);
2792 movwf (AOP(result), size-1);
2793 for (i=0; i < size - 1; i++)
2795 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
2796 movwf (AOP(result), size - 2 - i);
2799 /* now (zero-/sign) extend the result to its size */
2800 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2803 /*-----------------------------------------------------------------*/
2804 /* genMult - generates code for multiplication */
2805 /*-----------------------------------------------------------------*/
2806 static void genMult (iCode *ic)
2808 operand *left = IC_LEFT(ic);
2809 operand *right = IC_RIGHT(ic);
2810 operand *result= IC_RESULT(ic);
2814 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2815 /* assign the amsops */
2816 aopOp (left,ic,FALSE);
2817 aopOp (right,ic,FALSE);
2818 aopOp (result,ic,TRUE);
2820 DEBUGpic14_AopType(__LINE__,left,right,result);
2822 /* special cases first */
2824 if (AOP_TYPE(left) == AOP_CRY &&
2825 AOP_TYPE(right)== AOP_CRY) {
2826 genMultbits(left,right,result);
2830 /* if both are of size == 1 */
2831 if (AOP_SIZE(left) == 1 &&
2832 AOP_SIZE(right) == 1 ) {
2833 genMultOneByte(left,right,result);
2837 /* should have been converted to function call */
2841 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2842 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2843 freeAsmop(result,NULL,ic,TRUE);
2846 /*-----------------------------------------------------------------*/
2847 /* genDivbits :- division of bits */
2848 /*-----------------------------------------------------------------*/
2849 static void genDivbits (operand *left,
2858 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2859 /* the result must be bit */
2860 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
2861 l = aopGet(AOP(left),0,FALSE,FALSE);
2865 pic14_emitcode("div","ab");
2866 pic14_emitcode("rrc","a");
2867 aopPut(AOP(result),"c",0);
2870 /*-----------------------------------------------------------------*/
2871 /* genDivOneByte : 8 bit division */
2872 /*-----------------------------------------------------------------*/
2873 static void genDivOneByte (operand *left,
2881 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2883 assert (AOP_SIZE(right) == 1);
2884 assert (AOP_SIZE(left) == 1);
2886 size = min(AOP_SIZE(result),AOP_SIZE(left));
2887 sign = !(SPEC_USIGN(operandType(left))
2888 && SPEC_USIGN(operandType(right)));
2890 if (AOP_TYPE(right) == AOP_LIT)
2892 /* XXX: might add specialized code */
2897 /* unsigned division */
2899 mov2w(AOP(right),0);
2900 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
2902 call_libraryfunc("__divuchar");
2903 movwf(AOP(result),0);
2908 temp = popGetTempReg();
2909 lbl = newiTempLabel(NULL);
2911 /* XXX: improve this naive approach:
2912 [result] = [a] / [b]
2913 ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
2917 movwf temp // temp <-- left
2918 movf right,W // W <-- right
2922 subwf temp,F // temp <-- temp - W
2923 skipNC // subwf clears CARRY (i.e. sets BORROW) if temp < W
2925 decf result // we just subtract once too often
2928 /* XXX: This loops endlessly on DIVIDE BY ZERO */
2929 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
2932 emitpcode(POC_MOVWF, temp);
2933 mov2w(AOP(right),0);
2934 emitpcode(POC_CLRF, popGet(AOP(result),0));
2936 emitpLabel(lbl->key);
2937 emitpcode(POC_INCF, popGet(AOP(result),0));
2938 emitpcode(POC_SUBWF, temp);
2940 emitpcode(POC_GOTO, popGetLabel(lbl->key));
2941 emitpcode(POC_DECF, popGet(AOP(result),0));
2942 popReleaseTempReg(temp);
2947 /* signed division */
2948 mov2w(AOP(right),0);
2949 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
2951 call_libraryfunc("__divschar");
2952 movwf(AOP(result),0);
2955 /* now performed the signed/unsigned division -- extend result */
2956 addSign(result, 1, sign);
2959 /*-----------------------------------------------------------------*/
2960 /* genDiv - generates code for division */
2961 /*-----------------------------------------------------------------*/
2962 static void genDiv (iCode *ic)
2964 operand *left = IC_LEFT(ic);
2965 operand *right = IC_RIGHT(ic);
2966 operand *result= IC_RESULT(ic);
2969 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2970 /* assign the amsops */
2971 aopOp (left,ic,FALSE);
2972 aopOp (right,ic,FALSE);
2973 aopOp (result,ic,TRUE);
2975 /* special cases first */
2977 if (AOP_TYPE(left) == AOP_CRY &&
2978 AOP_TYPE(right)== AOP_CRY) {
2979 genDivbits(left,right,result);
2983 /* if both are of size == 1 */
2984 if (AOP_SIZE(left) == 1 &&
2985 AOP_SIZE(right) == 1 ) {
2986 genDivOneByte(left,right,result);
2990 /* should have been converted to function call */
2993 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2994 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2995 freeAsmop(result,NULL,ic,TRUE);
2998 /*-----------------------------------------------------------------*/
2999 /* genModOneByte : 8 bit modulus */
3000 /*-----------------------------------------------------------------*/
3001 static void genModOneByte (operand *left,
3009 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3011 assert (AOP_SIZE(right) == 1);
3012 assert (AOP_SIZE(left) == 1);
3014 size = min(AOP_SIZE(result),AOP_SIZE(left));
3015 sign = !(SPEC_USIGN(operandType(left))
3016 && SPEC_USIGN(operandType(right)));
3018 if (AOP_TYPE(right) == AOP_LIT)
3020 /* XXX: might add specialized code */
3025 /* unsigned division */
3027 mov2w(AOP(right),0);
3028 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3030 call_libraryfunc("__moduchar");
3031 movwf(AOP(result),0);
3036 lbl = newiTempLabel(NULL);
3038 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3040 /* XXX: improve this naive approach:
3041 [result] = [a] % [b]
3042 ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3046 movwf result // result <-- left
3047 movf right,W // W <-- right
3049 subwf result,F // result <-- result - W
3050 skipNC // subwf clears CARRY (i.e. sets BORROW) if result < W
3052 addwf result, F // we just subtract once too often
3055 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3056 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3058 if (!pic14_sameRegs(AOP(left), AOP(result)))
3061 emitpcode(POC_MOVWF, popGet(AOP(result),0));
3063 mov2w(AOP(right),0);
3065 emitpLabel(lbl->key);
3066 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3068 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3069 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3074 /* signed division */
3075 mov2w(AOP(right),0);
3076 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3078 call_libraryfunc("__modschar");
3079 movwf(AOP(result),0);
3082 /* now we performed the signed/unsigned modulus -- extend result */
3083 addSign(result, 1, sign);
3086 /*-----------------------------------------------------------------*/
3087 /* genMod - generates code for division */
3088 /*-----------------------------------------------------------------*/
3089 static void genMod (iCode *ic)
3091 operand *left = IC_LEFT(ic);
3092 operand *right = IC_RIGHT(ic);
3093 operand *result= IC_RESULT(ic);
3096 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3097 /* assign the amsops */
3098 aopOp (left,ic,FALSE);
3099 aopOp (right,ic,FALSE);
3100 aopOp (result,ic,TRUE);
3102 /* if both are of size == 1 */
3103 if (AOP_SIZE(left) == 1 &&
3104 AOP_SIZE(right) == 1 ) {
3105 genModOneByte(left,right,result);
3109 /* should have been converted to function call */
3113 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3114 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3115 freeAsmop(result,NULL,ic,TRUE);
3118 /*-----------------------------------------------------------------*/
3119 /* genIfxJump :- will create a jump depending on the ifx */
3120 /*-----------------------------------------------------------------*/
3122 note: May need to add parameter to indicate when a variable is in bit space.
3124 static void genIfxJump (iCode *ic, char *jval)
3128 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3129 /* if true label then we jump if condition
3131 if ( IC_TRUE(ic) ) {
3133 if(strcmp(jval,"a") == 0)
3135 else if (strcmp(jval,"c") == 0)
3138 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3139 emitpcode(POC_BTFSC, newpCodeOpBit(jval,-1,1));
3142 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3143 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3147 /* false label is present */
3148 if(strcmp(jval,"a") == 0)
3150 else if (strcmp(jval,"c") == 0)
3153 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3154 emitpcode(POC_BTFSS, newpCodeOpBit(jval,-1,1));
3157 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3158 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3163 /* mark the icode as generated */
3168 /*-----------------------------------------------------------------*/
3170 /*-----------------------------------------------------------------*/
3171 static void genSkip(iCode *ifx,int status_bit)
3177 if ( IC_TRUE(ifx) ) {
3178 switch(status_bit) {
3193 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3194 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3198 switch(status_bit) {
3212 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3213 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3220 /*-----------------------------------------------------------------*/
3222 /*-----------------------------------------------------------------*/
3223 static void genSkipc(resolvedIfx *rifx)
3234 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3235 emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3236 rifx->generated = 1;
3240 /*-----------------------------------------------------------------*/
3242 /*-----------------------------------------------------------------*/
3243 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3249 if( (rifx->condition ^ invert_condition) & 1)
3254 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3255 rifx->generated = 1;
3260 /*-----------------------------------------------------------------*/
3262 /*-----------------------------------------------------------------*/
3263 static void genSkipz(iCode *ifx, int condition)
3266 assert (ifx != NULL);
3274 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3276 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3279 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3281 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3287 /*-----------------------------------------------------------------*/
3289 /*-----------------------------------------------------------------*/
3290 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3297 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3299 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3302 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3303 rifx->generated = 1;
3308 /*-----------------------------------------------------------------*/
3309 /* genChkZeroes :- greater or less than comparison */
3310 /* For each byte in a literal that is zero, inclusive or the */
3311 /* the corresponding byte in the operand with W */
3312 /* returns true if any of the bytes are zero */
3313 /*-----------------------------------------------------------------*/
3314 static int genChkZeroes(operand *op, int lit, int size)
3321 i = (lit >> (size*8)) & 0xff;
3325 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3327 emitpcode(POC_IORFW, popGet(AOP(op),size));
3337 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3338 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
3339 #define DEBUGpc emitpComment
3341 /*-----------------------------------------------------------------*/
3342 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
3343 /* aop (if it's NOT a literal) or from lit (if */
3344 /* aop is a literal) */
3345 /*-----------------------------------------------------------------*/
3346 static void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset)
3348 if (aop->type == AOP_LIT) {
3349 emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3351 emitpcode (POC_MOVFW, popGet (aop, offset));
3355 /* genCmp performs a left < right comparison, stores
3356 * the outcome in result (if != NULL) and generates
3357 * control flow code for the ifx (if != NULL).
3359 * This version leaves in sequences like
3360 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3361 * which should be optmized by the peephole
3362 * optimizer - RN 2005-01-01 */
3363 static void genCmp (operand *left,operand *right,
3364 operand *result, iCode *ifx, int sign)
3374 int invert_result = 0;
3378 assert (AOP_SIZE(left) == AOP_SIZE(right));
3379 assert (left && right);
3381 size = AOP_SIZE(right) - 1;
3382 mask = (0x100UL << (size*8)) - 1;
3383 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3388 resolveIfx (&rIfx, ifx);
3390 /**********************************************************************
3391 * handle bits - bit compares are promoted to int compares seemingly! *
3392 **********************************************************************/
3394 // THIS IS COMPLETELY UNTESTED!
3395 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3396 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3397 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3398 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3401 // 1 < {0,1} is false --> clear C by skipping the next instruction
3402 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3403 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3404 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3405 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3406 emitCLRC; // only skipped for left=0 && right=1
3408 goto correct_result_in_carry;
3412 /*************************************************
3413 * make sure that left is register (or the like) *
3414 *************************************************/
3415 if (!isAOP_REGlike(left)) {
3416 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
3417 assert (isAOP_LIT(left));
3418 assert (isAOP_REGlike(right));
3419 // swap left and right
3420 // left < right <==> right > left <==> (right >= left + 1)
3421 lit = ulFromVal(AOP(left)->aopu.aop_lit);
3423 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
3424 // MAXVALUE < right? always false
3425 if (performedLt) emitCLRC; else emitSETC;
3426 goto correct_result_in_carry;
3429 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
3430 // that's why we handled it above.
3437 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
3438 } else if (isAOP_LIT(right)) {
3439 lit = ulFromVal(AOP(right)->aopu.aop_lit);
3442 assert (isAOP_REGlike(left)); // left must be register or the like
3443 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
3445 /*************************************************
3446 * special cases go here *
3447 *************************************************/
3449 if (isAOP_LIT(right)) {
3451 // unsigned comparison to a literal
3452 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
3454 // unsigned left < 0? always false
3455 if (performedLt) emitCLRC; else emitSETC;
3456 goto correct_result_in_carry;
3459 // signed comparison to a literal
3460 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
3461 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
3462 // signed left < 0x80000000? always false
3463 if (performedLt) emitCLRC; else emitSETC;
3464 goto correct_result_in_carry;
3465 } else if (lit == 0) {
3466 // compare left < 0; set CARRY if SIGNBIT(left) is set
3467 if (performedLt) emitSETC; else emitCLRC;
3468 emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
3469 if (performedLt) emitCLRC; else emitSETC;
3470 goto correct_result_in_carry;
3473 } // right is literal
3475 /*************************************************
3476 * perform a general case comparison *
3477 * make sure we get CARRY==1 <==> left >= right *
3478 *************************************************/
3479 // compare most significant bytes
3480 //DEBUGpc ("comparing bytes at offset %d", size);
3482 // unsigned comparison
3483 pic14_mov2w_regOrLit (AOP(right), lit, size);
3484 emitpcode (POC_SUBFW, popGet (AOP(left), size));
3486 // signed comparison
3487 // (add 2^n to both operands then perform an unsigned comparison)
3488 if (isAOP_LIT(right)) {
3489 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
3490 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
3492 if (litbyte == 0x80) {
3493 // left >= 0x80 -- always true, but more bytes to come
3494 mov2w (AOP(left), size);
3495 emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
3498 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
3499 mov2w (AOP(left), size);
3500 emitpcode (POC_ADDLW, popGetLit (0x80));
3501 emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
3504 pCodeOp *pctemp = popGetTempReg();
3505 mov2w (AOP(left), size);
3506 emitpcode (POC_ADDLW, popGetLit (0x80));
3507 emitpcode (POC_MOVWF, pctemp);
3508 mov2w (AOP(right), size);
3509 emitpcode (POC_ADDLW, popGetLit (0x80));
3510 emitpcode (POC_SUBFW, pctemp);
3511 popReleaseTempReg(pctemp);
3515 // compare remaining bytes (treat as unsigned case from above)
3516 templbl = newiTempLabel ( NULL );
3519 //DEBUGpc ("comparing bytes at offset %d", offs);
3521 emitpcode (POC_GOTO, popGetLabel (templbl->key));
3522 pic14_mov2w_regOrLit (AOP(right), lit, offs);
3523 emitpcode (POC_SUBFW, popGet (AOP(left), offs));
3525 emitpLabel (templbl->key);
3526 goto result_in_carry;
3530 /****************************************************
3531 * now CARRY contains the result of the comparison: *
3532 * SUBWF sets CARRY iff *
3533 * F-W >= 0 <==> F >= W <==> !(F < W) *
3534 * (F=left, W=right) *
3535 ****************************************************/
3539 // value will be used in the following genSkipc()
3540 rIfx.condition ^= 1;
3543 correct_result_in_carry:
3545 // assign result to variable (if neccessary)
3546 if (result && AOP_TYPE(result) != AOP_CRY) {
3547 //DEBUGpc ("assign result");
3548 size = AOP_SIZE(result);
3550 emitpcode (POC_CLRF, popGet (AOP(result), size));
3552 if (invert_result) {
3554 emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
3556 emitpcode (POC_RLF, popGet (AOP(result), 0));
3560 // perform conditional jump
3562 //DEBUGpc ("generate control flow");
3570 /* OLD VERSION -- BUGGY, DO NOT USE */
3572 /*-----------------------------------------------------------------*/
3573 /* genCmp :- greater or less than comparison */
3574 /*-----------------------------------------------------------------*/
3575 static void genCmp (operand *left,operand *right,
3576 operand *result, iCode *ifx, int sign)
3578 int size; //, offset = 0 ;
3579 unsigned long lit = 0L,i = 0;
3580 resolvedIfx rFalseIfx;
3581 // resolvedIfx rTrueIfx;
3585 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3588 DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
3589 DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
3593 resolveIfx(&rFalseIfx,ifx);
3594 truelbl = newiTempLabel(NULL);
3595 size = max(AOP_SIZE(left),AOP_SIZE(right));
3597 DEBUGpic14_AopType(__LINE__,left,right,result);
3601 /* if literal is on the right then swap with left */
3602 if ((AOP_TYPE(right) == AOP_LIT)) {
3603 operand *tmp = right ;
3604 unsigned long mask = (0x100 << (8*(size-1))) - 1;
3605 lit = ulFromVal(AOP(right)->aopu.aop_lit);
3608 lit = (lit - 1) & mask;
3611 rFalseIfx.condition ^= 1;
3614 } else if ((AOP_TYPE(left) == AOP_LIT)) {
3615 lit = ulFromVal(AOP(left)->aopu.aop_lit);
3619 //if(IC_TRUE(ifx) == NULL)
3620 /* if left & right are bit variables */
3621 if (AOP_TYPE(left) == AOP_CRY &&
3622 AOP_TYPE(right) == AOP_CRY ) {
3623 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3624 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3626 /* subtract right from left if at the
3627 end the carry flag is set then we know that
3628 left is greater than right */
3630 symbol *lbl = newiTempLabel(NULL);
3633 if(AOP_TYPE(right) == AOP_LIT) {
3635 //lit = ulFromVal(AOP(right)->aopu.aop_lit);
3637 DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
3644 genSkipCond(&rFalseIfx,left,size-1,7);
3646 /* no need to compare to 0...*/
3647 /* NOTE: this is a de-generate compare that most certainly
3648 * creates some dead code. */
3649 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3651 if(ifx) ifx->generated = 1;
3658 //i = (lit >> (size*8)) & 0xff;
3659 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3661 emitpcode(POC_MOVFW, popGet(AOP(left),size));
3663 i = ((0-lit) & 0xff);
3666 /* lit is 0x7f, all signed chars are less than
3667 * this except for 0x7f itself */
3668 emitpcode(POC_XORLW, popGetLit(0x7f));
3669 genSkipz2(&rFalseIfx,0);
3671 emitpcode(POC_ADDLW, popGetLit(0x80));
3672 emitpcode(POC_ADDLW, popGetLit(i^0x80));
3673 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
3678 genSkipz2(&rFalseIfx,1);
3680 emitpcode(POC_ADDLW, popGetLit(i));
3681 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
3685 if(ifx) ifx->generated = 1;
3689 /* chars are out of the way. now do ints and longs */
3692 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3699 genSkipCond(&rFalseIfx,left,size,7);
3700 if(ifx) ifx->generated = 1;
3705 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3707 //rFalseIfx.condition ^= 1;
3708 //genSkipCond(&rFalseIfx,left,size,7);
3709 //rFalseIfx.condition ^= 1;
3711 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3712 if(rFalseIfx.condition)
3713 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
3715 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
3717 emitpcode(POC_MOVLW, popGetLit(0x100-lit));
3718 emitpcode(POC_ADDFW, popGet(AOP(left),0));
3719 emitpcode(POC_MOVFW, popGet(AOP(left),1));
3722 emitpcode(POC_IORFW, popGet(AOP(left),size--));
3724 if(rFalseIfx.condition) {
3726 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
3732 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
3733 emitpLabel(truelbl->key);
3734 if(ifx) ifx->generated = 1;
3741 if( (lit & 0xff) == 0) {
3742 /* lower byte is zero */
3743 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3744 i = ((lit >> 8) & 0xff) ^0x80;
3745 emitpcode(POC_MOVFW, popGet(AOP(left),size));
3746 emitpcode(POC_ADDLW, popGetLit( 0x80));
3747 emitpcode(POC_ADDLW, popGetLit(0x100-i));
3748 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
3751 if(ifx) ifx->generated = 1;
3756 /* Special cases for signed longs */
3757 if( (lit & 0xffffff) == 0) {
3758 /* lower byte is zero */
3759 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3760 i = ((lit >> 8*3) & 0xff) ^0x80;
3761 emitpcode(POC_MOVFW, popGet(AOP(left),size));
3762 emitpcode(POC_ADDLW, popGetLit( 0x80));
3763 emitpcode(POC_ADDLW, popGetLit(0x100-i));
3764 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
3767 if(ifx) ifx->generated = 1;
3775 if(lit & (0x80 << (size*8))) {
3776 /* lit is negative */
3777 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3779 //genSkipCond(&rFalseIfx,left,size,7);
3781 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3783 if(rFalseIfx.condition)
3784 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
3786 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
3790 /* lit is positive */
3791 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3792 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3793 if(rFalseIfx.condition)
3794 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
3796 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
3800 /* There are no more special cases, so perform a general compare */
3802 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3803 emitpcode(POC_SUBFW, popGet(AOP(left),size));
3807 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3809 emitpcode(POC_SUBFW, popGet(AOP(left),size));
3811 //rFalseIfx.condition ^= 1;
3812 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
3814 emitpLabel(truelbl->key);
3816 if(ifx) ifx->generated = 1;
3823 /* sign is out of the way. So now do an unsigned compare */
3824 DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
3827 /* General case - compare to an unsigned literal on the right.*/
3829 i = (lit >> (size*8)) & 0xff;
3830 emitpcode(POC_MOVLW, popGetLit(i));
3831 emitpcode(POC_SUBFW, popGet(AOP(left),size));
3833 i = (lit >> (size*8)) & 0xff;
3836 emitpcode(POC_MOVLW, popGetLit(i));
3838 emitpcode(POC_SUBFW, popGet(AOP(left),size));
3840 /* this byte of the lit is zero,
3841 *if it's not the last then OR in the variable */
3843 emitpcode(POC_IORFW, popGet(AOP(left),size));
3848 emitpLabel(lbl->key);
3849 //if(emitFinalCheck)
3850 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
3852 emitpLabel(truelbl->key);
3854 if(ifx) ifx->generated = 1;
3861 if(AOP_TYPE(left) == AOP_LIT) {
3862 //symbol *lbl = newiTempLabel(NULL);
3864 //EXPERIMENTAL lit = ulFromVal(AOP(left)->aopu.aop_lit);
3867 DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
3870 if((lit == 0) && (sign == 0)){
3873 emitpcode(POC_MOVFW, popGet(AOP(right),size));
3875 emitpcode(POC_IORFW, popGet(AOP(right),--size));
3877 genSkipz2(&rFalseIfx,0);
3878 if(ifx) ifx->generated = 1;
3885 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
3886 /* degenerate compare can never be true */
3887 if(rFalseIfx.condition == 0)
3888 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3890 if(ifx) ifx->generated = 1;
3895 /* signed comparisons to a literal byte */
3897 int lp1 = (lit+1) & 0xff;
3899 DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
3902 rFalseIfx.condition ^= 1;
3903 genSkipCond(&rFalseIfx,right,0,7);
3906 emitpcode(POC_MOVFW, popGet(AOP(right),0));
3907 emitpcode(POC_XORLW, popGetLit(0x7f));
3908 genSkipz2(&rFalseIfx,1);
3911 emitpcode(POC_MOVFW, popGet(AOP(right),0));
3912 emitpcode(POC_ADDLW, popGetLit(0x80));
3913 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
3914 rFalseIfx.condition ^= 1;
3915 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
3918 if(ifx) ifx->generated = 1;
3920 /* unsigned comparisons to a literal byte */
3922 switch(lit & 0xff ) {
3924 emitpcode(POC_MOVFW, popGet(AOP(right),0));
3925 genSkipz2(&rFalseIfx,0);
3926 if(ifx) ifx->generated = 1;
3929 genSkipCond(&rFalseIfx,right,0,7);
3930 if(ifx) ifx->generated = 1;
3934 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
3935 emitpcode(POC_SUBFW, popGet(AOP(right),0));
3936 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3937 rFalseIfx.condition ^= 1;
3938 if (AOP_TYPE(result) == AOP_CRY) {
3939 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
3940 if(ifx) ifx->generated = 1;
3942 DEBUGpic14_emitcode ("; ***","%s %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
3943 emitpcode(POC_CLRF, popGet(AOP(result),0));
3944 emitpcode(POC_RLF, popGet(AOP(result),0));
3945 emitpcode(POC_MOVLW, popGetLit(0x01));
3946 emitpcode(POC_XORWF, popGet(AOP(result),0));
3957 /* Size is greater than 1 */
3965 /* this means lit = 0xffffffff, or -1 */
3968 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
3969 rFalseIfx.condition ^= 1;
3970 genSkipCond(&rFalseIfx,right,size,7);
3971 if(ifx) ifx->generated = 1;
3978 if(rFalseIfx.condition) {
3979 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
3980 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
3983 emitpcode(POC_MOVFW, popGet(AOP(right),size));
3985 emitpcode(POC_IORFW, popGet(AOP(right),size));
3989 if(rFalseIfx.condition) {
3990 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
3991 emitpLabel(truelbl->key);
3993 rFalseIfx.condition ^= 1;
3994 genSkipCond(&rFalseIfx,right,s,7);
3997 if(ifx) ifx->generated = 1;
4001 if((size == 1) && (0 == (lp1&0xff))) {
4002 /* lower byte of signed word is zero */
4003 DEBUGpic14_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
4004 i = ((lp1 >> 8) & 0xff) ^0x80;
4005 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4006 emitpcode(POC_ADDLW, popGetLit( 0x80));
4007 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4008 rFalseIfx.condition ^= 1;
4009 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4012 if(ifx) ifx->generated = 1;
4016 if(lit & (0x80 << (size*8))) {
4017 /* Lit is less than zero */
4018 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
4019 //rFalseIfx.condition ^= 1;
4020 //genSkipCond(&rFalseIfx,left,size,7);
4021 //rFalseIfx.condition ^= 1;
4022 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4023 //emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4025 if(rFalseIfx.condition)
4026 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4028 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4032 /* Lit is greater than or equal to zero */
4033 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
4034 //rFalseIfx.condition ^= 1;
4035 //genSkipCond(&rFalseIfx,right,size,7);
4036 //rFalseIfx.condition ^= 1;
4038 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4039 //emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4041 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4042 if(rFalseIfx.condition)
4043 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4045 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4050 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4051 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4055 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4057 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4059 rFalseIfx.condition ^= 1;
4060 //rFalseIfx.condition = 1;
4061 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4063 emitpLabel(truelbl->key);
4065 if(ifx) ifx->generated = 1;
4070 /* compare word or long to an unsigned literal on the right.*/
4075 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4078 break; /* handled above */
4081 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4083 emitpcode(POC_IORFW, popGet(AOP(right),size));
4084 genSkipz2(&rFalseIfx,0);
4088 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4090 emitpcode(POC_IORFW, popGet(AOP(right),size));
4093 if(rFalseIfx.condition)
4094 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4096 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4099 emitpcode(POC_MOVLW, popGetLit(lit+1));
4100 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4102 rFalseIfx.condition ^= 1;
4103 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4106 emitpLabel(truelbl->key);
4108 if(ifx) ifx->generated = 1;
4114 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4115 i = (lit >> (size*8)) & 0xff;
4117 emitpcode(POC_MOVLW, popGetLit(i));
4118 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4121 i = (lit >> (size*8)) & 0xff;
4124 emitpcode(POC_MOVLW, popGetLit(i));
4126 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4128 /* this byte of the lit is zero,
4129 *if it's not the last then OR in the variable */
4131 emitpcode(POC_IORFW, popGet(AOP(right),size));
4136 emitpLabel(lbl->key);
4138 rFalseIfx.condition ^= 1;
4139 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4143 emitpLabel(truelbl->key);
4144 if(ifx) ifx->generated = 1;
4148 /* Compare two variables */
4150 DEBUGpic14_emitcode(";sign","%d",sign);
4154 /* Sigh. thus sucks... */
4156 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4157 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4158 emitpcode(POC_MOVLW, popGetLit(0x80));
4159 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4160 emitpcode(POC_XORFW, popGet(AOP(right),size));
4161 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4163 /* Signed char comparison */
4164 /* Special thanks to Nikolai Golovchenko for this snippet */
4165 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4166 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4167 emitpcode(POC_RRFW, popGet(AOP(left),0)); /* could be any register */
4168 emitpcode(POC_XORFW, popGet(AOP(left),0));
4169 emitpcode(POC_XORFW, popGet(AOP(right),0));
4170 emitpcode(POC_ADDLW, popGetLit(0x80));
4172 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4173 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4175 if(ifx) ifx->generated = 1;
4181 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4182 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4186 /* The rest of the bytes of a multi-byte compare */
4190 emitpcode(POC_GOTO, popGetLabel(lbl->key));
4193 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4194 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4199 emitpLabel(lbl->key);
4201 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4202 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
4203 (AOP_TYPE(result) == AOP_REG)) {
4204 emitpcode(POC_CLRF, popGet(AOP(result),0));
4205 emitpcode(POC_RLF, popGet(AOP(result),0));
4207 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4209 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4210 if(ifx) ifx->generated = 1;
4217 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4218 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4219 pic14_outBitC(result);
4221 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4222 /* if the result is used in the next
4223 ifx conditional branch then generate
4224 code a little differently */
4226 genIfxJump (ifx,"c");
4228 pic14_outBitC(result);
4229 /* leave the result in acc */
4235 /*-----------------------------------------------------------------*/
4236 /* genCmpGt :- greater than comparison */
4237 /*-----------------------------------------------------------------*/
4238 static void genCmpGt (iCode *ic, iCode *ifx)
4240 operand *left, *right, *result;
4241 sym_link *letype , *retype;
4245 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4247 right= IC_RIGHT(ic);
4248 result = IC_RESULT(ic);
4250 letype = getSpec(operandType(left));
4251 retype =getSpec(operandType(right));
4252 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4253 /* assign the amsops */
4254 aopOp (left,ic,FALSE);
4255 aopOp (right,ic,FALSE);
4256 aopOp (result,ic,TRUE);
4258 genCmp(right, left, result, ifx, sign);
4260 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4261 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4262 freeAsmop(result,NULL,ic,TRUE);
4265 /*-----------------------------------------------------------------*/
4266 /* genCmpLt - less than comparisons */
4267 /*-----------------------------------------------------------------*/
4268 static void genCmpLt (iCode *ic, iCode *ifx)
4270 operand *left, *right, *result;
4271 sym_link *letype , *retype;
4275 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4277 right= IC_RIGHT(ic);
4278 result = IC_RESULT(ic);
4280 letype = getSpec(operandType(left));
4281 retype =getSpec(operandType(right));
4282 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4284 /* assign the amsops */
4285 aopOp (left,ic,FALSE);
4286 aopOp (right,ic,FALSE);
4287 aopOp (result,ic,TRUE);
4289 genCmp(left, right, result, ifx, sign);
4291 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4292 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4293 freeAsmop(result,NULL,ic,TRUE);
4296 /*-----------------------------------------------------------------*/
4297 /* genCmpEq - generates code for equal to */
4298 /*-----------------------------------------------------------------*/
4299 static void genCmpEq (iCode *ic, iCode *ifx)
4301 operand *left, *right, *result;
4303 symbol *false_label;
4306 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4309 DEBUGpic14_emitcode ("; ifx is non-null","");
4311 DEBUGpic14_emitcode ("; ifx is null","");
4313 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4314 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4315 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4317 DEBUGpic14_AopType(__LINE__,left,right,result);
4319 /* if literal, move literal to right */
4320 if (op_isLitLike (IC_LEFT(ic))) {
4321 operand *tmp = right ;
4327 if (ifx && !IC_TRUE(ifx))
4329 assert (IC_FALSE(ifx));
4330 false_label = IC_FALSE(ifx);
4333 size = min(AOP_SIZE(left),AOP_SIZE(right));
4334 assert(!pic14_sameRegs(AOP(result),AOP(left)));
4335 assert(!pic14_sameRegs(AOP(result),AOP(right)));
4337 /* assume left != right */
4340 for (i=0; i < AOP_SIZE(result); i++)
4342 emitpcode(POC_CLRF, popGet(AOP(result),i));
4346 if (AOP_TYPE(right) == AOP_LIT)
4348 unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit);
4350 size = AOP_SIZE(left);
4351 assert(!op_isLitLike(left));
4356 mov2w(AOP(left), 0);
4357 for (i=1; i < size; i++)
4358 emitpcode(POC_IORFW,popGet(AOP(left),i));
4359 /* now Z is set iff `left == right' */
4361 if (!false_label) false_label = newiTempLabel(NULL);
4362 emitpcode(POC_GOTO, popGetLabel(false_label->key));
4366 for (i=0; i < size; i++)
4369 emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
4370 /* now Z is cleared if `left != right' */
4372 if (!false_label) false_label = newiTempLabel(NULL);
4373 emitpcode(POC_GOTO, popGetLabel(false_label->key));
4380 /* right is no literal */
4383 for (i=0; i < size; i++)
4385 mov2w(AOP(right),i);
4386 emitpcode(POC_XORFW,popGet(AOP(left),i));
4387 /* now Z is cleared if `left != right' */
4389 if (!false_label) false_label = newiTempLabel(NULL);
4390 emitpcode(POC_GOTO, popGetLabel(false_label->key));
4394 /* if we reach here, left == right */
4396 if (AOP_SIZE(result) > 0)
4398 emitpcode(POC_INCF, popGet(AOP(result),0));
4401 if (ifx && IC_TRUE(ifx))
4403 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4406 if (false_label && (!ifx || IC_TRUE(ifx)))
4407 emitpLabel(false_label->key);
4409 if (ifx) ifx->generated = 1;
4411 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4412 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4413 freeAsmop(result,NULL,ic,TRUE);
4416 /*-----------------------------------------------------------------*/
4417 /* ifxForOp - returns the icode containing the ifx for operand */
4418 /*-----------------------------------------------------------------*/
4419 static iCode *ifxForOp ( operand *op, iCode *ic )
4422 /* if true symbol then needs to be assigned */
4423 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4424 if (IS_TRUE_SYMOP(op))
4427 /* if this has register type condition and
4428 the next instruction is ifx with the same operand
4429 and live to of the operand is upto the ifx only then */
4431 ic->next->op == IFX &&
4432 IC_COND(ic->next)->key == op->key &&
4433 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4437 ic->next->op == IFX &&
4438 IC_COND(ic->next)->key == op->key) {
4439 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
4443 DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
4445 ic->next->op == IFX)
4446 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
4449 ic->next->op == IFX &&
4450 IC_COND(ic->next)->key == op->key) {
4451 DEBUGpic14_emitcode ("; "," key is okay");
4452 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
4453 OP_SYMBOL(op)->liveTo,
4460 /*-----------------------------------------------------------------*/
4461 /* genAndOp - for && operation */
4462 /*-----------------------------------------------------------------*/
4463 static void genAndOp (iCode *ic)
4465 operand *left,*right, *result;
4469 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4470 /* note here that && operations that are in an
4471 if statement are taken away by backPatchLabels
4472 only those used in arthmetic operations remain */
4473 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4474 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4475 aopOp((result=IC_RESULT(ic)),ic,FALSE);
4477 DEBUGpic14_AopType(__LINE__,left,right,result);
4479 emitpcode(POC_MOVFW,popGet(AOP(left),0));
4480 emitpcode(POC_ANDFW,popGet(AOP(right),0));
4481 emitpcode(POC_MOVWF,popGet(AOP(result),0));
4483 /* if both are bit variables */
4484 /* if (AOP_TYPE(left) == AOP_CRY && */
4485 /* AOP_TYPE(right) == AOP_CRY ) { */
4486 /* pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
4487 /* pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
4488 /* pic14_outBitC(result); */
4490 /* tlbl = newiTempLabel(NULL); */
4491 /* pic14_toBoolean(left); */
4492 /* pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
4493 /* pic14_toBoolean(right); */
4494 /* pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
4495 /* pic14_outBitAcc(result); */
4498 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4499 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4500 freeAsmop(result,NULL,ic,TRUE);
4504 /*-----------------------------------------------------------------*/
4505 /* genOrOp - for || operation */
4506 /*-----------------------------------------------------------------*/
4509 modified this code, but it doesn't appear to ever get called
4512 static void genOrOp (iCode *ic)
4514 operand *left,*right, *result;
4518 /* note here that || operations that are in an
4519 if statement are taken away by backPatchLabels
4520 only those used in arthmetic operations remain */
4522 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4523 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4524 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4525 aopOp((result=IC_RESULT(ic)),ic,FALSE);
4527 DEBUGpic14_AopType(__LINE__,left,right,result);
4529 for (i=0; i < AOP_SIZE(result); i++)
4531 emitpcode(POC_CLRF, popGet(AOP(result), i));
4534 tlbl = newiTempLabel(NULL);
4535 pic14_toBoolean(left);
4537 emitpcode(POC_GOTO, popGetLabel(tlbl->key));
4538 pic14_toBoolean(right);
4539 emitpLabel(tlbl->key);
4540 /* here Z is clear IFF `left || right' */
4542 emitpcode(POC_INCF, popGet(AOP(result), 0));
4544 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4545 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4546 freeAsmop(result,NULL,ic,TRUE);
4549 /*-----------------------------------------------------------------*/
4550 /* isLiteralBit - test if lit == 2^n */
4551 /*-----------------------------------------------------------------*/
4552 static int isLiteralBit(unsigned long lit)
4554 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4555 0x100L,0x200L,0x400L,0x800L,
4556 0x1000L,0x2000L,0x4000L,0x8000L,
4557 0x10000L,0x20000L,0x40000L,0x80000L,
4558 0x100000L,0x200000L,0x400000L,0x800000L,
4559 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4560 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4564 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4565 for(idx = 0; idx < 32; idx++)
4571 /*-----------------------------------------------------------------*/
4572 /* continueIfTrue - */
4573 /*-----------------------------------------------------------------*/
4574 static void continueIfTrue (iCode *ic)
4577 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4581 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
4582 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4587 /*-----------------------------------------------------------------*/
4589 /*-----------------------------------------------------------------*/
4590 static void jumpIfTrue (iCode *ic)
4593 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4597 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
4598 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4603 /*-----------------------------------------------------------------*/
4604 /* jmpTrueOrFalse - */
4605 /*-----------------------------------------------------------------*/
4606 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4609 // ugly but optimized by peephole
4610 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4612 symbol *nlbl = newiTempLabel(NULL);
4613 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);
4614 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4615 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4616 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
4619 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4620 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4625 /*-----------------------------------------------------------------*/
4626 /* genAnd - code for and */
4627 /*-----------------------------------------------------------------*/
4628 static void genAnd (iCode *ic, iCode *ifx)
4630 operand *left, *right, *result;
4632 unsigned long lit = 0L;
4637 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4638 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4639 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4640 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4642 resolveIfx(&rIfx,ifx);
4644 /* if left is a literal & right is not then exchange them */
4645 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4646 AOP_NEEDSACC(left)) {
4647 operand *tmp = right ;
4652 /* if result = right then exchange them */
4653 if(pic14_sameRegs(AOP(result),AOP(right))){
4654 operand *tmp = right ;
4659 /* if right is bit then exchange them */
4660 if (AOP_TYPE(right) == AOP_CRY &&
4661 AOP_TYPE(left) != AOP_CRY){
4662 operand *tmp = right ;
4666 if(AOP_TYPE(right) == AOP_LIT)
4667 lit = ulFromVal (AOP(right)->aopu.aop_lit);
4669 size = AOP_SIZE(result);
4671 DEBUGpic14_AopType(__LINE__,left,right,result);
4674 // result = bit & yy;
4675 if (AOP_TYPE(left) == AOP_CRY){
4676 // c = bit & literal;
4677 if(AOP_TYPE(right) == AOP_LIT){
4679 if(size && pic14_sameRegs(AOP(result),AOP(left)))
4682 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4685 if(size && (AOP_TYPE(result) == AOP_CRY)){
4686 pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4689 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4693 pic14_emitcode("clr","c");
4696 if (AOP_TYPE(right) == AOP_CRY){
4698 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4699 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4702 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
4704 pic14_emitcode("rrc","a");
4705 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4711 pic14_outBitC(result);
4713 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4714 genIfxJump(ifx, "c");
4718 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4719 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4720 if((AOP_TYPE(right) == AOP_LIT) &&
4721 (AOP_TYPE(result) == AOP_CRY) &&
4722 (AOP_TYPE(left) != AOP_CRY)){
4723 int posbit = isLiteralBit(lit);
4727 //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
4730 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
4735 while (posbit > 7) {
4739 emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
4740 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
4741 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4748 symbol *tlbl = newiTempLabel(NULL);
4749 int sizel = AOP_SIZE(left);
4751 pic14_emitcode("setb","c");
4753 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4754 mov2w( AOP(left), offset);
4756 if((posbit = isLiteralBit(bytelit)) != 0) {
4757 emitpcode(rIfx.condition ? POC_BTFSC : POC_BTFSS, // XXX: or the other way round?
4758 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit - 1, 0));
4759 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
4762 emitpcode(POC_ANDLW, newpCodeOpLit(bytelit & 0x0ff));
4763 if (rIfx.condition) emitSKPZ;
4766 if(bytelit != 0x0FFL)
4768 pic14_emitcode("anl","a,%s",
4769 aopGet(AOP(right),offset,FALSE,TRUE));
4771 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
4774 emitpcode(POC_GOTO, popGetLabel(rIfx.lbl->key));
4780 // bit = left & literal
4782 pic14_emitcode("clr","c");
4783 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4785 // if(left & literal)
4788 jmpTrueOrFalse(ifx, tlbl);
4792 pic14_outBitC(result);
4796 /* if left is same as result */
4797 if(pic14_sameRegs(AOP(result),AOP(left))){
4799 for(;size--; offset++,lit>>=8) {
4800 if(AOP_TYPE(right) == AOP_LIT){
4801 switch(lit & 0xff) {
4803 /* and'ing with 0 has clears the result */
4804 emitpcode(POC_CLRF,popGet(AOP(result),offset));
4807 /* and'ing with 0xff is a nop when the result and left are the same */
4812 int p = my_powof2( (~lit) & 0xff );
4814 /* only one bit is set in the literal, so use a bcf instruction */
4815 emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
4818 if(know_W != (int)(lit&0xff))
4819 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
4821 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
4826 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
4827 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
4832 // left & result in different registers
4833 if(AOP_TYPE(result) == AOP_CRY){
4835 // if(size), result in bit
4836 // if(!size && ifx), conditional oper: if(left & right)
4837 symbol *tlbl = newiTempLabel(NULL);
4838 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4840 pic14_emitcode("setb","c");
4842 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4843 pic14_emitcode("anl","a,%s",
4844 aopGet(AOP(left),offset,FALSE,FALSE));
4845 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
4850 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4851 pic14_outBitC(result);
4853 jmpTrueOrFalse(ifx, tlbl);
4855 for(;(size--);offset++) {
4857 // result = left & right
4858 if(AOP_TYPE(right) == AOP_LIT){
4859 int t = (lit >> (offset*8)) & 0x0FFL;
4862 emitpcode(POC_CLRF,popGet(AOP(result),offset));
4865 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4866 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
4869 emitpcode(POC_MOVLW, popGetLit(t));
4870 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
4871 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
4876 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
4877 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
4878 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
4884 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4885 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4886 freeAsmop(result,NULL,ic,TRUE);
4889 /*-----------------------------------------------------------------*/
4890 /* genOr - code for or */
4891 /*-----------------------------------------------------------------*/
4892 static void genOr (iCode *ic, iCode *ifx)
4894 operand *left, *right, *result;
4896 unsigned long lit = 0L;
4899 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4901 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4902 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4903 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4905 DEBUGpic14_AopType(__LINE__,left,right,result);
4907 /* if left is a literal & right is not then exchange them */
4908 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4909 AOP_NEEDSACC(left)) {
4910 operand *tmp = right ;
4915 /* if result = right then exchange them */
4916 if(pic14_sameRegs(AOP(result),AOP(right))){
4917 operand *tmp = right ;
4922 /* if right is bit then exchange them */
4923 if (AOP_TYPE(right) == AOP_CRY &&
4924 AOP_TYPE(left) != AOP_CRY){
4925 operand *tmp = right ;
4930 DEBUGpic14_AopType(__LINE__,left,right,result);
4932 if(AOP_TYPE(right) == AOP_LIT)
4933 lit = ulFromVal (AOP(right)->aopu.aop_lit);
4935 size = AOP_SIZE(result);
4939 if (AOP_TYPE(left) == AOP_CRY){
4940 if(AOP_TYPE(right) == AOP_LIT){
4941 // c = bit & literal;
4943 // lit != 0 => result = 1
4944 if(AOP_TYPE(result) == AOP_CRY){
4946 emitpcode(POC_BSF, popGet(AOP(result),0));
4947 //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
4948 // AOP(result)->aopu.aop_dir,
4949 // AOP(result)->aopu.aop_dir);
4951 continueIfTrue(ifx);
4955 // lit == 0 => result = left
4956 if(size && pic14_sameRegs(AOP(result),AOP(left)))
4958 pic14_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
4961 if (AOP_TYPE(right) == AOP_CRY){
4962 if(pic14_sameRegs(AOP(result),AOP(left))){
4964 emitpcode(POC_BCF, popGet(AOP(result),0));
4965 emitpcode(POC_BTFSC, popGet(AOP(right),0));
4966 emitpcode(POC_BSF, popGet(AOP(result),0));
4968 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
4969 AOP(result)->aopu.aop_dir,
4970 AOP(result)->aopu.aop_dir);
4971 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
4972 AOP(right)->aopu.aop_dir,
4973 AOP(right)->aopu.aop_dir);
4974 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
4975 AOP(result)->aopu.aop_dir,
4976 AOP(result)->aopu.aop_dir);
4978 emitpcode(POC_BCF, popGet(AOP(result),0));
4979 emitpcode(POC_BTFSS, popGet(AOP(right),0));
4980 emitpcode(POC_BTFSC, popGet(AOP(left),0));
4981 emitpcode(POC_BSF, popGet(AOP(result),0));
4985 symbol *tlbl = newiTempLabel(NULL);
4986 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4989 emitpcode(POC_BCF, popGet(AOP(result),0));
4991 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4992 pic14_emitcode(";XXX setb","c");
4993 pic14_emitcode(";XXX jb","%s,%05d_DS_",
4994 AOP(left)->aopu.aop_dir,tlbl->key+100);
4995 pic14_toBoolean(right);
4996 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
4997 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4998 jmpTrueOrFalse(ifx, tlbl);
5002 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5009 pic14_outBitC(result);
5011 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5012 genIfxJump(ifx, "c");
5016 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5017 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5018 if((AOP_TYPE(right) == AOP_LIT) &&
5019 (AOP_TYPE(result) == AOP_CRY) &&
5020 (AOP_TYPE(left) != AOP_CRY)){
5022 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5025 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5027 continueIfTrue(ifx);
5030 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5031 // lit = 0, result = boolean(left)
5033 pic14_emitcode(";XXX setb","c");
5034 pic14_toBoolean(right);
5036 symbol *tlbl = newiTempLabel(NULL);
5037 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5039 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5041 genIfxJump (ifx,"a");
5045 pic14_outBitC(result);
5049 /* if left is same as result */
5050 if(pic14_sameRegs(AOP(result),AOP(left))){
5052 for(;size--; offset++,lit>>=8) {
5053 if(AOP_TYPE(right) == AOP_LIT){
5054 if((lit & 0xff) == 0)
5055 /* or'ing with 0 has no effect */
5058 int p = my_powof2(lit & 0xff);
5060 /* only one bit is set in the literal, so use a bsf instruction */
5062 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5064 if(know_W != (int)(lit & 0xff))
5065 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5066 know_W = lit & 0xff;
5067 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5072 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
5073 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5077 // left & result in different registers
5078 if(AOP_TYPE(result) == AOP_CRY){
5080 // if(size), result in bit
5081 // if(!size && ifx), conditional oper: if(left | right)
5082 symbol *tlbl = newiTempLabel(NULL);
5083 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5084 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5088 pic14_emitcode(";XXX setb","c");
5090 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5091 pic14_emitcode(";XXX orl","a,%s",
5092 aopGet(AOP(left),offset,FALSE,FALSE));
5093 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5098 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5099 pic14_outBitC(result);
5101 jmpTrueOrFalse(ifx, tlbl);
5102 } else for(;(size--);offset++){
5104 // result = left | right
5105 if(AOP_TYPE(right) == AOP_LIT){
5106 int t = (lit >> (offset*8)) & 0x0FFL;
5109 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
5110 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5114 emitpcode(POC_MOVLW, popGetLit(t));
5115 emitpcode(POC_IORFW, popGet(AOP(left),offset));
5116 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5121 // faster than result <- left, anl result,right
5122 // and better if result is SFR
5123 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5124 emitpcode(POC_IORFW,popGet(AOP(left),offset));
5125 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5130 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5131 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5132 freeAsmop(result,NULL,ic,TRUE);
5135 /*-----------------------------------------------------------------*/
5136 /* genXor - code for xclusive or */
5137 /*-----------------------------------------------------------------*/
5138 static void genXor (iCode *ic, iCode *ifx)
5140 operand *left, *right, *result;
5142 unsigned long lit = 0L;
5145 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5147 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5148 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5149 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5151 /* if left is a literal & right is not ||
5152 if left needs acc & right does not */
5153 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5154 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5155 operand *tmp = right ;
5160 /* if result = right then exchange them */
5161 if(pic14_sameRegs(AOP(result),AOP(right))){
5162 operand *tmp = right ;
5167 /* if right is bit then exchange them */
5168 if (AOP_TYPE(right) == AOP_CRY &&
5169 AOP_TYPE(left) != AOP_CRY){
5170 operand *tmp = right ;
5174 if(AOP_TYPE(right) == AOP_LIT)
5175 lit = ulFromVal (AOP(right)->aopu.aop_lit);
5177 size = AOP_SIZE(result);
5181 if (AOP_TYPE(left) == AOP_CRY){
5182 if(AOP_TYPE(right) == AOP_LIT){
5183 // c = bit & literal;
5185 // lit>>1 != 0 => result = 1
5186 if(AOP_TYPE(result) == AOP_CRY){
5188 {emitpcode(POC_BSF, popGet(AOP(result),offset));
5189 pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
5191 continueIfTrue(ifx);
5194 pic14_emitcode("setb","c");
5198 // lit == 0, result = left
5199 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5201 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5203 // lit == 1, result = not(left)
5204 if(size && pic14_sameRegs(AOP(result),AOP(left))){
5205 emitpcode(POC_MOVLW, popGet(AOP(result),offset));
5206 emitpcode(POC_XORWF, popGet(AOP(result),offset));
5207 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5210 assert ( !"incomplete genXor" );
5211 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5212 pic14_emitcode("cpl","c");
5219 symbol *tlbl = newiTempLabel(NULL);
5220 if (AOP_TYPE(right) == AOP_CRY){
5222 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5225 int sizer = AOP_SIZE(right);
5227 // if val>>1 != 0, result = 1
5228 pic14_emitcode("setb","c");
5230 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5232 // test the msb of the lsb
5233 pic14_emitcode("anl","a,#0xfe");
5234 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5238 pic14_emitcode("rrc","a");
5240 pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5241 pic14_emitcode("cpl","c");
5242 pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
5247 pic14_outBitC(result);
5249 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5250 genIfxJump(ifx, "c");
5254 if(pic14_sameRegs(AOP(result),AOP(left))){
5255 /* if left is same as result */
5256 for(;size--; offset++) {
5257 if(AOP_TYPE(right) == AOP_LIT){
5258 int t = (lit >> (offset*8)) & 0x0FFL;
5262 emitpcode(POC_MOVLW, popGetLit(t));
5263 emitpcode(POC_XORWF,popGet(AOP(left),offset));
5266 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5267 emitpcode(POC_XORWF,popGet(AOP(left),offset));
5271 // left & result in different registers
5272 if(AOP_TYPE(result) == AOP_CRY){
5274 // if(size), result in bit
5275 // if(!size && ifx), conditional oper: if(left ^ right)
5276 symbol *tlbl = newiTempLabel(NULL);
5277 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5279 pic14_emitcode("setb","c");
5281 if((AOP_TYPE(right) == AOP_LIT) &&
5282 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5283 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
5285 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5286 pic14_emitcode("xrl","a,%s",
5287 aopGet(AOP(left),offset,FALSE,FALSE));
5289 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5294 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5295 pic14_outBitC(result);
5297 jmpTrueOrFalse(ifx, tlbl);
5298 } else for(;(size--);offset++){
5300 // result = left & right
5301 if(AOP_TYPE(right) == AOP_LIT){
5302 int t = (lit >> (offset*8)) & 0x0FFL;
5305 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5306 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5309 emitpcode(POC_COMFW,popGet(AOP(left),offset));
5310 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5313 emitpcode(POC_MOVLW, popGetLit(t));
5314 emitpcode(POC_XORFW,popGet(AOP(left),offset));
5315 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5320 // faster than result <- left, anl result,right
5321 // and better if result is SFR
5322 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5323 emitpcode(POC_XORFW,popGet(AOP(left),offset));
5324 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5329 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5330 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5331 freeAsmop(result,NULL,ic,TRUE);
5334 /*-----------------------------------------------------------------*/
5335 /* genInline - write the inline code out */
5336 /*-----------------------------------------------------------------*/
5337 static void genInline (iCode *ic)
5339 char *buffer, *bp, *bp1;
5340 bool inComment = FALSE;
5343 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5345 _G.inLine += (!options.asmpeep);
5347 buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
5362 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
5367 /* Add \n for labels, not dirs such as c:\mydir */
5368 if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
5373 /* print label, use this special format with NULL directive
5374 * to denote that the argument should not be indented with tab */
5375 addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
5383 if ((bp1 != bp) && *bp1)
5384 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
5388 _G.inLine -= (!options.asmpeep);
5391 /*-----------------------------------------------------------------*/
5392 /* genRRC - rotate right with carry */
5393 /*-----------------------------------------------------------------*/
5394 static void genRRC (iCode *ic)
5396 operand *left , *result ;
5397 int size, offset = 0, same;
5400 /* rotate right with carry */
5402 result=IC_RESULT(ic);
5403 aopOp (left,ic,FALSE);
5404 aopOp (result,ic,FALSE);
5406 DEBUGpic14_AopType(__LINE__,left,NULL,result);
5408 same = pic14_sameRegs(AOP(result),AOP(left));
5410 size = AOP_SIZE(result);
5412 /* get the lsb and put it into the carry */
5413 emitpcode(POC_RRFW, popGet(AOP(left),size-1));
5420 emitpcode(POC_RRF, popGet(AOP(left),offset));
5422 emitpcode(POC_RRFW, popGet(AOP(left),offset));
5423 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5429 freeAsmop(left,NULL,ic,TRUE);
5430 freeAsmop(result,NULL,ic,TRUE);
5433 /*-----------------------------------------------------------------*/
5434 /* genRLC - generate code for rotate left with carry */
5435 /*-----------------------------------------------------------------*/
5436 static void genRLC (iCode *ic)
5438 operand *left , *result ;
5439 int size, offset = 0;
5443 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5444 /* rotate right with carry */
5446 result=IC_RESULT(ic);
5447 aopOp (left,ic,FALSE);
5448 aopOp (result,ic,FALSE);
5450 DEBUGpic14_AopType(__LINE__,left,NULL,result);
5452 same = pic14_sameRegs(AOP(result),AOP(left));
5454 /* move it to the result */
5455 size = AOP_SIZE(result);
5457 /* get the msb and put it into the carry */
5458 emitpcode(POC_RLFW, popGet(AOP(left),size-1));
5465 emitpcode(POC_RLF, popGet(AOP(left),offset));
5467 emitpcode(POC_RLFW, popGet(AOP(left),offset));
5468 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5475 freeAsmop(left,NULL,ic,TRUE);
5476 freeAsmop(result,NULL,ic,TRUE);
5479 /*-----------------------------------------------------------------*/
5480 /* genGetHbit - generates code get highest order bit */
5481 /*-----------------------------------------------------------------*/
5482 static void genGetHbit (iCode *ic)
5484 operand *left, *result;
5486 result=IC_RESULT(ic);
5487 aopOp (left,ic,FALSE);
5488 aopOp (result,ic,FALSE);
5491 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5492 /* get the highest order byte into a */
5493 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
5494 if(AOP_TYPE(result) == AOP_CRY){
5495 pic14_emitcode("rlc","a");
5496 pic14_outBitC(result);
5499 pic14_emitcode("rl","a");
5500 pic14_emitcode("anl","a,#0x01");
5501 pic14_outAcc(result);
5505 freeAsmop(left,NULL,ic,TRUE);
5506 freeAsmop(result,NULL,ic,TRUE);
5509 /*-----------------------------------------------------------------*/
5510 /* AccLsh - shift left accumulator by known count */
5511 /* MARK: pic14 always rotates through CARRY! */
5512 /*-----------------------------------------------------------------*/
5513 static void AccLsh (pCodeOp *pcop,int shCount)
5516 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5517 shCount &= 0x0007; // shCount : 0..7
5524 emitpcode(POC_RLF,pcop);
5528 emitpcode(POC_RLF,pcop);
5529 emitpcode(POC_RLF,pcop);
5532 emitpcode(POC_RLF,pcop);
5533 emitpcode(POC_RLF,pcop);
5534 emitpcode(POC_RLF,pcop);
5537 emitpcode(POC_SWAPF,pcop);
5540 emitpcode(POC_SWAPF,pcop);
5541 emitpcode(POC_RLF,pcop);
5544 emitpcode(POC_SWAPF,pcop);
5545 emitpcode(POC_RLF,pcop);
5546 emitpcode(POC_RLF,pcop);
5549 emitpcode(POC_RRFW,pcop);
5550 emitpcode(POC_RRF,pcop);
5553 /* clear invalid bits */
5554 emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
5555 emitpcode(POC_ANDWF, pcop);
5558 /*-----------------------------------------------------------------*/
5559 /* AccRsh - shift right accumulator by known count */
5560 /* MARK: pic14 always rotates through CARRY! */
5561 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
5562 /* 1: mask out invalid bits (zero-extend) */
5563 /* 2: sign-extend result (pretty slow) */
5564 /*-----------------------------------------------------------------*/
5565 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
5568 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5569 shCount &= 0x0007; // shCount : 0..7
5575 /* load sign if needed */
5576 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
5577 else if (mask_mode == 1) emitCLRC;
5578 emitpcode(POC_RRF,pcop);
5582 /* load sign if needed */
5583 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
5584 emitpcode(POC_RRF,pcop);
5585 /* load sign if needed */
5586 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
5587 emitpcode(POC_RRF,pcop);
5588 if (mask_mode == 2) return;
5591 /* load sign if needed */
5592 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
5593 emitpcode(POC_RRF,pcop);
5594 /* load sign if needed */
5595 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
5596 emitpcode(POC_RRF,pcop);
5597 /* load sign if needed */
5598 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
5599 emitpcode(POC_RRF,pcop);
5600 if (mask_mode == 2) return;
5603 emitpcode(POC_SWAPF,pcop);
5606 emitpcode(POC_SWAPF,pcop);
5607 emitpcode(POC_RRF,pcop);
5610 emitpcode(POC_SWAPF,pcop);
5611 emitpcode(POC_RRF,pcop);
5612 emitpcode(POC_RRF,pcop);
5618 emitpcode(POC_RLFW,pcop);
5619 emitpcode(POC_CLRF,pcop);
5621 emitpcode(POC_COMF,pcop);
5624 emitpcode(POC_RLFW,pcop);
5625 emitpcode(POC_RLF,pcop);
5632 /* leave invalid bits undefined */
5636 /* clear invalid bits -- zero-extend */
5637 emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
5638 emitpcode(POC_ANDWF, pcop);
5640 if (mask_mode == 2) {
5642 emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
5643 emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
5644 emitpcode(POC_IORWF, pcop);
5649 /*-----------------------------------------------------------------*/
5650 /* AccSRsh - signed right shift accumulator by known count */
5651 /*-----------------------------------------------------------------*/
5652 static void AccSRsh (int shCount)
5655 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5658 pic14_emitcode("mov","c,acc.7");
5659 pic14_emitcode("rrc","a");
5660 } else if(shCount == 2){
5661 pic14_emitcode("mov","c,acc.7");
5662 pic14_emitcode("rrc","a");
5663 pic14_emitcode("mov","c,acc.7");
5664 pic14_emitcode("rrc","a");
5666 tlbl = newiTempLabel(NULL);
5667 /* rotate right accumulator */
5668 AccRol(8 - shCount);
5669 /* and kill the higher order bits */
5670 pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
5671 pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5672 pic14_emitcode("orl","a,#0x%02x",
5673 (unsigned char)~SRMask[shCount]);
5674 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5679 /*-----------------------------------------------------------------*/
5680 /* shiftR1Left2Result - shift right one byte from left to result */
5681 /*-----------------------------------------------------------------*/
5682 static void shiftR1Left2ResultSigned (operand *left, int offl,
5683 operand *result, int offr,
5689 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5691 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
5695 emitpcode(POC_RLFW, popGet(AOP(left),offl));
5697 emitpcode(POC_RRF, popGet(AOP(result),offr));
5699 emitpcode(POC_RRFW, popGet(AOP(left),offl));
5700 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5706 emitpcode(POC_RLFW, popGet(AOP(left),offl));
5708 emitpcode(POC_RRF, popGet(AOP(result),offr));
5710 emitpcode(POC_RRFW, popGet(AOP(left),offl));
5711 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5713 emitpcode(POC_RLFW, popGet(AOP(result),offr));
5714 emitpcode(POC_RRF, popGet(AOP(result),offr));
5720 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
5722 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
5723 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5726 emitpcode(POC_RLFW, popGet(AOP(result),offr));
5727 emitpcode(POC_RLFW, popGet(AOP(result),offr));
5728 emitpcode(POC_ANDLW, popGetLit(0x1f));
5730 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
5731 emitpcode(POC_IORLW, popGetLit(0xe0));
5733 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5737 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
5738 emitpcode(POC_ANDLW, popGetLit(0x0f));
5739 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
5740 emitpcode(POC_IORLW, popGetLit(0xf0));
5741 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5745 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
5747 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
5748 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5750 emitpcode(POC_RRFW, popGet(AOP(result),offr));
5751 emitpcode(POC_ANDLW, popGetLit(0x07));
5752 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
5753 emitpcode(POC_IORLW, popGetLit(0xf8));
5754 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5759 emitpcode(POC_MOVLW, popGetLit(0x00));
5760 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
5761 emitpcode(POC_MOVLW, popGetLit(0xfe));
5762 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
5763 emitpcode(POC_IORLW, popGetLit(0x01));
5764 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5766 emitpcode(POC_CLRF, popGet(AOP(result),offr));
5767 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
5768 emitpcode(POC_DECF, popGet(AOP(result),offr));
5769 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
5770 emitpcode(POC_BCF, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
5776 emitpcode(POC_MOVLW, popGetLit(0x00));
5777 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
5778 emitpcode(POC_MOVLW, popGetLit(0xff));
5779 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5781 emitpcode(POC_CLRF, popGet(AOP(result),offr));
5782 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
5783 emitpcode(POC_DECF, popGet(AOP(result),offr));
5791 /*-----------------------------------------------------------------*/
5792 /* shiftR1Left2Result - shift right one byte from left to result */
5793 /*-----------------------------------------------------------------*/
5794 static void shiftR1Left2Result (operand *left, int offl,
5795 operand *result, int offr,
5796 int shCount, int sign)
5801 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5803 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
5805 /* Copy the msb into the carry if signed. */
5807 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
5817 emitpcode(POC_RRF, popGet(AOP(result),offr));
5819 emitpcode(POC_RRFW, popGet(AOP(left),offl));
5820 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5826 emitpcode(POC_RRF, popGet(AOP(result),offr));
5828 emitpcode(POC_RRFW, popGet(AOP(left),offl));
5829 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5832 emitpcode(POC_RRF, popGet(AOP(result),offr));
5837 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
5839 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
5840 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5843 emitpcode(POC_RLFW, popGet(AOP(result),offr));
5844 emitpcode(POC_RLFW, popGet(AOP(result),offr));
5845 emitpcode(POC_ANDLW, popGetLit(0x1f));
5846 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5850 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
5851 emitpcode(POC_ANDLW, popGetLit(0x0f));
5852 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5856 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
5857 emitpcode(POC_ANDLW, popGetLit(0x0f));
5858 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5860 emitpcode(POC_RRF, popGet(AOP(result),offr));
5865 emitpcode(POC_RLFW, popGet(AOP(left),offl));
5866 emitpcode(POC_ANDLW, popGetLit(0x80));
5867 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5868 emitpcode(POC_RLF, popGet(AOP(result),offr));
5869 emitpcode(POC_RLF, popGet(AOP(result),offr));
5874 emitpcode(POC_RLFW, popGet(AOP(left),offl));
5875 emitpcode(POC_CLRF, popGet(AOP(result),offr));
5876 emitpcode(POC_RLF, popGet(AOP(result),offr));
5885 /*-----------------------------------------------------------------*/
5886 /* shiftL1Left2Result - shift left one byte from left to result */
5887 /*-----------------------------------------------------------------*/
5888 static void shiftL1Left2Result (operand *left, int offl,
5889 operand *result, int offr, int shCount)
5895 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5897 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
5898 DEBUGpic14_emitcode ("; ***","same = %d",same);
5899 // l = aopGet(AOP(left),offl,FALSE,FALSE);
5901 /* shift left accumulator */
5902 //AccLsh(shCount); // don't comment out just yet...
5903 // aopPut(AOP(result),"a",offr);
5907 /* Shift left 1 bit position */
5908 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
5910 emitpcode(POC_ADDWF, popGet(AOP(left),offl));
5912 emitpcode(POC_ADDFW, popGet(AOP(left),offl));
5913 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5917 emitpcode(POC_RLFW, popGet(AOP(left),offl));
5918 emitpcode(POC_ANDLW,popGetLit(0x7e));
5919 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
5920 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
5923 emitpcode(POC_RLFW, popGet(AOP(left),offl));
5924 emitpcode(POC_ANDLW,popGetLit(0x3e));
5925 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
5926 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
5927 emitpcode(POC_RLF, popGet(AOP(result),offr));
5930 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
5931 emitpcode(POC_ANDLW, popGetLit(0xf0));
5932 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
5935 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
5936 emitpcode(POC_ANDLW, popGetLit(0xf0));
5937 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
5938 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
5941 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
5942 emitpcode(POC_ANDLW, popGetLit(0x30));
5943 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
5944 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
5945 emitpcode(POC_RLF, popGet(AOP(result),offr));
5948 emitpcode(POC_RRFW, popGet(AOP(left),offl));
5949 emitpcode(POC_CLRF, popGet(AOP(result),offr));
5950 emitpcode(POC_RRF, popGet(AOP(result),offr));
5954 DEBUGpic14_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
5960 /*-----------------------------------------------------------------*/
5961 /* movLeft2Result - move byte from left to result */
5962 /*-----------------------------------------------------------------*/
5963 static void movLeft2Result (operand *left, int offl,
5964 operand *result, int offr)
5967 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5968 if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5969 aopGet(AOP(left),offl,FALSE,FALSE);
5971 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
5972 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5976 /*-----------------------------------------------------------------*/
5977 /* shiftLeft_Left2ResultLit - shift left by known count */
5978 /*-----------------------------------------------------------------*/
5980 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
5982 int size, same, offr, i;
5984 size = AOP_SIZE(left);
5985 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
5987 same = pic14_sameRegs (AOP(left), AOP(result));
5990 shCount = shCount & 0x07;
5996 case 0: /* takes 0 or 2N cycles (for offr==0) */
5997 if (!same || offr) {
5998 for (i=size-1; i >= 0; i--)
5999 movLeft2Result (left, i, result, offr + i);
6003 case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6005 shiftLeft_Left2ResultLit (left, result, 8 * offr);
6006 shiftLeft_Left2ResultLit (result, result, shCount);
6007 return; /* prevent clearing result again */
6010 for (i=0; i < size; i++) {
6011 if (same && !offr) {
6012 emitpcode (POC_RLF, popGet (AOP(left), i));
6014 emitpcode (POC_RLFW, popGet (AOP(left), i));
6015 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6021 case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
6022 /* works in-place/with offr as well */
6023 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
6024 emitpcode (POC_ANDLW, popGetLit (0xF0));
6025 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
6027 for (i = size - 2; i >= 0; i--)
6029 emitpcode (POC_SWAPFW, popGet (AOP(left), i));
6030 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6031 emitpcode (POC_ANDLW, popGetLit (0x0F));
6032 emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
6033 emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
6037 case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
6038 /* works in-place/with offr as well */
6039 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
6040 for (i = size-2; i >= 0; i--) {
6041 emitpcode (POC_RRFW, popGet (AOP(left), i));
6042 emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
6044 emitpcode (POC_CLRF, popGet (AOP(result), offr));
6045 emitpcode (POC_RRF, popGet (AOP(result), offr));
6049 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
6050 shiftLeft_Left2ResultLit (result, result, 1);
6051 return; /* prevent clearing result again */
6057 emitpcode (POC_CLRF, popGet (AOP(result), offr));
6061 /*-----------------------------------------------------------------*/
6062 /* shiftRight_Left2ResultLit - shift right by known count */
6063 /*-----------------------------------------------------------------*/
6065 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
6067 int size, same, offr, i;
6069 size = AOP_SIZE(left);
6070 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6072 same = pic14_sameRegs (AOP(left), AOP(result));
6075 shCount = shCount & 0x07;
6083 case 0: /* takes 0 or 2N cycles (for offr==0) */
6084 if (!same || offr) {
6085 for (i=0; i < size; i++)
6086 movLeft2Result (left, i + offr, result, i);
6090 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
6091 emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
6093 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
6094 shiftRight_Left2ResultLit (result, result, shCount, sign);
6095 return; /* prevent sign-extending result again */
6099 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
6102 for (i = size-1; i >= 0; i--) {
6103 if (same && !offr) {
6104 emitpcode (POC_RRF, popGet (AOP(left), i));
6106 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
6107 emitpcode (POC_MOVWF, popGet (AOP(result), i));
6113 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
6114 /* works in-place/with offr as well */
6115 emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
6116 emitpcode (POC_ANDLW, popGetLit (0x0F));
6117 emitpcode (POC_MOVWF, popGet(AOP(result), 0));
6119 for (i = 1; i < size; i++)
6121 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
6122 emitpcode (POC_MOVWF, popGet (AOP(result), i));
6123 emitpcode (POC_ANDLW, popGetLit (0xF0));
6124 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
6125 emitpcode (POC_XORWF, popGet (AOP(result), i));
6130 emitpcode (POC_MOVLW, popGetLit (0xF0));
6131 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
6132 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
6136 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
6137 /* works in-place/with offr as well */
6138 emitpcode (POC_RLFW, popGet (AOP(left), offr));
6139 for (i = 0; i < size-1; i++) {
6140 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
6141 emitpcode (POC_MOVWF, popGet (AOP(result), i));
6143 emitpcode (POC_CLRF, popGet (AOP(result), size-1));
6145 emitpcode (POC_RLF, popGet (AOP(result), size-1));
6148 emitpcode (POC_DECF, popGet (AOP(result), size-1));
6153 shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
6154 shiftRight_Left2ResultLit (result, result, 1, sign);
6155 return; /* prevent sign extending result again */
6160 addSign (result, size, sign);
6164 /*-----------------------------------------------------------------*/
6165 /* shiftL2Left2Result - shift left two bytes from left to result */
6166 /*-----------------------------------------------------------------*/
6167 static void shiftL2Left2Result (operand *left, int offl,
6168 operand *result, int offr, int shCount)
6172 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6174 if(pic14_sameRegs(AOP(result), AOP(left))) {
6182 emitpcode(POC_MOVFW,popGet(AOP(result),offr));
6183 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6184 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6188 emitpcode(POC_RLF, popGet(AOP(result),offr));
6189 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6195 emitpcode(POC_MOVLW, popGetLit(0x0f));
6196 emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
6197 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6198 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6199 emitpcode(POC_ANDFW, popGet(AOP(result),offr));
6200 emitpcode(POC_XORWF, popGet(AOP(result),offr));
6201 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6203 emitpcode(POC_RLF, popGet(AOP(result),offr));
6204 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6208 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6209 emitpcode(POC_RRF, popGet(AOP(result),offr));
6210 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6211 emitpcode(POC_RRF, popGet(AOP(result),offr));
6212 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6213 emitpcode(POC_ANDLW,popGetLit(0xc0));
6214 emitpcode(POC_XORFW,popGet(AOP(result),offr));
6215 emitpcode(POC_XORWF,popGet(AOP(result),offr));
6216 emitpcode(POC_XORFW,popGet(AOP(result),offr));
6217 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6220 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6221 emitpcode(POC_RRFW, popGet(AOP(result),offr));
6222 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6223 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6224 emitpcode(POC_RRF, popGet(AOP(result),offr));
6234 /* note, use a mov/add for the shift since the mov has a
6235 chance of getting optimized out */
6236 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6237 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6238 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6239 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6240 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6244 emitpcode(POC_RLF, popGet(AOP(result),offr));
6245 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6251 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6252 emitpcode(POC_ANDLW, popGetLit(0xF0));
6253 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6254 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6255 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6256 emitpcode(POC_ANDLW, popGetLit(0xF0));
6257 emitpcode(POC_XORWF, popGet(AOP(result),offr));
6258 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6262 emitpcode(POC_RLF, popGet(AOP(result),offr));
6263 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6267 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6268 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6269 emitpcode(POC_RRFW, popGet(AOP(result),offl));
6270 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6272 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6273 emitpcode(POC_RRF, popGet(AOP(result),offr));
6274 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6275 emitpcode(POC_ANDLW,popGetLit(0xc0));
6276 emitpcode(POC_XORFW,popGet(AOP(result),offr));
6277 emitpcode(POC_XORWF,popGet(AOP(result),offr));
6278 emitpcode(POC_XORFW,popGet(AOP(result),offr));
6279 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6282 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6283 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6284 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6285 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6286 emitpcode(POC_RRF, popGet(AOP(result),offr));
6292 /*-----------------------------------------------------------------*/
6293 /* shiftR2Left2Result - shift right two bytes from left to result */
6294 /*-----------------------------------------------------------------*/
6295 static void shiftR2Left2Result (operand *left, int offl,
6296 operand *result, int offr,
6297 int shCount, int sign)
6302 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6303 same = pic14_sameRegs(AOP(result), AOP(left));
6305 if(same && ((offl + MSB16) == offr)){
6307 /* don't crash result[offr] */
6308 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6309 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6312 movLeft2Result(left,offl, result, offr);
6313 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6316 /* a:x >> shCount (x = lsb(result))*/
6324 emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
6329 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6330 emitpcode(POC_RRF,popGet(AOP(result),offr));
6332 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6333 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6334 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6335 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6340 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
6343 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6344 emitpcode(POC_RRF,popGet(AOP(result),offr));
6351 emitpcode(POC_MOVLW, popGetLit(0xf0));
6352 emitpcode(POC_ANDWF, popGet(AOP(result),offr));
6353 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6355 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6356 emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
6357 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6358 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6360 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6361 emitpcode(POC_ANDLW, popGetLit(0x0f));
6362 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6364 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6365 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6366 emitpcode(POC_ANDLW, popGetLit(0xf0));
6367 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6368 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6372 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6373 emitpcode(POC_RRF, popGet(AOP(result),offr));
6377 emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
6378 emitpcode(POC_BTFSC,
6379 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
6380 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6388 emitpcode(POC_RLF, popGet(AOP(result),offr));
6389 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6391 emitpcode(POC_RLF, popGet(AOP(result),offr));
6392 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6393 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6394 emitpcode(POC_ANDLW,popGetLit(0x03));
6396 emitpcode(POC_BTFSC,
6397 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
6398 emitpcode(POC_IORLW,popGetLit(0xfc));
6400 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6401 emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
6402 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6403 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6405 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6406 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6407 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6408 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6409 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6410 emitpcode(POC_RLF, popGet(AOP(result),offr));
6411 emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
6412 emitpcode(POC_ANDLW,popGetLit(0x03));
6414 emitpcode(POC_BTFSC,
6415 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
6416 emitpcode(POC_IORLW,popGetLit(0xfc));
6418 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6419 //emitpcode(POC_RLF, popGet(AOP(result),offr));
6426 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6427 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6428 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6429 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
6432 emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
6434 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6438 /*-----------------------------------------------------------------*/
6439 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
6440 /*-----------------------------------------------------------------*/
6441 static void shiftLLeftOrResult (operand *left, int offl,
6442 operand *result, int offr, int shCount)
6445 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6447 /* shift left accumulator */
6448 AccLsh(left,offl,shCount);
6449 /* or with result */
6450 emitpcode (POC_IORWF, popGet (AOP(result), offr));
6451 assert ( !"broken (modifies left, fails for left==result))" );
6454 /*-----------------------------------------------------------------*/
6455 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
6456 /*-----------------------------------------------------------------*/
6457 static void shiftRLeftOrResult (operand *left, int offl,
6458 operand *result, int offr, int shCount)
6461 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6463 /* shift right accumulator */
6464 AccRsh(left,offl,shCount);
6465 /* or with result */
6466 emitpcode (POC_IORWF, popGet (AOP(result), offr));
6467 assert ( !"broken (modifies left, fails for left==result))" );
6470 /*-----------------------------------------------------------------*/
6471 /* genlshOne - left shift a one byte quantity by known count */
6472 /*-----------------------------------------------------------------*/
6473 static void genlshOne (operand *result, operand *left, int shCount)
6476 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6477 shiftL1Left2Result(left, LSB, result, LSB, shCount);
6480 /*-----------------------------------------------------------------*/
6481 /* genlshTwo - left shift two bytes by known amount != 0 */
6482 /*-----------------------------------------------------------------*/
6483 static void genlshTwo (operand *result,operand *left, int shCount)
6488 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6489 size = pic14_getDataSize(result);
6491 /* if shCount >= 8 */
6497 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6499 movLeft2Result(left, LSB, result, MSB16);
6501 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
6504 /* 1 <= shCount <= 7 */
6507 shiftL1Left2Result(left, LSB, result, LSB, shCount);
6509 shiftL2Left2Result(left, LSB, result, LSB, shCount);
6513 /*-----------------------------------------------------------------*/
6514 /* shiftLLong - shift left one long from left to result */
6515 /* offl = LSB or MSB16 */
6516 /*-----------------------------------------------------------------*/
6517 static void shiftLLong (operand *left, operand *result, int offr )
6520 int size = AOP_SIZE(result);
6523 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6524 if(size >= LSB+offr){
6525 l = aopGet(AOP(left),LSB,FALSE,FALSE);
6527 pic14_emitcode("add","a,acc");
6528 if (pic14_sameRegs(AOP(left),AOP(result)) &&
6529 size >= MSB16+offr && offr != LSB )
6530 pic14_emitcode("xch","a,%s",
6531 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
6533 aopPut(AOP(result),"a",LSB+offr);
6536 if(size >= MSB16+offr){
6537 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6538 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
6541 pic14_emitcode("rlc","a");
6542 if (pic14_sameRegs(AOP(left),AOP(result)) &&
6543 size >= MSB24+offr && offr != LSB)
6544 pic14_emitcode("xch","a,%s",
6545 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
6547 aopPut(AOP(result),"a",MSB16+offr);
6550 if(size >= MSB24+offr){
6551 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
6552 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
6555 pic14_emitcode("rlc","a");
6556 if (pic14_sameRegs(AOP(left),AOP(result)) &&
6557 size >= MSB32+offr && offr != LSB )
6558 pic14_emitcode("xch","a,%s",
6559 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
6561 aopPut(AOP(result),"a",MSB24+offr);
6564 if(size > MSB32+offr){
6565 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
6566 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
6569 pic14_emitcode("rlc","a");
6570 aopPut(AOP(result),"a",MSB32+offr);
6573 aopPut(AOP(result),zero,LSB);
6576 /*-----------------------------------------------------------------*/
6577 /* genlshFour - shift four byte by a known amount != 0 */
6578 /*-----------------------------------------------------------------*/
6579 static void genlshFour (operand *result, operand *left, int shCount)
6584 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6585 size = AOP_SIZE(result);
6587 /* if shifting more that 3 bytes */
6588 if (shCount >= 24 ) {
6591 /* lowest order of left goes to the highest
6592 order of the destination */
6593 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6595 movLeft2Result(left, LSB, result, MSB32);
6596 aopPut(AOP(result),zero,LSB);
6597 aopPut(AOP(result),zero,MSB16);
6598 aopPut(AOP(result),zero,MSB32);
6602 /* more than two bytes */
6603 else if ( shCount >= 16 ) {
6604 /* lower order two bytes goes to higher order two bytes */
6606 /* if some more remaining */
6608 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6610 movLeft2Result(left, MSB16, result, MSB32);
6611 movLeft2Result(left, LSB, result, MSB24);
6613 aopPut(AOP(result),zero,MSB16);
6614 aopPut(AOP(result),zero,LSB);
6618 /* if more than 1 byte */
6619 else if ( shCount >= 8 ) {
6620 /* lower order three bytes goes to higher order three bytes */
6624 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6626 movLeft2Result(left, LSB, result, MSB16);
6628 else{ /* size = 4 */
6630 movLeft2Result(left, MSB24, result, MSB32);
6631 movLeft2Result(left, MSB16, result, MSB24);
6632 movLeft2Result(left, LSB, result, MSB16);
6633 aopPut(AOP(result),zero,LSB);
6635 else if(shCount == 1)
6636 shiftLLong(left, result, MSB16);
6638 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
6639 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6640 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6641 aopPut(AOP(result),zero,LSB);
6646 /* 1 <= shCount <= 7 */
6647 else if(shCount <= 2){
6648 shiftLLong(left, result, LSB);
6650 shiftLLong(result, result, LSB);
6652 /* 3 <= shCount <= 7, optimize */
6654 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6655 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6656 shiftL2Left2Result(left, LSB, result, LSB, shCount);
6662 /*-----------------------------------------------------------------*/
6663 /* genLeftShiftLiteral - left shifting by known count */
6664 /*-----------------------------------------------------------------*/
6665 static void genLeftShiftLiteral (operand *left,
6670 int shCount = (int) ulFromVal (AOP(right)->aopu.aop_lit);
6674 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6675 freeAsmop(right,NULL,ic,TRUE);
6677 aopOp(left,ic,FALSE);
6678 aopOp(result,ic,FALSE);
6680 size = getSize(operandType(result));
6683 pic14_emitcode("; shift left ","result %d, left %d",size,
6687 /* I suppose that the left size >= result size */
6690 movLeft2Result(left, size, result, size);
6694 else if(shCount >= (size * 8))
6696 aopPut(AOP(result),zero,size);
6700 genlshOne (result,left,shCount);
6705 genlshTwo (result,left,shCount);
6709 genlshFour (result,left,shCount);
6713 freeAsmop(left,NULL,ic,TRUE);
6714 freeAsmop(result,NULL,ic,TRUE);
6718 /*-----------------------------------------------------------------*
6719 * genMultiAsm - repeat assembly instruction for size of register.
6720 * if endian == 1, then the high byte (i.e base address + size of
6721 * register) is used first else the low byte is used first;
6722 *-----------------------------------------------------------------*/
6723 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
6729 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6742 emitpcode(poc, popGet(AOP(reg),offset));
6748 /*-----------------------------------------------------------------*/
6749 /* loadSignToC - load the operand's sign bit into CARRY */
6750 /*-----------------------------------------------------------------*/
6752 static void loadSignToC (operand *op)
6755 assert (op && AOP(op) && AOP_SIZE(op));
6758 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
6762 /*-----------------------------------------------------------------*/
6763 /* genRightShift - generate code for right shifting */
6764 /*-----------------------------------------------------------------*/
6765 static void genGenericShift (iCode *ic, int shiftRight)
6767 operand *right, *left, *result;
6770 symbol *tlbl, *tlbl1, *inverselbl;
6773 /* if signed then we do it the hard way preserve the
6774 sign bit moving it inwards */
6775 retype = getSpec(operandType(IC_RESULT(ic)));
6776 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6778 /* signed & unsigned types are treated the same : i.e. the
6779 signed is NOT propagated inwards : quoting from the
6780 ANSI - standard : "for E1 >> E2, is equivalent to division
6781 by 2**E2 if unsigned or if it has a non-negative value,
6782 otherwise the result is implementation defined ", MY definition
6783 is that the sign does not get propagated */
6785 right = IC_RIGHT(ic);
6787 result = IC_RESULT(ic);
6789 aopOp(right,ic,FALSE);
6790 aopOp(left,ic,FALSE);
6791 aopOp(result,ic,FALSE);
6793 /* if the shift count is known then do it
6794 as efficiently as possible */
6795 if (AOP_TYPE(right) == AOP_LIT) {
6796 int lit = (int) ulFromVal (AOP(right)->aopu.aop_lit);
6800 shiftRight = !shiftRight;
6804 shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
6806 shiftLeft_Left2ResultLit (left, result, lit);
6807 //genRightShiftLiteral (left,right,result,ic, 0);
6811 /* shift count is unknown then we have to form
6812 a loop get the loop count in B : Note: we take
6813 only the lower order byte since shifting
6814 more that 32 bits make no sense anyway, ( the
6815 largest size of an object can be only 32 bits ) */
6817 /* we must not overwrite the shift counter */
6818 assert (!pic14_sameRegs(AOP(right),AOP(result)));
6820 /* now move the left to the result if they are not the
6822 if (!pic14_sameRegs(AOP(left),AOP(result)))
6824 size = min(AOP_SIZE(result), AOP_SIZE(left));
6826 mov2w(AOP(left), size);
6827 movwf(AOP(result), size);
6829 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
6832 tlbl = newiTempLabel(NULL);
6833 tlbl1= newiTempLabel(NULL);
6835 size = AOP_SIZE(result);
6837 mov2w(AOP(right),0);
6838 if (!SPEC_USIGN(operandType(right)))
6840 inverselbl = newiTempLabel(NULL);
6841 /* signed shift count -- invert shift direction for c<0 */
6842 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
6843 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
6845 emitpcode(POC_SUBLW, popGetLit(0)); /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
6846 /* check for `a = b >> c' with `-c == 0' */
6848 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
6849 emitpLabel(tlbl->key);
6850 /* propagate the sign bit inwards for SIGNED result */
6851 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
6852 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
6853 emitpcode(POC_ADDLW, popGetLit(1)); /* clears CARRY (unless W==0 afterwards) */
6855 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
6857 if (!SPEC_USIGN(operandType(right)))
6859 symbol *inv_loop = newiTempLabel(NULL);
6861 shiftRight = !shiftRight; /* invert shift direction */
6863 /* we came here from the code above -- we are done */
6864 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
6866 /* emit code for shifting N<0 steps, count is already in W */
6867 emitpLabel(inverselbl->key);
6868 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
6869 emitpLabel(inv_loop->key);
6870 /* propagate the sign bit inwards for SIGNED result */
6871 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
6872 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
6873 emitpcode(POC_ADDLW, popGetLit(1));
6875 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
6878 emitpLabel(tlbl1->key);
6880 freeAsmop(left,NULL,ic,TRUE);
6881 freeAsmop (right,NULL,ic,TRUE);
6882 freeAsmop(result,NULL,ic,TRUE);
6885 static void genRightShift (iCode *ic)
6887 genGenericShift(ic, 1);
6890 static void genLeftShift (iCode *ic)
6892 genGenericShift(ic, 0);
6895 /*-----------------------------------------------------------------*/
6896 /* SetIrp - Set IRP bit */
6897 /*-----------------------------------------------------------------*/
6898 static void SetIrp(operand *result)
6901 if (AOP_TYPE(result) == AOP_LIT) {
6902 unsigned lit = (unsigned) double2ul (operandLitValue(result));
6908 if ((AOP_TYPE(result) == AOP_PCODE)
6909 && (AOP(result)->aopu.pcop->type == PO_LITERAL))
6911 int addrs = PCOL(AOP(result)->aopu.pcop)->lit;
6917 emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
6918 if(AOP_SIZE(result) > 1) {
6919 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
6927 setup_fsr (operand *ptr)
6930 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
6932 /* also setup-up IRP */
6936 /*-----------------------------------------------------------------*/
6937 /* emitPtrByteGet - emits code to get a byte into WREG from an */
6938 /* arbitrary pointer (__code, __data, generic) */
6939 /*-----------------------------------------------------------------*/
6941 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
6948 if (!alreadyAddressed) setup_fsr (src);
6949 emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
6953 assert( AOP_SIZE(src) == 2 );
6955 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
6957 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
6958 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
6959 call_libraryfunc ("__gptrget1");
6963 assert( AOP_SIZE(src) == 3 );
6965 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
6967 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
6969 call_libraryfunc ("__gptrget1");
6973 assert( !"unhandled pointer type" );
6978 /*-----------------------------------------------------------------*/
6979 /* emitPtrByteSet - emits code to set a byte from src through a */
6980 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR). */
6981 /*-----------------------------------------------------------------*/
6983 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
6990 if (!alreadyAddressed) setup_fsr (dst);
6991 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
6995 assert( !"trying to assign to __code pointer" );
6999 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
7001 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
7003 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
7005 call_libraryfunc ("__gptrput1");
7009 assert( !"unhandled pointer type" );
7014 /*-----------------------------------------------------------------*/
7015 /* genUnpackBits - generates code for unpacking bits */
7016 /*-----------------------------------------------------------------*/
7017 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
7019 int rsize; /* result size */
7020 sym_link *etype; /* bitfield type information */
7021 int blen; /* bitfield length */
7022 int bstr; /* bitfield starting bit within byte */
7025 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7026 etype = getSpec(operandType(result));
7027 rsize = getSize (operandType (result));
7028 blen = SPEC_BLEN (etype);
7029 bstr = SPEC_BSTR (etype);
7031 /* single bit field case */
7033 if (ifx) { /* that is for an if statement */
7036 resolveIfx(&rIfx,ifx);
7037 if (ptype == -1) /* direct */
7038 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
7040 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
7041 emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
7042 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
7046 assert (!pic14_sameRegs (AOP(result), AOP(left)));
7047 for (i=0; i < AOP_SIZE(result); i++)
7048 emitpcode (POC_CLRF, popGet (AOP(result), i));
7053 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
7054 /* adjust result below */
7061 emitPtrByteGet (left, ptype, FALSE);
7062 emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
7064 /* adjust result below */
7068 assert( !"unhandled pointer type" );
7071 /* move sign-/zero extended bit to result */
7072 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
7073 emitpcode (POC_INCF, popGet (AOP(result), 0));
7075 emitpcode (POC_DECF, popGet (AOP(result), 0));
7077 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
7081 else if (blen <= 8 && ((blen + bstr) <= 8))
7086 for (i=0; i < AOP_SIZE(result); i++)
7087 emitpcode (POC_CLRF, popGet (AOP(result), i));
7092 mov2w(AOP(left), 0);
7099 emitPtrByteGet (left, ptype, FALSE);
7103 assert( !"unhandled pointer type" );
7107 emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
7108 movwf(AOP(result), 0);
7109 AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
7111 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
7113 /* signed bitfield */
7114 assert (bstr + blen > 0);
7115 emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
7116 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
7117 emitpcode(POC_IORWF, popGet(AOP(result),0));
7119 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
7123 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
7127 /*-----------------------------------------------------------------*/
7128 /* genDataPointerGet - generates code when ptr offset is known */
7129 /*-----------------------------------------------------------------*/
7130 static void genDataPointerGet (operand *left,
7134 int size , offset = 0;
7137 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7140 /* optimization - most of the time, left and result are the same
7141 * address, but different types. for the pic code, we could omit
7144 aopOp(result,ic,TRUE);
7146 if (pic14_sameRegs (AOP(left), AOP(result)))
7149 DEBUGpic14_AopType(__LINE__,left,NULL,result);
7151 //emitpcode(POC_MOVFW, popGet(AOP(left),0));
7153 size = AOP_SIZE(result);
7154 if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
7158 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
7159 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7163 freeAsmop(left,NULL,ic,TRUE);
7164 freeAsmop(result,NULL,ic,TRUE);
7168 /*-----------------------------------------------------------------*/
7169 /* genNearPointerGet - pic14_emitcode for near pointer fetch */
7170 /*-----------------------------------------------------------------*/
7171 static void genNearPointerGet (operand *left,
7176 sym_link *ltype = operandType(left);
7177 sym_link *rtype = operandType(result);
7178 sym_link *retype= getSpec(rtype); /* bitfield type information */
7182 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7185 aopOp(left,ic,FALSE);
7187 /* if left is rematerialisable and
7188 result is not bit variable type and
7189 the left is pointer to data space i.e
7190 lower 128 bytes of space */
7191 if (AOP_TYPE(left) == AOP_PCODE && //AOP_TYPE(left) == AOP_IMMD &&
7192 !IS_BITVAR(retype) &&
7193 PIC_IS_DATA_PTR(ltype)) {
7194 genDataPointerGet (left,result,ic);
7198 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7199 aopOp (result,ic,FALSE);
7201 /* Check if can access directly instead of via a pointer */
7202 if ((AOP_TYPE(left) == AOP_PCODE)
7203 && (AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
7204 && (AOP_SIZE(result) == 1))
7209 if (IS_BITFIELD(getSpec(operandType(result))))
7211 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
7215 /* If the pointer value is not in a the FSR then need to put it in */
7216 /* Must set/reset IRP bit for use with FSR. */
7221 /* if bitfield then unpack the bits */
7223 /* we have can just get the values */
7224 int size = AOP_SIZE(result);
7227 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7231 emitpcode(POC_MOVWF,popGet(AOP(left),0));
7233 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
7234 if (AOP_TYPE(result) == AOP_LIT) {
7235 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
7237 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
7239 if (size && !direct)
7240 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
7245 /* now some housekeeping stuff */
7247 /* we had to allocate for this iCode */
7248 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7249 freeAsmop(NULL,aop,ic,TRUE);
7251 /* we did not allocate which means left
7252 already in a pointer register, then
7253 if size > 0 && this could be used again
7254 we have to point it back to where it
7256 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7257 if (AOP_SIZE(result) > 1 &&
7258 !OP_SYMBOL(left)->remat &&
7259 ( OP_SYMBOL(left)->liveTo > ic->seq ||
7261 int size = AOP_SIZE(result) - 1;
7263 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
7269 freeAsmop(left,NULL,ic,TRUE);
7270 freeAsmop(result,NULL,ic,TRUE);
7274 /*-----------------------------------------------------------------*/
7275 /* genGenPointerGet - gget value from generic pointer space */
7276 /*-----------------------------------------------------------------*/
7277 static void genGenPointerGet (operand *left,
7278 operand *result, iCode *ic)
7281 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7282 aopOp(left,ic,FALSE);
7283 aopOp(result,ic,FALSE);
7286 DEBUGpic14_AopType(__LINE__,left,NULL,result);
7288 if (IS_BITFIELD(getSpec(operandType(result))))
7290 genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
7295 /* emit call to __gptrget */
7296 char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
7297 int size = AOP_SIZE(result);
7300 assert (size > 0 && size <= 4);
7302 /* pass arguments */
7303 assert (AOP_SIZE(left) == 3);
7304 mov2w(AOP(left), 0);
7305 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
7306 mov2w(AOP(left), 1);
7307 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
7308 mov2w(AOP(left), 2);
7309 call_libraryfunc (func[size]);
7312 movwf (AOP(result), --size);
7314 emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
7315 movwf (AOP(result), size);
7319 freeAsmop(left,NULL,ic,TRUE);
7320 freeAsmop(result,NULL,ic,TRUE);
7324 /*-----------------------------------------------------------------*/
7325 /* genConstPointerGet - get value from const generic pointer space */
7326 /*-----------------------------------------------------------------*/
7327 static void genConstPointerGet (operand *left,
7328 operand *result, iCode *ic)
7330 //sym_link *retype = getSpec(operandType(result));
7332 symbol *albl, *blbl;//, *clbl;
7339 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7340 aopOp(left,ic,FALSE);
7341 aopOp(result,ic,FALSE);
7343 size = AOP_SIZE(result);
7345 DEBUGpic14_AopType(__LINE__,left,NULL,result);
7347 DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
7349 lit = op_isLitLike (left);
7350 poc = lit ? POC_MOVLW : POC_MOVFW;
7352 if (IS_BITFIELD(getSpec(operandType(result))))
7354 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
7359 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
7360 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
7361 assert (size > 0 && size <= 4);
7364 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
7366 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
7367 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
7368 call_libraryfunc (func[size]);
7370 movwf(AOP(result),size-1);
7371 for (i = 1; i < size; i++)
7373 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
7374 movwf(AOP(result),size - 1 - i);
7379 freeAsmop(left,NULL,ic,TRUE);
7380 freeAsmop(result,NULL,ic,TRUE);
7383 /*-----------------------------------------------------------------*/
7384 /* genPointerGet - generate code for pointer get */
7385 /*-----------------------------------------------------------------*/
7386 static void genPointerGet (iCode *ic)
7388 operand *left, *result ;
7389 sym_link *type, *etype;
7393 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7396 result = IC_RESULT(ic) ;
7398 /* depending on the type of pointer we need to
7399 move it to the correct pointer register */
7400 type = operandType(left);
7401 etype = getSpec(type);
7403 if (IS_PTR_CONST(type))
7404 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
7406 /* if left is of type of pointer then it is simple */
7407 if (IS_PTR(type) && !IS_FUNC(type->next))
7408 p_type = DCL_TYPE(type);
7410 /* we have to go by the storage class */
7411 p_type = PTR_TYPE(SPEC_OCLS(etype));
7413 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
7415 if (SPEC_OCLS(etype)->codesp ) {
7416 DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
7417 //p_type = CPOINTER ;
7420 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
7421 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
7422 /*p_type = FPOINTER ;*/
7424 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
7425 DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
7426 /* p_type = PPOINTER; */
7428 if (SPEC_OCLS(etype) == idata )
7429 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
7430 /* p_type = IPOINTER; */
7432 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
7433 /* p_type = POINTER ; */
7436 /* now that we have the pointer type we assign
7437 the pointer values */
7443 genNearPointerGet (left,result,ic);
7447 genPagedPointerGet(left,result,ic);
7451 genFarPointerGet (left,result,ic);
7455 genConstPointerGet (left,result,ic);
7459 genGenPointerGet (left,result,ic);
7462 assert ( !"unhandled pointer type" );
7468 /*-----------------------------------------------------------------*/
7469 /* genPackBits - generates code for packed bit storage */
7470 /*-----------------------------------------------------------------*/
7471 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
7473 int blen; /* bitfield length */
7474 int bstr; /* bitfield starting bit within byte */
7475 int litval; /* source literal value (if AOP_LIT) */
7476 unsigned char mask; /* bitmask within current byte */
7479 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7481 blen = SPEC_BLEN (etype);
7482 bstr = SPEC_BSTR (etype);
7484 /* If the bitfield length is less than a byte and does not cross byte boundaries */
7485 if ((blen <= 8) && ((bstr + blen) <= 8))
7487 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7488 (unsigned char) (0xFF >> (8 - bstr)));
7490 if (AOP_TYPE (right) == AOP_LIT)
7492 /* Case with a bitfield length <8 and literal source */
7493 int lit = (int) ulFromVal (AOP (right)->aopu.aop_lit);
7500 if (AOP(result)->type == AOP_PCODE)
7501 pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
7503 pcop = popGet(AOP(result),0);
7504 emitpcode(lit?POC_BSF:POC_BCF,pcop);
7510 emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
7514 assert( !"trying to assign to bitfield via pointer to __code space" );
7518 emitPtrByteGet(result, p_type, FALSE);
7520 emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
7522 emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
7524 emitPtrByteSet(result, p_type, TRUE);
7528 assert( !"unhandled pointer type" );
7530 } // switch (p_type)
7533 litval = lit << bstr;
7534 litval &= (~mask) & 0x00ff;
7539 mov2w (AOP(result), 0);
7540 if ((litval|mask) != 0x00ff)
7541 emitpcode(POC_ANDLW, popGetLit (mask));
7543 emitpcode(POC_IORLW, popGetLit (litval));
7544 movwf (AOP(result), 0);
7550 emitPtrByteGet(result, p_type, FALSE);
7551 if ((litval|mask) != 0x00ff)
7552 emitpcode(POC_ANDLW, popGetLit (mask));
7554 emitpcode(POC_IORLW, popGetLit (litval));
7555 emitPtrByteSet(result, p_type, TRUE);
7559 assert( !"trying to assign to bitfield via pointer to __code space" );
7563 assert( !"unhandled pointer type" );
7570 /* right is no literal */
7575 /* Note more efficient code, of pre clearing bit then only setting it if required,
7576 * can only be done if it is known that the result is not a SFR */
7577 emitpcode(POC_RRFW,popGet(AOP(right),0));
7579 emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
7581 emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
7587 emitPtrByteGet (result, p_type, FALSE);
7588 emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
7589 emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
7590 emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
7591 emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
7592 emitPtrByteSet (result, p_type, TRUE);
7596 assert( !"trying to assign to bitfield via pointer to __code space" );
7600 assert( !"unhandled pointer type" );
7605 /* Case with a bitfield 1 < length <= 8 and arbitrary source */
7606 pCodeOp *temp = popGetTempReg ();
7608 mov2w (AOP(right), 0);
7610 emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
7612 emitpcode(POC_MOVWF, temp);
7614 AccLsh (temp, bstr);
7620 mov2w (AOP(result), 0);
7621 emitpcode(POC_ANDLW, popGetLit (mask));
7622 emitpcode(POC_IORFW, temp);
7623 movwf (AOP(result), 0);
7629 emitPtrByteGet (result, p_type, FALSE);
7630 emitpcode(POC_ANDLW, popGetLit (mask));
7631 emitpcode(POC_IORFW, temp);
7632 emitPtrByteSet (result, p_type, TRUE);
7636 assert( !"trying to assign to bitfield via pointer to __code space" );
7640 assert( !"unhandled pointer type" );
7644 popReleaseTempReg (temp);
7646 } // if (AOP(right)->type != AOP_LIT)
7648 } // if (blen <= 8 && ((blen + bstr) <= 8))
7650 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
7653 /*-----------------------------------------------------------------*/
7654 /* genDataPointerSet - remat pointer to data space */
7655 /*-----------------------------------------------------------------*/
7656 static void genDataPointerSet(operand *right,
7660 int size, offset = 0 ;
7664 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7665 aopOp(right,ic,FALSE);
7666 aopOp(result,ic,FALSE);
7668 assert (IS_SYMOP(result));
7669 assert (IS_PTR(OP_SYM_TYPE(result)));
7671 if (AOP_TYPE(right) == AOP_LIT)
7674 size = AOP_SIZE(right);
7675 ressize = getSize(OP_SYM_ETYPE(result));
7676 if (size > ressize) size = ressize;
7677 //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
7679 //assert( !"what's going on here?" );
7682 if ( AOP_TYPE(result) == AOP_PCODE) {
7683 fprintf(stderr,"genDataPointerSet %s, %d\n",
7684 AOP(result)->aopu.pcop->name,
7685 PCOI(AOP(result)->aopu.pcop)->offset);
7689 // tsd, was l+1 - the underline `_' prefix was being stripped
7691 emitpComment ("%s:%u: size=%d/%d, offset=%d, AOP_TYPE(res)=%d", __FILE__,__LINE__, size, ressize, offset, AOP_TYPE(result));
7693 if (AOP_TYPE(right) == AOP_LIT) {
7694 unsigned int lit = pic14aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
7695 //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
7697 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
7698 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
7700 emitpcode(POC_CLRF, popGet(AOP(result), offset));
7703 //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
7704 emitpcode(POC_MOVFW, popGet(AOP(right), offset));
7705 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
7711 freeAsmop(right,NULL,ic,TRUE);
7712 freeAsmop(result,NULL,ic,TRUE);
7715 /*-----------------------------------------------------------------*/
7716 /* genNearPointerSet - pic14_emitcode for near pointer put */
7717 /*-----------------------------------------------------------------*/
7718 static void genNearPointerSet (operand *right,
7723 sym_link *ptype = operandType(result);
7724 sym_link *retype = getSpec(operandType(right));
7725 sym_link *letype = getSpec(ptype);
7730 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7731 aopOp(result,ic,FALSE);
7734 /* if the result is rematerializable &
7735 in data space & not a bit variable */
7736 //if (AOP_TYPE(result) == AOP_IMMD &&
7737 if (AOP_TYPE(result) == AOP_PCODE &&
7738 PIC_IS_DATA_PTR(ptype) &&
7739 !IS_BITVAR (retype) &&
7740 !IS_BITVAR (letype)) {
7741 genDataPointerSet (right,result,ic);
7742 freeAsmop(result,NULL,ic,TRUE);
7747 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7748 aopOp(right,ic,FALSE);
7749 DEBUGpic14_AopType(__LINE__,NULL,right,result);
7751 /* Check if can access directly instead of via a pointer */
7752 if ((AOP_TYPE(result) == AOP_PCODE)
7753 && (AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
7754 && (AOP_SIZE(right) == 1))
7759 if (IS_BITFIELD (letype))
7761 genPackBits (letype, result, right, direct?-1:POINTER);
7765 /* If the pointer value is not in a the FSR then need to put it in */
7766 /* Must set/reset IRP bit for use with FSR. */
7767 /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
7772 /* we have can just get the values */
7773 int size = AOP_SIZE(right);
7776 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7778 char *l = aopGet(AOP(right),offset,FALSE,TRUE);
7780 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
7782 if (AOP_TYPE(right) == AOP_LIT) {
7783 emitpcode(POC_MOVLW,popGet(AOP(right),offset));
7785 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
7788 emitpcode(POC_MOVWF,popGet(AOP(result),0));
7790 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
7792 if (size && !direct)
7793 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
7798 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7799 /* now some housekeeping stuff */
7801 /* we had to allocate for this iCode */
7802 freeAsmop(NULL,aop,ic,TRUE);
7804 /* we did not allocate which means left
7805 already in a pointer register, then
7806 if size > 0 && this could be used again
7807 we have to point it back to where it
7809 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7810 if (AOP_SIZE(right) > 1 &&
7811 !OP_SYMBOL(result)->remat &&
7812 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7814 int size = AOP_SIZE(right) - 1;
7816 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
7820 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7823 freeAsmop(right,NULL,ic,TRUE);
7824 freeAsmop(result,NULL,ic,TRUE);
7827 /*-----------------------------------------------------------------*/
7828 /* genGenPointerSet - set value from generic pointer space */
7829 /*-----------------------------------------------------------------*/
7830 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
7832 sym_link *retype = getSpec(operandType(result));
7835 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7836 aopOp(right,ic,FALSE);
7837 aopOp(result,ic,FALSE);
7840 DEBUGpic14_AopType(__LINE__,right,NULL,result);
7842 if (IS_BITFIELD(retype))
7844 genPackBits (retype, result, right, GPOINTER);
7849 /* emit call to __gptrput */
7850 char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
7851 int size = AOP_SIZE(right);
7854 /* The following assertion fails for
7855 * struct foo { char a; char b; } bar;
7856 * void demo(struct foo *dst, char c) { dst->b = c; }
7857 * as size will be 1 (sizeof(c)), whereas dst->b will be accessed
7858 * using (((char *)dst)+1), whose OP_SYM_ETYPE still is struct foo
7860 * The frontend seems to guarantee that IC_LEFT has the correct size,
7861 * it works fine both for larger and smaller types of `char c'.
7863 //assert (size == getSize(OP_SYM_ETYPE(result)));
7864 assert (size > 0 && size <= 4);
7866 /* pass arguments */
7867 /* - value (MSB in Gstack_base_addr-2, growing downwards) */
7873 mov2w_op (right, off);
7874 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
7879 assert (AOP_SIZE(result) == 3);
7880 mov2w(AOP(result), 0);
7881 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
7882 mov2w(AOP(result), 1);
7883 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
7884 mov2w(AOP(result), 2);
7885 call_libraryfunc (func[size]);
7888 freeAsmop(right,NULL,ic,TRUE);
7889 freeAsmop(result,NULL,ic,TRUE);
7892 /*-----------------------------------------------------------------*/
7893 /* genPointerSet - stores the value into a pointer location */
7894 /*-----------------------------------------------------------------*/
7895 static void genPointerSet (iCode *ic)
7897 operand *right, *result ;
7898 sym_link *type, *etype;
7902 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7904 right = IC_RIGHT(ic);
7905 result = IC_RESULT(ic) ;
7907 /* depending on the type of pointer we need to
7908 move it to the correct pointer register */
7909 type = operandType(result);
7910 etype = getSpec(type);
7911 /* if left is of type of pointer then it is simple */
7912 if (IS_PTR(type) && !IS_FUNC(type->next)) {
7913 p_type = DCL_TYPE(type);
7916 /* we have to go by the storage class */
7917 p_type = PTR_TYPE(SPEC_OCLS(etype));
7919 /* if (SPEC_OCLS(etype)->codesp ) { */
7920 /* p_type = CPOINTER ; */
7923 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7924 /* p_type = FPOINTER ; */
7926 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7927 /* p_type = PPOINTER ; */
7929 /* if (SPEC_OCLS(etype) == idata ) */
7930 /* p_type = IPOINTER ; */
7932 /* p_type = POINTER ; */
7935 /* now that we have the pointer type we assign
7936 the pointer values */
7942 genNearPointerSet (right,result,ic);
7946 genPagedPointerSet (right,result,ic);
7950 genFarPointerSet (right,result,ic);
7954 genGenPointerSet (right,result,ic);
7958 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7959 "genPointerSet: illegal pointer type");
7963 /*-----------------------------------------------------------------*/
7964 /* genIfx - generate code for Ifx statement */
7965 /*-----------------------------------------------------------------*/
7966 static void genIfx (iCode *ic, iCode *popIc)
7968 operand *cond = IC_COND(ic);
7972 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7974 aopOp(cond,ic,FALSE);
7976 /* get the value into acc */
7977 if (AOP_TYPE(cond) != AOP_CRY)
7978 pic14_toBoolean(cond);
7982 /* if there was something to be popped then do it */
7988 /* This assumes that CARRY is set iff cond is true */
7991 assert (!IC_FALSE(ic));
7992 emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
7994 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
7996 assert (IC_FALSE(ic));
7997 emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
7999 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
8003 static int hasWarned = 0;
8006 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
8013 /* now Z is set iff !cond */
8016 assert (!IC_FALSE(ic));
8018 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
8021 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
8027 /* the result is now in the accumulator */
8028 freeAsmop(cond,NULL,ic,TRUE);
8031 /*-----------------------------------------------------------------*/
8032 /* genAddrOf - generates code for address of */
8033 /*-----------------------------------------------------------------*/
8034 static void genAddrOf (iCode *ic)
8036 operand *right, *result, *left;
8040 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8043 //aopOp(IC_RESULT(ic),ic,FALSE);
8045 aopOp((left=IC_LEFT(ic)),ic,FALSE);
8046 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
8047 aopOp((result=IC_RESULT(ic)),ic,TRUE);
8049 DEBUGpic14_AopType(__LINE__,left,right,result);
8050 assert (IS_SYMOP (left));
8052 /* sanity check: generic pointers to code space are not yet supported,
8053 * pionters to codespace must not be assigned addresses of __data values. */
8055 fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
8056 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)));
8057 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)));
8058 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)));
8059 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)));
8062 if (IS_SYMOP(result) && IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
8063 fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
8064 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
8065 OP_SYMBOL(left)->name);
8066 } else if (IS_SYMOP(result) && !IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
8067 fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
8068 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
8069 OP_SYMBOL(left)->name);
8072 size = AOP_SIZE(IC_RESULT(ic));
8073 if (IS_SYMOP(result) && IS_GENPTR(OP_SYM_TYPE(result))) {
8075 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
8080 /* fixing bug #863624, reported from (errolv) */
8081 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
8082 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
8085 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
8086 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8091 if (IS_SYMOP(result) && IS_GENPTR(OP_SYM_TYPE(result)))
8093 /* provide correct tag */
8094 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
8095 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
8096 movwf (AOP(result), 2);
8099 freeAsmop(left,NULL,ic,FALSE);
8100 freeAsmop(result,NULL,ic,TRUE);
8105 /*-----------------------------------------------------------------*/
8106 /* genFarFarAssign - assignment when both are in far space */
8107 /*-----------------------------------------------------------------*/
8108 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
8110 int size = AOP_SIZE(right);
8113 /* first push the right side on to the stack */
8115 l = aopGet(AOP(right),offset++,FALSE,FALSE);
8117 pic14_emitcode ("push","acc");
8120 freeAsmop(right,NULL,ic,FALSE);
8121 /* now assign DPTR to result */
8122 aopOp(result,ic,FALSE);
8123 size = AOP_SIZE(result);
8125 pic14_emitcode ("pop","acc");
8126 aopPut(AOP(result),"a",--offset);
8128 freeAsmop(result,NULL,ic,FALSE);
8133 /*-----------------------------------------------------------------*/
8134 /* genAssign - generate code for assignment */
8135 /*-----------------------------------------------------------------*/
8136 static void genAssign (iCode *ic)
8138 operand *result, *right;
8139 int size, offset,know_W;
8140 unsigned long lit = 0L;
8142 result = IC_RESULT(ic);
8143 right = IC_RIGHT(ic) ;
8146 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8148 /* if they are the same */
8149 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
8152 aopOp(right,ic,FALSE);
8153 aopOp(result,ic,TRUE);
8155 DEBUGpic14_AopType(__LINE__,NULL,right,result);
8157 /* if they are the same registers */
8158 if (pic14_sameRegs(AOP(right),AOP(result)))
8161 /* special case: assign from __code */
8162 if (!IS_ITEMP(right) /* --> iTemps never reside in __code */
8163 && IS_SYMOP (right) /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
8164 && !IS_FUNC(OP_SYM_TYPE(right)) /* --> we would want its address instead of the first instruction */
8165 && !IS_CODEPTR(OP_SYM_TYPE(right)) /* --> get symbols address instread */
8166 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
8168 emitpComment ("genAssign from CODESPACE");
8169 genConstPointerGet (right, result, ic);
8173 /* just for symmetry reasons... */
8174 if (!IS_ITEMP(result)
8175 && IS_SYMOP (result)
8176 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
8178 assert ( !"cannot write to CODESPACE" );
8181 /* if the result is a bit */
8182 if (AOP_TYPE(result) == AOP_CRY) {
8184 /* if the right size is a literal then
8185 we know what the value is */
8186 if (AOP_TYPE(right) == AOP_LIT) {
8188 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
8189 popGet(AOP(result),0));
8191 if (((int) operandLitValue(right)))
8192 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
8193 AOP(result)->aopu.aop_dir,
8194 AOP(result)->aopu.aop_dir);
8196 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
8197 AOP(result)->aopu.aop_dir,
8198 AOP(result)->aopu.aop_dir);
8202 /* the right is also a bit variable */
8203 if (AOP_TYPE(right) == AOP_CRY) {
8204 emitpcode(POC_BCF, popGet(AOP(result),0));
8205 emitpcode(POC_BTFSC, popGet(AOP(right),0));
8206 emitpcode(POC_BSF, popGet(AOP(result),0));
8208 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
8209 AOP(result)->aopu.aop_dir,
8210 AOP(result)->aopu.aop_dir);
8211 pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
8212 AOP(right)->aopu.aop_dir,
8213 AOP(right)->aopu.aop_dir);
8214 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
8215 AOP(result)->aopu.aop_dir,
8216 AOP(result)->aopu.aop_dir);
8221 emitpcode(POC_BCF, popGet(AOP(result),0));
8222 pic14_toBoolean(right);
8224 emitpcode(POC_BSF, popGet(AOP(result),0));
8225 //aopPut(AOP(result),"a",0);
8229 /* bit variables done */
8231 size = AOP_SIZE(result);
8233 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
8234 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8235 if(aopIdx(AOP(result),0) == 4) {
8236 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8237 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8238 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8241 DEBUGpic14_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
8247 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8248 if(AOP_TYPE(right) == AOP_LIT) {
8249 lit = (unsigned long)pic14aopLiteral(AOP(right)->aopu.aop_lit, offset) & 0x0ff;
8251 if(know_W != (int)(lit&0xff))
8252 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
8254 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8256 emitpcode(POC_CLRF, popGet(AOP(result),offset));
8258 } else if (AOP_TYPE(right) == AOP_CRY) {
8259 emitpcode(POC_CLRF, popGet(AOP(result),offset));
8261 emitpcode(POC_BTFSS, popGet(AOP(right),0));
8262 emitpcode(POC_INCF, popGet(AOP(result),0));
8265 mov2w_op (right, offset);
8266 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8274 freeAsmop (right,NULL,ic,FALSE);
8275 freeAsmop (result,NULL,ic,TRUE);
8278 /*-----------------------------------------------------------------*/
8279 /* genJumpTab - genrates code for jump table */
8280 /*-----------------------------------------------------------------*/
8281 static void genJumpTab (iCode *ic)
8287 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8289 aopOp(IC_JTCOND(ic),ic,FALSE);
8290 /* get the condition into accumulator */
8291 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
8293 /* multiply by three */
8294 pic14_emitcode("add","a,acc");
8295 pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
8297 jtab = newiTempLabel(NULL);
8298 pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
8299 pic14_emitcode("jmp","@a+dptr");
8300 pic14_emitcode("","%05d_DS_:",jtab->key+100);
8302 emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
8303 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
8304 emitpcode(POC_MOVLW, popGetLabel(jtab->key));
8305 emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
8307 emitpcode(POC_INCF, popCopyReg(&pc_pclath));
8308 emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
8309 emitpLabel(jtab->key);
8311 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
8313 /* now generate the jump labels */
8314 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
8315 jtab = setNextItem(IC_JTLABELS(ic))) {
8316 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
8317 emitpcode(POC_GOTO,popGetLabel(jtab->key));
8323 /*-----------------------------------------------------------------*/
8324 /* genMixedOperation - gen code for operators between mixed types */
8325 /*-----------------------------------------------------------------*/
8327 TSD - Written for the PIC port - but this unfortunately is buggy.
8328 This routine is good in that it is able to efficiently promote
8329 types to different (larger) sizes. Unfortunately, the temporary
8330 variables that are optimized out by this routine are sometimes
8331 used in other places. So until I know how to really parse the
8332 iCode tree, I'm going to not be using this routine :(.
8334 static int genMixedOperation (iCode *ic)
8338 operand *result = IC_RESULT(ic);
8339 sym_link *ctype = operandType(IC_LEFT(ic));
8340 operand *right = IC_RIGHT(ic);
8346 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
8348 pic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
8354 nextright = IC_RIGHT(nextic);
8355 nextleft = IC_LEFT(nextic);
8356 nextresult = IC_RESULT(nextic);
8358 aopOp(right,ic,FALSE);
8359 aopOp(result,ic,FALSE);
8360 aopOp(nextright, nextic, FALSE);
8361 aopOp(nextleft, nextic, FALSE);
8362 aopOp(nextresult, nextic, FALSE);
8364 if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
8370 pic14_emitcode(";remove right +","");
8372 } else if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
8378 pic14_emitcode(";remove left +","");
8382 big = AOP_SIZE(nextleft);
8383 small = AOP_SIZE(nextright);
8385 switch(nextic->op) {
8388 pic14_emitcode(";optimize a +","");
8389 /* if unsigned or not an integral type */
8390 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
8391 pic14_emitcode(";add a bit to something","");
8394 pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
8396 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
8397 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
8398 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
8400 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
8408 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8409 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8410 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8413 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8415 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
8416 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
8417 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
8418 pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8419 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
8422 pic14_emitcode("rlf","known_zero,w");
8429 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8430 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8431 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8433 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8443 freeAsmop(right,NULL,ic,TRUE);
8444 freeAsmop(result,NULL,ic,TRUE);
8445 freeAsmop(nextright,NULL,ic,TRUE);
8446 freeAsmop(nextleft,NULL,ic,TRUE);
8448 nextic->generated = 1;
8455 /*-----------------------------------------------------------------*/
8456 /* genCast - gen code for casting */
8457 /*-----------------------------------------------------------------*/
8458 static void genCast (iCode *ic)
8460 operand *result = IC_RESULT(ic);
8461 sym_link *restype = operandType(result);
8462 sym_link *rtype = operandType(IC_RIGHT(ic));
8463 operand *right = IC_RIGHT(ic);
8467 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
8468 /* if they are equivalent then do nothing */
8469 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
8472 aopOp(right,ic,FALSE) ;
8473 aopOp(result,ic,FALSE);
8475 DEBUGpic14_AopType(__LINE__,NULL,right,result);
8477 /* if the result is a bit */
8478 if (AOP_TYPE(result) == AOP_CRY) {
8479 assert(!"assigning to bit variables is not supported");
8482 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
8484 size = AOP_SIZE(result);
8486 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
8488 emitpcode(POC_CLRF, popGet(AOP(result),0));
8489 emitpcode(POC_BTFSC, popGet(AOP(right),0));
8490 emitpcode(POC_INCF, popGet(AOP(result),0));
8493 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
8498 if (IS_PTR(restype))
8500 operand *result = IC_RESULT(ic);
8501 //operand *left = IC_LEFT(ic);
8502 operand *right = IC_RIGHT(ic);
8505 /* copy common part */
8506 int max, size = AOP_SIZE(result);
8507 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
8508 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
8510 /* warn if we discard generic opinter tag */
8511 if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
8513 //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
8519 mov2w_op (right, size);
8520 movwf (AOP(result), size);
8523 /* upcast into generic pointer type? */
8524 if (IS_GENPTR(restype)
8525 && (size < AOP_SIZE(result))
8526 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
8528 //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
8531 switch (DCL_TYPE(rtype))
8533 case POINTER: /* __data */
8534 case FPOINTER: /* __data */
8535 assert (AOP_SIZE(right) == 2);
8539 case CPOINTER: /* __code */
8540 assert (AOP_SIZE(right) == 2);
8544 case GPOINTER: /* unknown destination, __data or __code */
8545 /* assume __data space (address of immediate) */
8546 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
8547 if (AOP(right)->code)
8554 assert (!"unhandled pointer type");
8557 /* convert other values into pointers to __data space */
8561 assert (AOP_SIZE(result) == 3);
8563 emitpcode(POC_CLRF, popGet(AOP(result), 2));
8565 emitpcode(POC_MOVLW, popGetLit(tag));
8566 movwf(AOP(result), 2);
8569 addSign(result, max, 0);
8574 /* if they are the same size : or less */
8575 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8577 /* if they are in the same place */
8578 if (pic14_sameRegs(AOP(right),AOP(result)))
8581 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
8582 if (IS_PTR_CONST(rtype))
8583 DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
8584 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
8585 DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
8587 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
8588 emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
8589 emitpcode(POC_MOVWF, popGet(AOP(result),0));
8590 emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
8591 emitpcode(POC_MOVWF, popGet(AOP(result),1));
8592 if(AOP_SIZE(result) <2)
8593 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
8597 /* if they in different places then copy */
8598 size = AOP_SIZE(result);
8601 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8602 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8604 //aopPut(AOP(result),
8605 // aopGet(AOP(right),offset,FALSE,FALSE),
8614 /* so we now know that the size of destination is greater
8615 than the size of the source.
8616 Now, if the next iCode is an operator then we might be
8617 able to optimize the operation without performing a cast.
8619 if(0 && genMixedOperation(ic)) {
8620 /* XXX: cannot optimize: must copy regs! */
8624 /* we move to result for the size of source */
8625 size = AOP_SIZE(right);
8628 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8629 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8633 addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
8636 freeAsmop(right,NULL,ic,TRUE);
8637 freeAsmop(result,NULL,ic,TRUE);
8641 /*-----------------------------------------------------------------*/
8642 /* genDjnz - generate decrement & jump if not zero instrucion */
8643 /*-----------------------------------------------------------------*/
8644 static int genDjnz (iCode *ic, iCode *ifx)
8648 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8653 /* if the if condition has a false label
8654 then we cannot save */
8658 /* if the minus is not of the form
8660 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8661 !IS_OP_LITERAL(IC_RIGHT(ic)))
8664 if (operandLitValue(IC_RIGHT(ic)) != 1)
8667 /* if the size of this greater than one then no
8669 if (getSize(operandType(IC_RESULT(ic))) > 1)
8672 /* otherwise we can save BIG */
8673 lbl = newiTempLabel(NULL);
8674 lbl1= newiTempLabel(NULL);
8676 aopOp(IC_RESULT(ic),ic,FALSE);
8678 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
8679 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
8681 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8686 /*-----------------------------------------------------------------*/
8687 /* genReceive - generate code for a receive iCode */
8688 /*-----------------------------------------------------------------*/
8689 static void genReceive (iCode *ic)
8692 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8694 if (isOperandInFarSpace(IC_RESULT(ic)) &&
8695 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8696 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8698 int size = getSize(operandType(IC_RESULT(ic)));
8699 int offset = fReturnSizePic - size;
8701 pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
8702 fReturn[fReturnSizePic - offset - 1] : "acc"));
8705 aopOp(IC_RESULT(ic),ic,FALSE);
8706 size = AOP_SIZE(IC_RESULT(ic));
8709 pic14_emitcode ("pop","acc");
8710 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8715 aopOp(IC_RESULT(ic),ic,FALSE);
8717 GpsuedoStkPtr = ic->parmBytes; // address used arg on stack
8718 assignResultValue(IC_RESULT(ic));
8721 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8724 /*-----------------------------------------------------------------*/
8725 /* genDummyRead - generate code for dummy read of volatiles */
8726 /*-----------------------------------------------------------------*/
8728 genDummyRead (iCode * ic)
8731 pic14_emitcode ("; genDummyRead","");
8732 pic14_emitcode ("; not implemented","");
8737 /*-----------------------------------------------------------------*/
8738 /* genpic14Code - generate code for pic14 based controllers */
8739 /*-----------------------------------------------------------------*/
8741 * At this point, ralloc.c has gone through the iCode and attempted
8742 * to optimize in a way suitable for a PIC. Now we've got to generate
8743 * PIC instructions that correspond to the iCode.
8745 * Once the instructions are generated, we'll pass through both the
8746 * peep hole optimizer and the pCode optimizer.
8747 *-----------------------------------------------------------------*/
8749 void genpic14Code (iCode *lic)
8756 lineHead = lineCurr = NULL;
8758 pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
8761 /* if debug information required */
8762 if (options.debug && debugFile && currFunc) {
8763 debugFile->writeFunction (currFunc, lic);
8767 for (ic = lic ; ic ; ic = ic->next ) {
8769 //DEBUGpic14_emitcode(";ic","");
8770 //fprintf (stderr, "in ic loop\n");
8771 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
8772 //ic->lineno, printCLine(ic->filename, ic->lineno));
8774 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
8776 //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
8777 cline = printCLine (ic->filename, ic->lineno);
8778 if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
8779 addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
8780 //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
8783 if (options.iCodeInAsm) {
8784 const char *iLine = printILine(ic);
8785 emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
8788 /* if the result is marked as
8789 spilt and rematerializable or code for
8790 this has already been generated then
8792 if (resultRemat(ic) || ic->generated )
8795 /* depending on the operation */
8814 /* IPOP happens only when trying to restore a
8815 spilt live range, if there is an ifx statement
8816 following this pop then the if statement might
8817 be using some of the registers being popped which
8818 would destory the contents of the register so
8819 we need to check for this condition and handle it */
8821 ic->next->op == IFX &&
8822 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
8823 genIfx (ic->next,ic);
8841 genEndFunction (ic);
8861 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8878 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
8882 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8889 /* note these two are xlated by algebraic equivalence
8890 during parsing SDCC.y */
8891 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8892 "got '>=' or '<=' shouldn't have come here");
8896 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8908 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8912 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8916 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8943 case GET_VALUE_AT_ADDRESS:
8948 if (POINTER_SET(ic))
8975 addSet(&_G.sendSet,ic);
8978 case DUMMY_READ_VOLATILE:
8983 fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
8990 /* now we are ready to call the
8991 peep hole optimizer */
8992 if (!options.nopeep) {
8993 peepHole (&lineHead);
8995 /* now do the actual printing */
8996 printLine (lineHead,codeOutBuf);
8999 DFPRINTF((stderr,"printing pBlock\n\n"));
9000 printpBlock(stdout,pb);
9006 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
9007 * (meaning: representing its own address) or not (referencing its contents).
9008 * This can only be decided based on the operand's type. */
9010 aop_isLitLike (asmop *aop)
9013 if (aop->type == AOP_LIT) return 1;
9014 if (aop->type == AOP_IMMD) return 1;
9015 if ((aop->type == AOP_PCODE) &&
9016 ((aop->aopu.pcop->type == PO_LITERAL)))
9018 /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
9019 * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
9026 op_isLitLike (operand *op)
9029 if (aop_isLitLike (AOP(op))) return 1;
9030 if (IS_SYMOP(op) && IS_FUNC(OP_SYM_TYPE(op))) return 1;
9031 if (IS_SYMOP(op) && IS_PTR(OP_SYM_TYPE(op))
9032 && (AOP_TYPE(op) == AOP_PCODE)
9033 && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {