1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for pic
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 PIC port - Scott Dattalo scott@dattalo.com (2000)
8 cont'd - Raphael Neider <rneider AT web.de> (2005)
10 This program is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the
12 Free Software Foundation; either version 2, or (at your option) any
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 In other words, you are welcome to use, share and improve this program.
25 You are forbidden to forbid anyone else to use, share and improve
26 what you give them. Help stamp out software-hoarding!
29 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
30 Made everything static
31 -------------------------------------------------------------------------*/
37 #include "SDCCglobl.h"
41 #include "SDCCpeeph.h"
47 /* The PIC port(s) need not differentiate between POINTER and FPOINTER. */
48 #define PIC_IS_DATA_PTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
49 #define PIC_IS_FARPTR(x) (PIC_IS_DATA_PTR(x))
51 extern void printpBlock(FILE *of, pBlock *pb);
53 static int labelOffset=0;
54 extern int debug_verbose;
55 extern int pic14_hasInterrupt;
56 //static int optimized_for_speed = 0;
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.
63 static int GpsuedoStkPtr=0;
64 static int pic14_inISR = 0;
66 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
67 extern char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
68 const char *AopType(short type);
70 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0x00ff)
72 /* this is the down and dirty file with all kinds of
73 kludgy & hacky stuff. This is what it is all about
74 CODE GENERATION for a specific MCU . some of the
75 routines may be reusable, will have to see */
77 static char *zero = "0x00";
78 static char *one = "0x01";
79 static char *spname = "sp";
81 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
82 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
83 static char **fReturn = fReturnpic14;
93 /* Resolved ifx structure. This structure stores information
94 about an iCode ifx that makes it easier to generate code.
96 typedef struct resolvedIfx {
97 symbol *lbl; /* pointer to a label */
98 int condition; /* true or false ifx */
99 int generated; /* set true when the code associated with the ifx
103 extern int pic14_nRegs;
104 extern struct dbuf_s *codeOutBuf;
105 static void saverbank (int, iCode *,bool);
107 static lineNode *lineHead = NULL;
108 static lineNode *lineCurr = NULL;
112 /*-----------------------------------------------------------------*/
113 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
114 /* exponent of 2 is returned, otherwise -1 is */
116 /* note that this is similar to the function `powof2' in SDCCsymt */
120 /*-----------------------------------------------------------------*/
121 static int my_powof2 (unsigned long num)
124 if( (num & (num-1)) == 0) {
137 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
140 DEBUGpic14_emitcode ("; ","line = %d result %s=%s, size=%d, left %s=%s, size=%d, right %s=%s, size=%d",
142 ((result) ? AopType(AOP_TYPE(result)) : "-"),
143 ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
144 ((result) ? AOP_SIZE(result) : 0),
145 ((left) ? AopType(AOP_TYPE(left)) : "-"),
146 ((left) ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
147 ((left) ? AOP_SIZE(left) : 0),
148 ((right) ? AopType(AOP_TYPE(right)) : "-"),
149 ((right) ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
150 ((right) ? AOP_SIZE(right) : 0));
154 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
157 DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
159 ((result) ? AopType(AOP_TYPE(result)) : "-"),
160 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
161 ((left) ? AopType(AOP_TYPE(left)) : "-"),
162 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
163 ((right) ? AopType(AOP_TYPE(right)) : "-"),
164 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
168 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
171 char lb[INITIAL_INLINEASM];
172 unsigned char *lbp = (unsigned char *)lb;
174 if(!debug_verbose && !options.debug)
181 sprintf(lb,"%s\t",inst);
183 sprintf(lb,"%s",inst);
184 vsprintf(lb+(strlen(lb)),fmt,ap);
188 while (isspace(*lbp)) lbp++;
191 lineCurr = (lineCurr ?
192 connectLine(lineCurr,newLineNode(lb)) :
193 (lineHead = newLineNode(lb)));
194 lineCurr->isInline = _G.inLine;
195 lineCurr->isDebug = _G.debugLine;
197 addpCode2pBlock(pb,newpCodeCharP(lb));
202 static void Safe_vsnprintf (char *buf, size_t size, const char *fmt, va_list ap)
204 #if defined (HAVE_VSNPRINTF)
205 vsnprintf (buf, size, fmt, ap);
206 #elif defined (HAVE_VSPRINTF)
207 vsprintf (buf, size, fmt, ap);
208 if (strlen (buf) >= size)
210 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
212 #elif defined (HAVE_SNPRINTF)
213 snprintf (buf, size, "vs(n)printf required");
214 #elif defined (HAVE_SRINTF)
215 sprintf (buf, "vs(n)printf required");
216 if (strlen (buf) >= size)
218 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
221 assert ( !"neither vsnprintf nor vsprintf is present -- unable to proceed" );
225 void emitpComment (const char *fmt, ...)
232 Safe_vsnprintf (buffer, 4096, fmt, va);
233 //fprintf (stderr, "%s\n" ,buffer);
234 addpCode2pBlock (pb, newpCodeCharP (buffer));
237 Safe_vsnprintf (buffer, 4096, fmt, va);
238 fprintf (stderr, "No current pBlock -- discarding comment [%s]\n", buffer);
244 void emitpLabel(int key)
246 addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
249 /* gen.h defines a macro emitpcode that should be used to call emitpcode
250 * as this allows for easy debugging (ever asked the question: where was
251 * this instruction geenrated? Here is the answer... */
252 void emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
255 addpCode2pBlock(pb,newpCode(poc,pcop));
257 static int has_warned = 0;
259 DEBUGpic14_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
262 fprintf( stderr, "WARNING: encountered NULL pcop--this is probably a compiler bug...\n" );
267 void emitpcodeNULLop(PIC_OPCODE poc)
270 addpCode2pBlock(pb,newpCode(poc,NULL));
275 /*-----------------------------------------------------------------*/
276 /* pic14_emitcode - writes the code into a file : for now it is simple */
277 /*-----------------------------------------------------------------*/
278 void pic14_emitcode (char *inst,char *fmt, ...)
281 char lb[INITIAL_INLINEASM];
288 sprintf(lb,"%s\t",inst);
290 sprintf(lb,"%s",inst);
291 vsprintf(lb+(strlen(lb)),fmt,ap);
295 while (isspace(*lbp)) lbp++;
298 lineCurr = (lineCurr ?
299 connectLine(lineCurr,newLineNode(lb)) :
300 (lineHead = newLineNode(lb)));
301 lineCurr->isInline = _G.inLine;
302 lineCurr->isDebug = _G.debugLine;
303 lineCurr->isLabel = (lbp[strlen (lbp) - 1] == ':');
306 addpCode2pBlock(pb,newpCodeCharP(lb));
311 /*-----------------------------------------------------------------*/
312 /* pic14_emitDebuggerSymbol - associate the current code location */
313 /* with a debugger symbol */
314 /*-----------------------------------------------------------------*/
316 pic14_emitDebuggerSymbol (char * debugSym)
319 pic14_emitcode ("", ";%s ==.", debugSym);
323 /*-----------------------------------------------------------------*/
324 /* newAsmop - creates a new asmOp */
325 /*-----------------------------------------------------------------*/
326 asmop *newAsmop (short type)
330 aop = Safe_calloc(1,sizeof(asmop));
335 /*-----------------------------------------------------------------*/
336 /* resolveIfx - converts an iCode ifx into a form more useful for */
337 /* generating code */
338 /*-----------------------------------------------------------------*/
339 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
344 // DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
346 resIfx->condition = 1; /* assume that the ifx is true */
347 resIfx->generated = 0; /* indicate that the ifx has not been used */
350 resIfx->lbl = NULL; /* this is wrong: newiTempLabel(NULL); / * oops, there is no ifx. so create a label */
352 DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
353 __FUNCTION__,__LINE__,resIfx->lbl->key);
357 resIfx->lbl = IC_TRUE(ifx);
359 resIfx->lbl = IC_FALSE(ifx);
360 resIfx->condition = 0;
364 DEBUGpic14_emitcode("; ***","ifx true is non-null");
366 DEBUGpic14_emitcode("; ***","ifx false is non-null");
370 // DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
373 /*-----------------------------------------------------------------*/
374 /* pointerCode - returns the code for a pointer type */
375 /*-----------------------------------------------------------------*/
377 static int pointerCode (sym_link *etype)
380 return PTR_TYPE(SPEC_OCLS(etype));
385 /*-----------------------------------------------------------------*/
386 /* aopForSym - for a true symbol */
387 /*-----------------------------------------------------------------*/
388 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
391 memmap *space= SPEC_OCLS(sym->etype);
393 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
394 /* if already has one */
398 //DEBUGpic14_emitcode(";","%d",__LINE__);
399 /* if it is in direct space */
400 if (IN_DIRSPACE(space)) {
401 sym->aop = aop = newAsmop (AOP_DIR);
402 aop->aopu.aop_dir = sym->rname ;
403 aop->size = getSize(sym->type);
404 DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
408 /* special case for a function */
409 if (IS_FUNC(sym->type)) {
411 sym->aop = aop = newAsmop(AOP_PCODE);
412 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
413 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
414 PCOI(aop->aopu.pcop)->_function = 1;
415 PCOI(aop->aopu.pcop)->index = 0;
416 aop->size = FPTRSIZE;
418 sym->aop = aop = newAsmop(AOP_IMMD);
419 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
420 strcpy(aop->aopu.aop_immd,sym->rname);
421 aop->size = FPTRSIZE;
423 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
427 if (IS_ARRAY(sym->type)) {
428 sym->aop = aop = newAsmop(AOP_PCODE);
429 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
430 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
431 PCOI(aop->aopu.pcop)->_function = 0;
432 PCOI(aop->aopu.pcop)->index = 0;
433 aop->size = getSize(sym->etype) * DCL_ELEM(sym->type);
435 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
439 /* only remaining is far space */
440 /* in which case DPTR gets the address */
441 sym->aop = aop = newAsmop(AOP_PCODE);
443 aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
444 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
445 PCOI(aop->aopu.pcop)->index = 0;
447 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
448 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
450 allocDirReg (IC_LEFT(ic));
452 aop->size = FPTRSIZE;
454 /* if it is in code space */
455 if (IN_CODESPACE(space))
461 /*-----------------------------------------------------------------*/
462 /* aopForRemat - rematerialzes an object */
463 /*-----------------------------------------------------------------*/
464 static asmop *aopForRemat (operand *op) // x symbol *sym)
466 symbol *sym = OP_SYMBOL(op);
468 asmop *aop = newAsmop(AOP_PCODE);
472 ic = sym->rematiCode;
474 DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
475 if(IS_OP_POINTER(op)) {
476 DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
480 val += (int) operandLitValue(IC_RIGHT(ic));
481 } else if (ic->op == '-') {
482 val -= (int) operandLitValue(IC_RIGHT(ic));
486 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
489 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
490 aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
491 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
492 PCOI(aop->aopu.pcop)->index = val;
494 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
495 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
496 val, IS_PTR_CONST(operandType(op)));
498 // DEBUGpic14_emitcode(";","aop type %s",AopType(AOP_TYPE(IC_LEFT(ic))));
500 allocDirReg (IC_LEFT(ic));
505 int aopIdx (asmop *aop, int offset)
510 if(aop->type != AOP_REG)
513 return aop->aopu.aop_reg[offset]->rIdx;
516 /*-----------------------------------------------------------------*/
517 /* regsInCommon - two operands have some registers in common */
518 /*-----------------------------------------------------------------*/
519 static bool regsInCommon (operand *op1, operand *op2)
524 /* if they have registers in common */
525 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
528 sym1 = OP_SYMBOL(op1);
529 sym2 = OP_SYMBOL(op2);
531 if (sym1->nRegs == 0 || sym2->nRegs == 0)
534 for (i = 0 ; i < sym1->nRegs ; i++) {
539 for (j = 0 ; j < sym2->nRegs ;j++ ) {
543 if (sym2->regs[j] == sym1->regs[i])
551 /*-----------------------------------------------------------------*/
552 /* operandsEqu - equivalent */
553 /*-----------------------------------------------------------------*/
554 static bool operandsEqu ( operand *op1, operand *op2)
558 /* if they not symbols */
559 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
562 sym1 = OP_SYMBOL(op1);
563 sym2 = OP_SYMBOL(op2);
565 /* if both are itemps & one is spilt
566 and the other is not then false */
567 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
568 sym1->isspilt != sym2->isspilt )
571 /* if they are the same */
575 if (sym1->rname[0] && sym2->rname[0]
576 && strcmp (sym1->rname, sym2->rname) == 0)
580 /* if left is a tmp & right is not */
584 (sym1->usl.spillLoc == sym2))
591 (sym2->usl.spillLoc == sym1))
597 /*-----------------------------------------------------------------*/
598 /* pic14_sameRegs - two asmops have the same registers */
599 /*-----------------------------------------------------------------*/
600 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
607 if (aop1->type != AOP_REG ||
608 aop2->type != AOP_REG )
611 if (aop1->size != aop2->size )
614 for (i = 0 ; i < aop1->size ; i++ )
615 if (aop1->aopu.aop_reg[i] !=
616 aop2->aopu.aop_reg[i] )
622 /*-----------------------------------------------------------------*/
623 /* aopOp - allocates an asmop for an operand : */
624 /*-----------------------------------------------------------------*/
625 void aopOp (operand *op, iCode *ic, bool result)
634 /* if this a literal */
635 if (IS_OP_LITERAL(op)) {
636 op->aop = aop = newAsmop(AOP_LIT);
637 aop->aopu.aop_lit = op->operand.valOperand;
638 aop->size = getSize(operandType(op));
643 sym_link *type = operandType(op);
644 if(IS_PTR_CONST(type))
645 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
648 /* if already has a asmop then continue */
652 /* if the underlying symbol has a aop */
653 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
654 DEBUGpic14_emitcode(";","%d",__LINE__);
655 op->aop = OP_SYMBOL(op)->aop;
659 /* if this is a true symbol */
660 if (IS_TRUE_SYMOP(op)) {
661 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
662 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
666 /* this is a temporary : this has
672 e) can be a return use only */
677 /* if the type is a conditional */
678 if (sym->regType == REG_CND) {
679 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
684 /* if it is spilt then two situations
686 b) has a spill location */
687 if (sym->isspilt || sym->nRegs == 0) {
689 DEBUGpic14_emitcode(";","%d",__LINE__);
690 /* rematerialize it NOW */
693 sym->aop = op->aop = aop = aopForRemat (op);
694 aop->size = getSize(sym->type);
695 //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
700 if(sym->isptr) { // && sym->uptr
701 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
702 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
704 //PCOI(aop->aopu.pcop)->_const = 0;
705 //PCOI(aop->aopu.pcop)->index = 0;
707 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
708 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
710 //allocDirReg (IC_LEFT(ic));
712 aop->size = getSize(sym->type);
713 DEBUGpic14_emitcode(";","%d",__LINE__);
720 aop = op->aop = sym->aop = newAsmop(AOP_STR);
721 aop->size = getSize(sym->type);
722 for ( i = 0 ; i < fReturnSizePic ; i++ )
723 aop->aopu.aop_str[i] = fReturn[i];
725 DEBUGpic14_emitcode(";","%d",__LINE__);
730 /* else spill location */
731 if (sym->usl.spillLoc)
733 asmop *oldAsmOp = NULL;
735 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
737 /* force a new aop if sizes differ */
738 oldAsmOp = sym->usl.spillLoc->aop;
739 sym->usl.spillLoc->aop = NULL;
741 DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
742 __FUNCTION__,__LINE__,
743 sym->usl.spillLoc->rname,
744 sym->rname, sym->usl.spillLoc->offset);
746 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
747 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
749 /* Don't reuse the new aop, go with the last one */
750 sym->usl.spillLoc->aop = oldAsmOp;
752 //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
753 aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname,
755 sym->usl.spillLoc->offset);
756 aop->size = getSize(sym->type);
763 sym_link *type = operandType(op);
764 if(IS_PTR_CONST(type))
765 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
768 /* must be in a register */
769 DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
770 sym->aop = op->aop = aop = newAsmop(AOP_REG);
771 aop->size = sym->nRegs;
772 for ( i = 0 ; i < sym->nRegs ;i++)
773 aop->aopu.aop_reg[i] = sym->regs[i];
776 /*-----------------------------------------------------------------*/
777 /* freeAsmop - free up the asmop given to an operand */
778 /*----------------------------------------------------------------*/
779 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
793 /* all other cases just dealloc */
797 OP_SYMBOL(op)->aop = NULL;
798 /* if the symbol has a spill */
800 SPIL_LOC(op)->aop = NULL;
805 /*-----------------------------------------------------------------*/
806 /* aopGet - for fetching value of the aop */
807 /*-----------------------------------------------------------------*/
808 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
813 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
814 /* offset is greater than
817 if (offset > (aop->size - 1) &&
818 aop->type != AOP_LIT)
821 /* depending on type */
826 sprintf (s,"%s",aop->aopu.aop_immd);
829 sprintf(s,"(%s >> %d)",
835 DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
836 rs = Safe_calloc(1,strlen(s)+1);
842 sprintf(s,"(%s + %d)",
845 DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
847 sprintf(s,"%s",aop->aopu.aop_dir);
848 rs = Safe_calloc(1,strlen(s)+1);
854 // return aop->aopu.aop_reg[offset]->dname;
856 return aop->aopu.aop_reg[offset]->name;
859 //pic14_emitcode(";","%d",__LINE__);
860 return aop->aopu.aop_dir;
863 sprintf(s, "0x%02x", pic14aopLiteral (aop->aopu.aop_lit, offset));
869 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
872 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
874 return aop->aopu.aop_str[offset];
878 pCodeOp *pcop = aop->aopu.pcop;
879 DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
881 if (pcop->type == PO_IMMEDIATE) {
882 offset += PCOI(pcop)->index;
885 DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
886 sprintf(s,"(%s+%d)", pcop->name,offset);
888 DEBUGpic14_emitcode(";","%s",pcop->name);
889 sprintf(s,"%s", pcop->name);
892 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
895 rs = Safe_calloc(1,strlen(s)+1);
901 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
902 "aopget got unsupported aop->type");
907 /*-----------------------------------------------------------------*/
908 /* popGetTempReg - create a new temporary pCodeOp */
909 /*-----------------------------------------------------------------*/
910 pCodeOp *popGetTempReg(void)
915 pcop = newpCodeOp(NULL, PO_GPR_TEMP);
916 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
917 PCOR(pcop)->r->wasUsed=1;
918 PCOR(pcop)->r->isFree=0;
924 /*-----------------------------------------------------------------*/
925 /* popReleaseTempReg - create a new temporary pCodeOp */
926 /*-----------------------------------------------------------------*/
927 void popReleaseTempReg(pCodeOp *pcop)
930 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
931 PCOR(pcop)->r->isFree = 1;
934 /*-----------------------------------------------------------------*/
935 /* popGetLabel - create a new pCodeOp of type PO_LABEL */
936 /*-----------------------------------------------------------------*/
937 pCodeOp *popGetLabel(unsigned int key)
940 DEBUGpic14_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, labelOffset);
942 if(key>(unsigned int)max_key)
945 return newpCodeOpLabel(NULL,key+100+labelOffset);
948 /*-------------------------------------------------------------------*/
949 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
950 /*-------------------------------------------------------------------*/
951 pCodeOp *popGetHighLabel(unsigned int key)
954 pcop = popGetLabel(key);
955 PCOLAB(pcop)->offset = 1;
959 /*-----------------------------------------------------------------*/
960 /* popGetLit - asm operator to pcode operator conversion */
961 /*-----------------------------------------------------------------*/
962 pCodeOp *popGetLit(unsigned int lit)
965 return newpCodeOpLit((unsigned char)lit);
968 /*-----------------------------------------------------------------*/
969 /* popGetImmd - asm operator to pcode immediate conversion */
970 /*-----------------------------------------------------------------*/
971 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
974 return newpCodeOpImmd(name, offset,index, 0, is_func);
979 /*-----------------------------------------------------------------*/
980 /* popGetWithString - asm operator to pcode operator conversion */
981 /*-----------------------------------------------------------------*/
982 pCodeOp *popGetWithString(char *str, int isExtern)
988 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
992 pcop = newpCodeOp(str,PO_STR);
993 PCOS(pcop)->isPublic = isExtern ? 1 : 0;
998 pCodeOp *popGetExternal (char *str, int isReg)
1003 pcop = newpCodeOpRegFromStr(str);
1005 pcop = popGetWithString (str, 1);
1011 for (sym = setFirstItem (externs); sym; sym = setNextItem (externs))
1013 if (!strcmp (str, sym->rname)) break;
1018 sym = newSymbol(str, 0);
1019 strncpy(sym->rname, str, SDCC_NAME_MAX);
1020 addSet (&externs, sym);
1027 /*-----------------------------------------------------------------*/
1028 /* popRegFromString - */
1029 /*-----------------------------------------------------------------*/
1030 pCodeOp *popRegFromString(char *str, int size, int offset)
1033 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1034 pcop->type = PO_DIR;
1036 DEBUGpic14_emitcode(";","%d",__LINE__);
1041 pcop->name = Safe_calloc(1,strlen(str)+1);
1042 strcpy(pcop->name,str);
1044 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1046 PCOR(pcop)->r = dirregWithName(pcop->name);
1047 if(PCOR(pcop)->r == NULL) {
1048 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1049 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1050 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1052 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1054 PCOR(pcop)->instance = offset;
1059 /*-----------------------------------------------------------------*/
1060 /*-----------------------------------------------------------------*/
1061 pCodeOp *popRegFromIdx(int rIdx)
1065 DEBUGpic14_emitcode ("; ***","%s,%d , rIdx=0x%x",
1066 __FUNCTION__,__LINE__,rIdx);
1068 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1070 PCOR(pcop)->rIdx = rIdx;
1071 PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1072 PCOR(pcop)->r->isFree = 0;
1073 PCOR(pcop)->r->wasUsed = 1;
1075 pcop->type = PCOR(pcop)->r->pc_type;
1081 /*-----------------------------------------------------------------*/
1082 /* popGet - asm operator to pcode operator conversion */
1083 /*-----------------------------------------------------------------*/
1084 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1086 //char *s = buffer ;
1091 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1092 /* offset is greater than
1098 /* XXX: still needed for BIT operands (AOP_CRY) */
1099 if (offset > (aop->size - 1) &&
1100 aop->type != AOP_LIT &&
1101 aop->type != AOP_PCODE)
1103 printf( "%s: (offset[%d] > AOP_SIZE(op)[%d]-1) && AOP_TYPE(op) != AOP_LIT)\n", __FUNCTION__, offset, aop->size);
1104 return NULL; //zero;
1107 /* depending on type */
1108 switch (aop->type) {
1111 DEBUGpic14_emitcode(";","%d",__LINE__);
1112 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1115 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1117 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1118 pcop->type = PO_DIR;
1120 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1121 strcpy(pcop->name,aop->aopu.aop_dir);
1122 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1123 if(PCOR(pcop)->r == NULL) {
1124 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1125 PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1126 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1128 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1130 PCOR(pcop)->instance = offset;
1138 assert (offset < aop->size);
1139 rIdx = aop->aopu.aop_reg[offset]->rIdx;
1141 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1142 PCOR(pcop)->rIdx = rIdx;
1143 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1144 PCOR(pcop)->r->wasUsed=1;
1145 PCOR(pcop)->r->isFree=0;
1147 PCOR(pcop)->instance = offset;
1148 pcop->type = PCOR(pcop)->r->pc_type;
1149 //rs = aop->aopu.aop_reg[offset]->name;
1150 DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1155 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1156 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1157 //if(PCOR(pcop)->r == NULL)
1158 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1162 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1165 DEBUGpic14_emitcode(";","%d %s",__LINE__,aop->aopu.aop_str[offset]);
1166 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1168 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1169 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1170 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1171 pcop->type = PCOR(pcop)->r->pc_type;
1172 pcop->name = PCOR(pcop)->r->name;
1179 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1181 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1182 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1183 switch (aop->aopu.pcop->type)
1186 pcop = pCodeOpCopy (aop->aopu.pcop);
1187 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1188 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1189 PCOI(pcop)->index += offset;
1190 //PCOI(pcop)->offset = 0;
1193 pcop = pCodeOpCopy (aop->aopu.pcop);
1194 PCOR(pcop)->instance = offset;
1197 assert ( !"unhandled pCode type" );
1203 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1204 "popGet got unsupported aop->type");
1208 /*-----------------------------------------------------------------*/
1209 /* popGetAddr - access the low/high word of a symbol (immediate) */
1210 /* (for non-PO_IMMEDIATEs this is the same as popGet) */
1211 /*-----------------------------------------------------------------*/
1212 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1214 if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1216 pCodeOp *pcop = aop->aopu.pcop;
1217 assert (offset <= GPTRSIZE);
1219 /* special case: index >= 2 should return GPOINTER-style values */
1222 pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1226 pcop = pCodeOpCopy (pcop);
1227 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1228 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1229 PCOI(pcop)->offset += offset;
1230 PCOI(pcop)->index += index;
1231 //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);
1234 return popGet (aop, offset + index);
1238 /*-----------------------------------------------------------------*/
1239 /* aopPut - puts a string for a aop */
1240 /*-----------------------------------------------------------------*/
1241 void aopPut (asmop *aop, char *s, int offset)
1246 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1248 if (aop->size && offset > ( aop->size - 1)) {
1249 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1250 "aopPut got offset > aop->size");
1254 /* will assign value to value */
1255 /* depending on where it is ofcourse */
1256 switch (aop->type) {
1259 sprintf(d,"(%s + %d)",
1260 aop->aopu.aop_dir,offset);
1261 fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1264 sprintf(d,"%s",aop->aopu.aop_dir);
1267 DEBUGpic14_emitcode(";","%d",__LINE__);
1269 pic14_emitcode("movf","%s,w",s);
1270 pic14_emitcode("movwf","%s",d);
1273 pic14_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
1274 if(offset >= aop->size) {
1275 emitpcode(POC_CLRF,popGet(aop,offset));
1278 emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
1281 emitpcode(POC_MOVWF,popGet(aop,offset));
1287 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1288 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1291 strcmp(s,"r0") == 0 ||
1292 strcmp(s,"r1") == 0 ||
1293 strcmp(s,"r2") == 0 ||
1294 strcmp(s,"r3") == 0 ||
1295 strcmp(s,"r4") == 0 ||
1296 strcmp(s,"r5") == 0 ||
1297 strcmp(s,"r6") == 0 ||
1298 strcmp(s,"r7") == 0 )
1299 pic14_emitcode("mov","%s,%s ; %d",
1300 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1304 if(strcmp(s,"W")==0 )
1305 pic14_emitcode("movf","%s,w ; %d",s,__LINE__);
1307 pic14_emitcode("movwf","%s",
1308 aop->aopu.aop_reg[offset]->name);
1310 if(strcmp(s,zero)==0) {
1311 emitpcode(POC_CLRF,popGet(aop,offset));
1313 } else if(strcmp(s,"W")==0) {
1314 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1315 pcop->type = PO_GPR_REGISTER;
1317 PCOR(pcop)->rIdx = -1;
1318 PCOR(pcop)->r = NULL;
1320 DEBUGpic14_emitcode(";","%d",__LINE__);
1321 pcop->name = Safe_strdup(s);
1322 emitpcode(POC_MOVFW,pcop);
1323 emitpcode(POC_MOVWF,popGet(aop,offset));
1324 } else if(strcmp(s,one)==0) {
1325 emitpcode(POC_CLRF,popGet(aop,offset));
1326 emitpcode(POC_INCF,popGet(aop,offset));
1328 emitpcode(POC_MOVWF,popGet(aop,offset));
1334 if (strcmp(s,"a") == 0)
1335 pic14_emitcode("push","acc");
1337 pic14_emitcode("push","%s",s);
1342 /* if bit variable */
1343 if (!aop->aopu.aop_dir) {
1344 pic14_emitcode("clr","a");
1345 pic14_emitcode("rlc","a");
1348 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1351 pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1354 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1356 lbl = newiTempLabel(NULL);
1358 if (strcmp(s,"a")) {
1361 pic14_emitcode("clr","c");
1362 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1363 pic14_emitcode("cpl","c");
1364 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1365 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1372 if (strcmp(aop->aopu.aop_str[offset],s))
1373 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1377 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1378 "aopPut got unsupported aop->type");
1384 /*-----------------------------------------------------------------*/
1385 /* mov2w_op - generate either a MOVLW or MOVFW based operand type */
1386 /*-----------------------------------------------------------------*/
1387 static void mov2w_op (operand *op, int offset)
1392 /* for PO_IMMEDIATEs: use address or value? */
1393 if (op_isLitLike (op))
1395 /* access address of op */
1396 if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
1397 if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
1399 if (offset == GPTRSIZE-1)
1400 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1402 emitpcode (POC_MOVLW, popGetLit (0));
1405 emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
1407 /* access value stored in op */
1408 mov2w (AOP(op), offset);
1413 /*-----------------------------------------------------------------*/
1414 /* mov2w - generate either a MOVLW or MOVFW based operand type */
1415 /*-----------------------------------------------------------------*/
1416 void mov2w (asmop *aop, int offset)
1422 DEBUGpic14_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
1424 if ( aop_isLitLike (aop) )
1425 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1427 emitpcode(POC_MOVFW,popGet(aop,offset));
1431 static void movwf (asmop *op, int offset)
1433 emitpcode (POC_MOVWF, popGet(op, offset));
1436 static pCodeOp *get_argument_pcop (int idx)
1438 assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1439 return popRegFromIdx (Gstack_base_addr - (idx - 1));
1442 static pCodeOp *get_return_val_pcop (int offset)
1444 assert (offset > 0 && "the most significant byte is returned via WREG");
1445 return popRegFromIdx (Gstack_base_addr - (offset - 1));
1448 static void pass_argument (operand *op, int offset, int idx)
1451 mov2w_op (op, offset);
1453 emitpcode(POC_MOVWF, get_argument_pcop (idx));
1456 static void get_returnvalue (operand *op, int offset, int idx)
1459 emitpcode(POC_MOVFW, get_return_val_pcop (idx));
1460 movwf(AOP(op), offset);
1463 static void call_libraryfunc (char *name)
1467 /* library code might reside in different page... */
1468 emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1469 /* call the library function */
1470 emitpcode (POC_CALL, popGetExternal (name, 0));
1471 /* might return from different page... */
1472 emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1474 /* create symbol, mark it as `extern' */
1475 sym = findSym(SymbolTab, NULL, name);
1477 sym = newSymbol(name, 0);
1478 strncpy(sym->rname, name, SDCC_NAME_MAX);
1479 addSym(SymbolTab, sym, sym->rname, 0, 0, 0);
1480 addSet(&externs, sym);
1485 /*-----------------------------------------------------------------*/
1486 /* pic14_getDataSize - get the operand data size */
1487 /*-----------------------------------------------------------------*/
1488 int pic14_getDataSize(operand *op)
1492 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1495 size = getSize(OP_SYM_ETYPE(op));
1497 //return AOP_SIZE(op);
1499 // tsd- in the pic port, the genptr size is 1, so this code here
1500 // fails. ( in the 8051 port, the size was 4).
1502 size = AOP_SIZE(op);
1503 if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)))
1505 sym_link *type = operandType(op);
1506 if (IS_GENPTR(type))
1508 /* generic pointer; arithmetic operations
1509 * should ignore the high byte (pointer type).
1512 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1519 /*-----------------------------------------------------------------*/
1520 /* pic14_outAcc - output Acc */
1521 /*-----------------------------------------------------------------*/
1522 void pic14_outAcc(operand *result)
1525 DEBUGpic14_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
1526 DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1529 size = pic14_getDataSize(result);
1531 emitpcode(POC_MOVWF,popGet(AOP(result),0));
1534 /* unsigned or positive */
1536 emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1541 /*-----------------------------------------------------------------*/
1542 /* pic14_outBitC - output a bit C */
1543 /*-----------------------------------------------------------------*/
1544 void pic14_outBitC(operand *result)
1547 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1548 /* if the result is bit */
1549 if (AOP_TYPE(result) == AOP_CRY)
1550 aopPut(AOP(result),"c",0);
1552 pic14_emitcode("clr","a ; %d", __LINE__);
1553 pic14_emitcode("rlc","a");
1554 pic14_outAcc(result);
1558 /*-----------------------------------------------------------------*/
1559 /* pic14_toBoolean - emit code for orl a,operator(sizeop) */
1560 /*-----------------------------------------------------------------*/
1561 void pic14_toBoolean(operand *oper)
1563 int size = AOP_SIZE(oper);
1566 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1571 /* MOVFW does not load the flags... */
1572 emitpcode(POC_MOVLW, popGetLit(0));
1575 emitpcode(POC_MOVFW,popGet(AOP(oper),0));
1579 while (offset < size) {
1580 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
1582 /* Z is set iff (oper == 0) */
1586 /*-----------------------------------------------------------------*/
1587 /* genNot - generate code for ! operation */
1588 /*-----------------------------------------------------------------*/
1589 static void genNot (iCode *ic)
1596 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1597 /* assign asmOps to operand & result */
1598 aopOp (IC_LEFT(ic),ic,FALSE);
1599 aopOp (IC_RESULT(ic),ic,TRUE);
1601 DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1602 /* if in bit space then a special case */
1603 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1604 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1605 emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
1606 emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
1608 emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
1609 emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
1610 emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
1615 size = AOP_SIZE(IC_LEFT(ic));
1616 mov2w (AOP(IC_LEFT(ic)),0);
1619 if (op_isLitLike (IC_LEFT(ic)))
1620 emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
1622 emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
1624 emitpcode(POC_MOVLW, popGetLit (0));
1626 emitpcode(POC_MOVLW, popGetLit (1));
1627 movwf(AOP(IC_RESULT(ic)), 0);
1629 for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
1631 emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
1636 /* release the aops */
1637 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1638 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1642 /*-----------------------------------------------------------------*/
1643 /* genCpl - generate code for complement */
1644 /*-----------------------------------------------------------------*/
1645 static void genCpl (iCode *ic)
1647 operand *left, *result;
1652 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1653 aopOp((left = IC_LEFT(ic)),ic,FALSE);
1654 aopOp((result=IC_RESULT(ic)),ic,TRUE);
1656 /* if both are in bit space then
1658 if (AOP_TYPE(result) == AOP_CRY &&
1659 AOP_TYPE(left) == AOP_CRY ) {
1661 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir);
1662 pic14_emitcode("cpl","c");
1663 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir);
1667 size = AOP_SIZE(result);
1668 if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
1670 emitpcode(POC_COMFW,popGet(AOP(left),offset));
1671 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
1674 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
1678 /* release the aops */
1679 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1680 freeAsmop(result,NULL,ic,TRUE);
1683 /*-----------------------------------------------------------------*/
1684 /* genUminusFloat - unary minus for floating points */
1685 /*-----------------------------------------------------------------*/
1686 static void genUminusFloat(operand *op,operand *result)
1688 int size ,offset =0 ;
1693 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1694 /* for this we just need to flip the
1695 first it then copy the rest in place */
1696 size = AOP_SIZE(op) - 1;
1697 l = aopGet(AOP(op),3,FALSE,FALSE);
1701 pic14_emitcode("cpl","acc.7");
1702 aopPut(AOP(result),"a",3);
1706 aopGet(AOP(op),offset,FALSE,FALSE),
1712 /*-----------------------------------------------------------------*/
1713 /* genUminus - unary minus code generation */
1714 /*-----------------------------------------------------------------*/
1715 static void genUminus (iCode *ic)
1718 sym_link *optype, *rtype;
1722 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1724 aopOp(IC_LEFT(ic),ic,FALSE);
1725 aopOp(IC_RESULT(ic),ic,TRUE);
1727 /* if both in bit space then special
1729 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1730 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1732 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0));
1733 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
1734 emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0));
1739 optype = operandType(IC_LEFT(ic));
1740 rtype = operandType(IC_RESULT(ic));
1742 /* if float then do float stuff */
1743 if (IS_FLOAT(optype)) {
1744 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1748 /* otherwise subtract from zero by taking the 2's complement */
1749 size = AOP_SIZE(IC_LEFT(ic));
1751 for(i=0; i<size; i++) {
1752 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
1753 emitpcode(POC_COMF, popGet(AOP(IC_LEFT(ic)),i));
1755 emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
1756 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
1760 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0));
1761 for(i=1; i<size; i++) {
1763 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),i));
1767 /* release the aops */
1768 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1769 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1772 /*-----------------------------------------------------------------*/
1773 /* saveRegisters - will look for a call and save the registers */
1774 /*-----------------------------------------------------------------*/
1775 static void saveRegisters(iCode *lic)
1783 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1785 for (ic = lic ; ic ; ic = ic->next)
1786 if (ic->op == CALL || ic->op == PCALL)
1790 fprintf(stderr,"found parameter push with no function call\n");
1794 /* if the registers have been saved already then
1796 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
1799 /* find the registers in use at this time
1800 and push them away to safety */
1801 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1806 //fprintf(stderr, "ERROR: saveRegisters did not do anything to save registers, please report this as a bug.\n");
1808 dtype = operandType(IC_LEFT(ic));
1809 if (currFunc && dtype &&
1810 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
1811 IFFUNC_ISISR(currFunc->type) &&
1814 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
1817 /*-----------------------------------------------------------------*/
1818 /* unsaveRegisters - pop the pushed registers */
1819 /*-----------------------------------------------------------------*/
1820 static void unsaveRegisters (iCode *ic)
1827 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1828 /* find the registers in use at this time
1829 and push them away to safety */
1830 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1833 if (options.useXstack) {
1834 pic14_emitcode("mov","r0,%s",spname);
1835 for (i = pic14_nRegs ; i >= 0 ; i--) {
1836 if (bitVectBitValue(rsave,i)) {
1837 pic14_emitcode("dec","r0");
1838 pic14_emitcode("movx","a,@r0");
1839 pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
1843 pic14_emitcode("mov","%s,r0",spname);
1845 //for (i = pic14_nRegs ; i >= 0 ; i--) {
1846 // if (bitVectBitValue(rsave,i))
1847 // pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
1853 /*-----------------------------------------------------------------*/
1855 /*-----------------------------------------------------------------*/
1856 static void pushSide(operand * oper, int size)
1860 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1862 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1863 if (AOP_TYPE(oper) != AOP_REG &&
1864 AOP_TYPE(oper) != AOP_DIR &&
1866 pic14_emitcode("mov","a,%s",l);
1867 pic14_emitcode("push","acc");
1869 pic14_emitcode("push","%s",l);
1874 /*-----------------------------------------------------------------*/
1875 /* assignResultValue - */
1876 /*-----------------------------------------------------------------*/
1877 static void assignResultValue(operand * oper)
1879 int size = AOP_SIZE(oper);
1884 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1886 DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
1888 /* assign MSB first (passed via WREG) */
1890 get_returnvalue (oper, size, offset + GpsuedoStkPtr);
1896 /*-----------------------------------------------------------------*/
1897 /* genIpush - genrate code for pushing this gets a little complex */
1898 /*-----------------------------------------------------------------*/
1899 static void genIpush (iCode *ic)
1903 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
1905 int size, offset = 0 ;
1909 /* if this is not a parm push : ie. it is spill push
1910 and spill push is always done on the local stack */
1911 if (!ic->parmPush) {
1913 /* and the item is spilt then do nothing */
1914 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1917 aopOp(IC_LEFT(ic),ic,FALSE);
1918 size = AOP_SIZE(IC_LEFT(ic));
1919 /* push it on the stack */
1921 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1926 pic14_emitcode("push","%s",l);
1931 /* this is a paramter push: in this case we call
1932 the routine to find the call and save those
1933 registers that need to be saved */
1936 /* then do the push */
1937 aopOp(IC_LEFT(ic),ic,FALSE);
1940 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1941 size = AOP_SIZE(IC_LEFT(ic));
1944 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1945 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1946 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1948 pic14_emitcode("mov","a,%s",l);
1949 pic14_emitcode("push","acc");
1951 pic14_emitcode("push","%s",l);
1954 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1958 /*-----------------------------------------------------------------*/
1959 /* genIpop - recover the registers: can happen only for spilling */
1960 /*-----------------------------------------------------------------*/
1961 static void genIpop (iCode *ic)
1965 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
1966 assert (!"genIpop -- unimplemented");
1971 /* if the temp was not pushed then */
1972 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1975 aopOp(IC_LEFT(ic),ic,FALSE);
1976 size = AOP_SIZE(IC_LEFT(ic));
1979 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1982 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1986 /*-----------------------------------------------------------------*/
1987 /* unsaverbank - restores the resgister bank from stack */
1988 /*-----------------------------------------------------------------*/
1989 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1993 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
1999 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2001 if (options.useXstack) {
2003 r = getFreePtr(ic,&aop,FALSE);
2006 pic14_emitcode("mov","%s,_spx",r->name);
2007 pic14_emitcode("movx","a,@%s",r->name);
2008 pic14_emitcode("mov","psw,a");
2009 pic14_emitcode("dec","%s",r->name);
2012 pic14_emitcode ("pop","psw");
2015 for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2016 if (options.useXstack) {
2017 pic14_emitcode("movx","a,@%s",r->name);
2018 //pic14_emitcode("mov","(%s+%d),a",
2019 // regspic14[i].base,8*bank+regspic14[i].offset);
2020 pic14_emitcode("dec","%s",r->name);
2023 pic14_emitcode("pop",""); //"(%s+%d)",
2024 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2027 if (options.useXstack) {
2029 pic14_emitcode("mov","_spx,%s",r->name);
2030 freeAsmop(NULL,aop,ic,TRUE);
2036 /*-----------------------------------------------------------------*/
2037 /* saverbank - saves an entire register bank on the stack */
2038 /*-----------------------------------------------------------------*/
2039 static void saverbank (int bank, iCode *ic, bool pushPsw)
2043 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2049 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2050 if (options.useXstack) {
2053 r = getFreePtr(ic,&aop,FALSE);
2054 pic14_emitcode("mov","%s,_spx",r->name);
2058 for (i = 0 ; i < pic14_nRegs ;i++) {
2059 if (options.useXstack) {
2060 pic14_emitcode("inc","%s",r->name);
2061 //pic14_emitcode("mov","a,(%s+%d)",
2062 // regspic14[i].base,8*bank+regspic14[i].offset);
2063 pic14_emitcode("movx","@%s,a",r->name);
2065 pic14_emitcode("push","");// "(%s+%d)",
2066 //regspic14[i].base,8*bank+regspic14[i].offset);
2070 if (options.useXstack) {
2071 pic14_emitcode("mov","a,psw");
2072 pic14_emitcode("movx","@%s,a",r->name);
2073 pic14_emitcode("inc","%s",r->name);
2074 pic14_emitcode("mov","_spx,%s",r->name);
2075 freeAsmop (NULL,aop,ic,TRUE);
2078 pic14_emitcode("push","psw");
2080 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2086 /*-----------------------------------------------------------------*/
2087 /* genCall - generates a call statement */
2088 /*-----------------------------------------------------------------*/
2089 static void genCall (iCode *ic)
2098 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2100 /* if caller saves & we have not saved then */
2104 /* if we are calling a function that is not using
2105 the same register bank then we need to save the
2106 destination registers on the stack */
2107 dtype = operandType(IC_LEFT(ic));
2108 if (currFunc && dtype &&
2109 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2110 IFFUNC_ISISR(currFunc->type) &&
2113 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2115 /* if send set is not empty the assign */
2118 /* For the Pic port, there is no data stack.
2119 * So parameters passed to functions are stored
2120 * in registers. (The pCode optimizer will get
2121 * rid of most of these :).
2123 int psuedoStkPtr=-1;
2124 int firstTimeThruLoop = 1;
2126 _G.sendSet = reverseSet(_G.sendSet);
2128 /* First figure how many parameters are getting passed */
2129 for (sic = setFirstItem(_G.sendSet) ; sic ;
2130 sic = setNextItem(_G.sendSet)) {
2132 aopOp(IC_LEFT(sic),sic,FALSE);
2133 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2134 freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2137 for (sic = setFirstItem(_G.sendSet) ; sic ;
2138 sic = setNextItem(_G.sendSet)) {
2139 int size, offset = 0;
2141 aopOp(IC_LEFT(sic),sic,FALSE);
2142 size = AOP_SIZE(IC_LEFT(sic));
2145 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2146 AopType(AOP_TYPE(IC_LEFT(sic))));
2148 if(!firstTimeThruLoop) {
2149 /* If this is not the first time we've been through the loop
2150 * then we need to save the parameter in a temporary
2151 * register. The last byte of the last parameter is
2153 emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2156 firstTimeThruLoop=0;
2158 mov2w_op (IC_LEFT(sic), offset);
2161 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2166 sym = OP_SYMBOL(IC_LEFT(ic));
2167 name = sym->rname[0] ? sym->rname : sym->name;
2169 * As SDCC emits code as soon as it reaches the end of each
2170 * function's definition, prototyped functions that are implemented
2171 * after the current one are always considered EXTERN, which
2172 * introduces many unneccessary PAGESEL instructions.
2173 * XXX: Use a post pass to iterate over all `CALL _name' statements
2174 * and insert `PAGESEL _name' and `PAGESEL $' around the CALL
2175 * only iff there is no definition of the function in the whole
2176 * file (might include this in the PAGESEL pass).
2178 isExtern = IS_EXTERN(sym->etype) || pic14_inISR;
2180 /* Extern functions and ISRs maybe on a different page;
2181 * must call pagesel */
2182 emitpcode(POC_PAGESEL,popGetWithString(name,1));
2184 emitpcode(POC_CALL,popGetWithString(name,isExtern));
2186 /* May have returned from a different page;
2187 * must use pagesel to restore PCLATH before next
2188 * goto or call instruction */
2189 emitpcode(POC_PAGESEL,popGetWithString("$",0));
2192 /* if we need assign a result value */
2193 if ((IS_ITEMP(IC_RESULT(ic)) &&
2194 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2195 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2196 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2199 aopOp(IC_RESULT(ic),ic,FALSE);
2202 assignResultValue(IC_RESULT(ic));
2204 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2205 AopType(AOP_TYPE(IC_RESULT(ic))));
2207 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2210 /* if register bank was saved then pop them */
2212 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2214 /* if we hade saved some registers then unsave them */
2215 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2216 unsaveRegisters (ic);
2221 /*-----------------------------------------------------------------*/
2222 /* genPcall - generates a call by pointer statement */
2223 /*-----------------------------------------------------------------*/
2224 static void genPcall (iCode *ic)
2227 symbol *albl = newiTempLabel(NULL);
2228 symbol *blbl = newiTempLabel(NULL);
2235 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2236 /* if caller saves & we have not saved then */
2240 /* if we are calling a function that is not using
2241 the same register bank then we need to save the
2242 destination registers on the stack */
2243 dtype = operandType(IC_LEFT(ic));
2244 if (currFunc && dtype &&
2245 IFFUNC_ISISR(currFunc->type) &&
2246 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2247 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2250 aopOp(left,ic,FALSE);
2251 DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2253 poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2255 pushSide(IC_LEFT(ic), FPTRSIZE);
2257 /* if send set is not empty, assign parameters */
2260 DEBUGpic14_emitcode ("; ***","%s %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2261 /* no way to pass args - W always gets used to make the call */
2263 /* first idea - factor out a common helper function and call it.
2264 But don't know how to get it generated only once in its own block
2266 if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2269 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2270 DEBUGpic14_emitcode ("; ***","%s %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2271 buffer = Safe_calloc(1,strlen(rname)+16);
2272 sprintf(buffer, "%s_goto_helper", rname);
2273 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2277 emitpcode(POC_CALL,popGetLabel(albl->key));
2278 pcop = popGetLabel(blbl->key);
2279 emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
2280 emitpcode(POC_GOTO,pcop);
2281 emitpLabel(albl->key);
2283 emitpcode(poc,popGetAddr(AOP(left),1,0));
2284 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2285 emitpcode(poc,popGetAddr(AOP(left),0,0));
2286 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2288 emitpLabel(blbl->key);
2290 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2292 /* if we need to assign a result value */
2293 if ((IS_ITEMP(IC_RESULT(ic)) &&
2294 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2295 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2296 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2299 aopOp(IC_RESULT(ic),ic,FALSE);
2304 assignResultValue(IC_RESULT(ic));
2306 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2309 /* if register bank was saved then unsave them */
2310 if (currFunc && dtype &&
2311 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2312 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2314 /* if we hade saved some registers then
2317 unsaveRegisters (ic);
2321 /*-----------------------------------------------------------------*/
2322 /* resultRemat - result is rematerializable */
2323 /*-----------------------------------------------------------------*/
2324 static int resultRemat (iCode *ic)
2326 // DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2329 if (SKIP_IC(ic) || ic->op == IFX)
2332 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2333 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2334 if (sym->remat && !POINTER_SET(ic))
2342 /*-----------------------------------------------------------------*/
2343 /* inExcludeList - return 1 if the string is in exclude Reg list */
2344 /*-----------------------------------------------------------------*/
2345 static bool inExcludeList(char *s)
2347 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2350 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2351 if (options.excludeRegs[i] &&
2352 STRCASECMP(options.excludeRegs[i],"none") == 0)
2355 for ( i = 0 ; options.excludeRegs[i]; i++) {
2356 if (options.excludeRegs[i] &&
2357 STRCASECMP(s,options.excludeRegs[i]) == 0)
2364 /*-----------------------------------------------------------------*/
2365 /* genFunction - generated code for function entry */
2366 /*-----------------------------------------------------------------*/
2367 static void genFunction (iCode *ic)
2374 DEBUGpic14_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2376 labelOffset += (max_key+4);
2380 /* create the function header */
2381 pic14_emitcode(";","-----------------------------------------");
2382 pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2383 pic14_emitcode(";","-----------------------------------------");
2385 /* prevent this symbol from being emitted as 'extern' */
2386 pic14_stringInSet(sym->rname, &pic14_localFunctions, 1);
2388 pic14_emitcode("","%s:",sym->rname);
2389 addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2391 /* mark symbol as NOT extern (even if it was declared so previously) */
2392 assert(IS_SPEC(sym->etype));
2393 SPEC_EXTR(sym->etype) = 0;
2395 if (!SPEC_OCLS(sym->etype)) SPEC_OCLS(sym->etype) = code;
2396 addSetIfnotP(&SPEC_OCLS(sym->etype)->syms, sym);
2398 ftype = operandType(IC_LEFT(ic));
2400 /* if critical function then turn interrupts off */
2401 if (IFFUNC_ISCRITICAL(ftype))
2402 pic14_emitcode("clr","ea");
2404 /* here we need to generate the equates for the
2405 register bank if required */
2407 if (FUNC_REGBANK(ftype) != rbank) {
2410 rbank = FUNC_REGBANK(ftype);
2411 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2412 if (strcmp(regspic14[i].base,"0") == 0)
2413 pic14_emitcode("","%s = 0x%02x",
2415 8*rbank+regspic14[i].offset);
2417 pic14_emitcode ("","%s = %s + 0x%02x",
2420 8*rbank+regspic14[i].offset);
2425 /* if this is an interrupt service routine */
2427 if (IFFUNC_ISISR(sym->type)) {
2429 emitpcode(POC_MOVWF, popCopyReg(&pc_wsave));
2430 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2431 /* XXX: Why? Does this assume that ssave and psave reside
2432 * in a shared bank or bank0? We cannot guarantee the
2435 emitpcode(POC_CLRF, popCopyReg(&pc_status));
2436 emitpcode(POC_MOVWF, popCopyReg(&pc_ssave));
2437 //emitpcode(POC_MOVWF, popGetExternal("___sdcc_saved_status",1 ));
2438 emitpcode(POC_MOVFW, popCopyReg(&pc_pclath));
2439 /* during an interrupt PCLATH must be cleared before a goto or call statement */
2440 emitpcode(POC_CLRF, popCopyReg(&pc_pclath));
2441 emitpcode(POC_MOVWF, popCopyReg(&pc_psave));
2442 //emitpcode(POC_MOVWF, popGetExternal("___sdcc_saved_pclath", 1));
2443 emitpcode(POC_MOVFW, popCopyReg(&pc_fsr));
2444 emitpcode(POC_MOVWF, popGetExternal("___sdcc_saved_fsr", 1));
2446 pBlockConvert2ISR(pb);
2447 pic14_hasInterrupt = 1;
2449 /* if callee-save to be used for this function
2450 then save the registers being used in this function */
2451 if (IFFUNC_CALLEESAVES(sym->type)) {
2454 /* if any registers used */
2455 if (sym->regsUsed) {
2456 /* save the registers used */
2457 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2458 if (bitVectBitValue(sym->regsUsed,i)) {
2459 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2467 /* set the register bank to the desired value */
2468 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2469 pic14_emitcode("push","psw");
2470 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);
2473 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2475 if (options.useXstack) {
2476 pic14_emitcode("mov","r0,%s",spname);
2477 pic14_emitcode("mov","a,_bp");
2478 pic14_emitcode("movx","@r0,a");
2479 pic14_emitcode("inc","%s",spname);
2483 /* set up the stack */
2484 pic14_emitcode ("push","_bp"); /* save the callers stack */
2486 pic14_emitcode ("mov","_bp,%s",spname);
2489 /* adjust the stack for the function */
2494 werror(W_STACK_OVERFLOW,sym->name);
2496 if (i > 3 && sym->recvSize < 4) {
2498 pic14_emitcode ("mov","a,sp");
2499 pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2500 pic14_emitcode ("mov","sp,a");
2505 pic14_emitcode("inc","sp");
2510 pic14_emitcode ("mov","a,_spx");
2511 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2512 pic14_emitcode ("mov","_spx,a");
2517 /*-----------------------------------------------------------------*/
2518 /* genEndFunction - generates epilogue for functions */
2519 /*-----------------------------------------------------------------*/
2520 static void genEndFunction (iCode *ic)
2522 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2526 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2528 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2530 pic14_emitcode ("mov","%s,_bp",spname);
2533 /* if use external stack but some variables were
2534 added to the local stack then decrement the
2536 if (options.useXstack && sym->stack) {
2537 pic14_emitcode("mov","a,sp");
2538 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2539 pic14_emitcode("mov","sp,a");
2543 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2544 if (options.useXstack) {
2545 pic14_emitcode("mov","r0,%s",spname);
2546 pic14_emitcode("movx","a,@r0");
2547 pic14_emitcode("mov","_bp,a");
2548 pic14_emitcode("dec","%s",spname);
2552 pic14_emitcode ("pop","_bp");
2556 /* restore the register bank */
2557 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2558 pic14_emitcode ("pop","psw");
2560 if (IFFUNC_ISISR(sym->type)) {
2562 /* now we need to restore the registers */
2563 /* if this isr has no bank i.e. is going to
2564 run with bank 0 , then we need to save more
2566 if (!FUNC_REGBANK(sym->type)) {
2568 /* if this function does not call any other
2569 function then we can be economical and
2570 save only those registers that are used */
2571 if (! IFFUNC_HASFCALL(sym->type)) {
2574 /* if any registers used */
2575 if (sym->regsUsed) {
2576 /* save the registers used */
2577 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2578 if (bitVectBitValue(sym->regsUsed,i)) {
2579 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2585 /* this function has a function call; cannot
2586 determines register usage so we will have the
2588 unsaverbank(0,ic,FALSE);
2592 /* if debug then send end of function */
2593 if (options.debug && debugFile && currFunc) {
2594 debugFile->writeEndFunction (currFunc, ic, 1);
2597 emitpcode(POC_MOVFW, popGetExternal("___sdcc_saved_fsr", 1));
2598 emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
2599 //emitpcode(POC_MOVFW, popGetExternal("___sdcc_saved_pclath", 1));
2600 emitpcode(POC_MOVFW, popCopyReg(&pc_psave));
2601 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
2602 emitpcode(POC_CLRF, popCopyReg(&pc_status)); // see genFunction
2603 //emitpcode(POC_SWAPFW, popGetExternal("___sdcc_saved_status", 1));
2604 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
2605 emitpcode(POC_MOVWF, popCopyReg(&pc_status));
2606 emitpcode(POC_SWAPF, popCopyReg(&pc_wsave));
2607 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
2608 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
2609 emitpcodeNULLop(POC_RETFIE);
2612 if (IFFUNC_ISCRITICAL(sym->type))
2613 pic14_emitcode("setb","ea");
2615 if (IFFUNC_CALLEESAVES(sym->type)) {
2618 /* if any registers used */
2619 if (sym->regsUsed) {
2620 /* save the registers used */
2621 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2622 if (bitVectBitValue(sym->regsUsed,i)) {
2623 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2629 /* if debug then send end of function */
2630 if (options.debug && debugFile && currFunc) {
2631 debugFile->writeEndFunction (currFunc, ic, 1);
2634 pic14_emitcode ("return","");
2635 emitpcodeNULLop(POC_RETURN);
2637 /* Mark the end of a function */
2638 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
2643 /*-----------------------------------------------------------------*/
2644 /* genRet - generate code for return statement */
2645 /*-----------------------------------------------------------------*/
2646 static void genRet (iCode *ic)
2648 int size,offset = 0;
2652 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2653 /* if we have no return value then
2654 just generate the "ret" */
2658 /* we have something to return then
2659 move the return value into place */
2660 aopOp(IC_LEFT(ic),ic,FALSE);
2661 size = AOP_SIZE(IC_LEFT(ic));
2663 for (offset = 0; offset < size; offset++)
2665 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
2668 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2671 /* generate a jump to the return label
2672 if the next is not the return statement */
2673 if (!(ic->next && ic->next->op == LABEL &&
2674 IC_LABEL(ic->next) == returnLabel)) {
2676 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
2681 /*-----------------------------------------------------------------*/
2682 /* genLabel - generates a label */
2683 /*-----------------------------------------------------------------*/
2684 static void genLabel (iCode *ic)
2688 /* special case never generate */
2689 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2690 if (IC_LABEL(ic) == entryLabel)
2693 emitpLabel(IC_LABEL(ic)->key);
2694 pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
2697 /*-----------------------------------------------------------------*/
2698 /* genGoto - generates a goto */
2699 /*-----------------------------------------------------------------*/
2701 static void genGoto (iCode *ic)
2705 emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
2706 pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
2710 /*-----------------------------------------------------------------*/
2711 /* genMultbits :- multiplication of bits */
2712 /*-----------------------------------------------------------------*/
2713 static void genMultbits (operand *left,
2718 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2720 if(!pic14_sameRegs(AOP(result),AOP(right)))
2721 emitpcode(POC_BSF, popGet(AOP(result),0));
2723 emitpcode(POC_BTFSC,popGet(AOP(right),0));
2724 emitpcode(POC_BTFSS,popGet(AOP(left),0));
2725 emitpcode(POC_BCF, popGet(AOP(result),0));
2730 /*-----------------------------------------------------------------*/
2731 /* genMultOneByte : 8 bit multiplication & division */
2732 /*-----------------------------------------------------------------*/
2733 static void genMultOneByte (operand *left,
2737 char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
2745 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2746 DEBUGpic14_AopType(__LINE__,left,right,result);
2747 DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
2749 /* (if two literals, the value is computed before) */
2750 /* if one literal, literal on the right */
2751 if (AOP_TYPE(left) == AOP_LIT){
2757 assert (AOP_SIZE(left) == AOP_SIZE(right));
2759 size = min(AOP_SIZE(result),AOP_SIZE(left));
2760 offset = Gstack_base_addr - (2*size - 1);
2762 /* pass right operand as argument */
2763 for (i=0; i < size; i++)
2765 mov2w (AOP(right), i);
2766 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
2769 /* pass left operand as argument */
2770 for (i=0; i < size; i++)
2772 mov2w (AOP(left), i);
2773 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
2775 assert (offset == Gstack_base_addr);
2777 /* call library routine */
2778 assert (size > 0 && size <= 4);
2779 call_libraryfunc (func[size]);
2782 movwf (AOP(result), size-1);
2783 for (i=0; i < size - 1; i++)
2785 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
2786 movwf (AOP(result), size - 2 - i);
2789 /* now (zero-/sign) extend the result to its size */
2790 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2793 /*-----------------------------------------------------------------*/
2794 /* genMult - generates code for multiplication */
2795 /*-----------------------------------------------------------------*/
2796 static void genMult (iCode *ic)
2798 operand *left = IC_LEFT(ic);
2799 operand *right = IC_RIGHT(ic);
2800 operand *result= IC_RESULT(ic);
2804 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2805 /* assign the amsops */
2806 aopOp (left,ic,FALSE);
2807 aopOp (right,ic,FALSE);
2808 aopOp (result,ic,TRUE);
2810 DEBUGpic14_AopType(__LINE__,left,right,result);
2812 /* special cases first */
2814 if (AOP_TYPE(left) == AOP_CRY &&
2815 AOP_TYPE(right)== AOP_CRY) {
2816 genMultbits(left,right,result);
2820 /* if both are of size == 1 */
2821 if (AOP_SIZE(left) == 1 &&
2822 AOP_SIZE(right) == 1 ) {
2823 genMultOneByte(left,right,result);
2827 /* should have been converted to function call */
2831 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2832 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2833 freeAsmop(result,NULL,ic,TRUE);
2836 /*-----------------------------------------------------------------*/
2837 /* genDivbits :- division of bits */
2838 /*-----------------------------------------------------------------*/
2839 static void genDivbits (operand *left,
2848 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2849 /* the result must be bit */
2850 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
2851 l = aopGet(AOP(left),0,FALSE,FALSE);
2855 pic14_emitcode("div","ab");
2856 pic14_emitcode("rrc","a");
2857 aopPut(AOP(result),"c",0);
2860 /*-----------------------------------------------------------------*/
2861 /* genDivOneByte : 8 bit division */
2862 /*-----------------------------------------------------------------*/
2863 static void genDivOneByte (operand *left,
2871 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2873 assert (AOP_SIZE(right) == 1);
2874 assert (AOP_SIZE(left) == 1);
2876 size = min(AOP_SIZE(result),AOP_SIZE(left));
2877 sign = !(SPEC_USIGN(operandType(left))
2878 && SPEC_USIGN(operandType(right)));
2880 if (AOP_TYPE(right) == AOP_LIT)
2882 /* XXX: might add specialized code */
2887 /* unsigned division */
2889 mov2w(AOP(right),0);
2890 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
2892 call_libraryfunc("__divuchar");
2893 movwf(AOP(result),0);
2898 temp = popGetTempReg();
2899 lbl = newiTempLabel(NULL);
2901 /* XXX: improve this naive approach:
2902 [result] = [a] / [b]
2903 ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
2907 movwf temp // temp <-- left
2908 movf right,W // W <-- right
2912 subwf temp,F // temp <-- temp - W
2913 skipNC // subwf clears CARRY (i.e. sets BORROW) if temp < W
2915 decf result // we just subtract once too often
2918 /* XXX: This loops endlessly on DIVIDE BY ZERO */
2919 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
2922 emitpcode(POC_MOVWF, temp);
2923 mov2w(AOP(right),0);
2924 emitpcode(POC_CLRF, popGet(AOP(result),0));
2926 emitpLabel(lbl->key);
2927 emitpcode(POC_INCF, popGet(AOP(result),0));
2928 emitpcode(POC_SUBWF, temp);
2930 emitpcode(POC_GOTO, popGetLabel(lbl->key));
2931 emitpcode(POC_DECF, popGet(AOP(result),0));
2932 popReleaseTempReg(temp);
2937 /* signed division */
2938 mov2w(AOP(right),0);
2939 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
2941 call_libraryfunc("__divschar");
2942 movwf(AOP(result),0);
2945 /* now performed the signed/unsigned division -- extend result */
2946 addSign(result, 1, sign);
2949 /*-----------------------------------------------------------------*/
2950 /* genDiv - generates code for division */
2951 /*-----------------------------------------------------------------*/
2952 static void genDiv (iCode *ic)
2954 operand *left = IC_LEFT(ic);
2955 operand *right = IC_RIGHT(ic);
2956 operand *result= IC_RESULT(ic);
2959 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2960 /* assign the amsops */
2961 aopOp (left,ic,FALSE);
2962 aopOp (right,ic,FALSE);
2963 aopOp (result,ic,TRUE);
2965 /* special cases first */
2967 if (AOP_TYPE(left) == AOP_CRY &&
2968 AOP_TYPE(right)== AOP_CRY) {
2969 genDivbits(left,right,result);
2973 /* if both are of size == 1 */
2974 if (AOP_SIZE(left) == 1 &&
2975 AOP_SIZE(right) == 1 ) {
2976 genDivOneByte(left,right,result);
2980 /* should have been converted to function call */
2983 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2984 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2985 freeAsmop(result,NULL,ic,TRUE);
2988 /*-----------------------------------------------------------------*/
2989 /* genModOneByte : 8 bit modulus */
2990 /*-----------------------------------------------------------------*/
2991 static void genModOneByte (operand *left,
2999 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3001 assert (AOP_SIZE(right) == 1);
3002 assert (AOP_SIZE(left) == 1);
3004 size = min(AOP_SIZE(result),AOP_SIZE(left));
3005 sign = !(SPEC_USIGN(operandType(left))
3006 && SPEC_USIGN(operandType(right)));
3008 if (AOP_TYPE(right) == AOP_LIT)
3010 /* XXX: might add specialized code */
3015 /* unsigned division */
3017 mov2w(AOP(right),0);
3018 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3020 call_libraryfunc("__moduchar");
3021 movwf(AOP(result),0);
3026 lbl = newiTempLabel(NULL);
3028 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3030 /* XXX: improve this naive approach:
3031 [result] = [a] % [b]
3032 ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3036 movwf result // result <-- left
3037 movf right,W // W <-- right
3039 subwf result,F // result <-- result - W
3040 skipNC // subwf clears CARRY (i.e. sets BORROW) if result < W
3042 addwf result, F // we just subtract once too often
3045 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3046 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3048 if (!pic14_sameRegs(AOP(left), AOP(result)))
3051 emitpcode(POC_MOVWF, popGet(AOP(result),0));
3053 mov2w(AOP(right),0);
3055 emitpLabel(lbl->key);
3056 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3058 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3059 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3064 /* signed division */
3065 mov2w(AOP(right),0);
3066 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3068 call_libraryfunc("__modschar");
3069 movwf(AOP(result),0);
3072 /* now we performed the signed/unsigned modulus -- extend result */
3073 addSign(result, 1, sign);
3076 /*-----------------------------------------------------------------*/
3077 /* genMod - generates code for division */
3078 /*-----------------------------------------------------------------*/
3079 static void genMod (iCode *ic)
3081 operand *left = IC_LEFT(ic);
3082 operand *right = IC_RIGHT(ic);
3083 operand *result= IC_RESULT(ic);
3086 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3087 /* assign the amsops */
3088 aopOp (left,ic,FALSE);
3089 aopOp (right,ic,FALSE);
3090 aopOp (result,ic,TRUE);
3092 /* if both are of size == 1 */
3093 if (AOP_SIZE(left) == 1 &&
3094 AOP_SIZE(right) == 1 ) {
3095 genModOneByte(left,right,result);
3099 /* should have been converted to function call */
3103 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3104 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3105 freeAsmop(result,NULL,ic,TRUE);
3108 /*-----------------------------------------------------------------*/
3109 /* genIfxJump :- will create a jump depending on the ifx */
3110 /*-----------------------------------------------------------------*/
3112 note: May need to add parameter to indicate when a variable is in bit space.
3114 static void genIfxJump (iCode *ic, char *jval)
3118 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3119 /* if true label then we jump if condition
3121 if ( IC_TRUE(ic) ) {
3123 if(strcmp(jval,"a") == 0)
3125 else if (strcmp(jval,"c") == 0)
3128 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3129 emitpcode(POC_BTFSC, newpCodeOpBit(jval,-1,1));
3132 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3133 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3137 /* false label is present */
3138 if(strcmp(jval,"a") == 0)
3140 else if (strcmp(jval,"c") == 0)
3143 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3144 emitpcode(POC_BTFSS, newpCodeOpBit(jval,-1,1));
3147 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3148 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3153 /* mark the icode as generated */
3158 /*-----------------------------------------------------------------*/
3160 /*-----------------------------------------------------------------*/
3161 static void genSkip(iCode *ifx,int status_bit)
3167 if ( IC_TRUE(ifx) ) {
3168 switch(status_bit) {
3183 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3184 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3188 switch(status_bit) {
3202 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3203 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3210 /*-----------------------------------------------------------------*/
3212 /*-----------------------------------------------------------------*/
3213 static void genSkipc(resolvedIfx *rifx)
3224 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3225 emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3226 rifx->generated = 1;
3230 /*-----------------------------------------------------------------*/
3232 /*-----------------------------------------------------------------*/
3233 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3239 if( (rifx->condition ^ invert_condition) & 1)
3244 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3245 rifx->generated = 1;
3250 /*-----------------------------------------------------------------*/
3252 /*-----------------------------------------------------------------*/
3253 static void genSkipz(iCode *ifx, int condition)
3256 assert (ifx != NULL);
3264 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3266 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3269 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3271 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3277 /*-----------------------------------------------------------------*/
3279 /*-----------------------------------------------------------------*/
3280 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3287 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3289 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3292 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3293 rifx->generated = 1;
3298 /*-----------------------------------------------------------------*/
3299 /* genChkZeroes :- greater or less than comparison */
3300 /* For each byte in a literal that is zero, inclusive or the */
3301 /* the corresponding byte in the operand with W */
3302 /* returns true if any of the bytes are zero */
3303 /*-----------------------------------------------------------------*/
3304 static int genChkZeroes(operand *op, int lit, int size)
3311 i = (lit >> (size*8)) & 0xff;
3315 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3317 emitpcode(POC_IORFW, popGet(AOP(op),size));
3327 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3328 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
3329 #define DEBUGpc emitpComment
3331 /*-----------------------------------------------------------------*/
3332 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
3333 /* aop (if it's NOT a literal) or from lit (if */
3334 /* aop is a literal) */
3335 /*-----------------------------------------------------------------*/
3336 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3337 if (aop->type == AOP_LIT) {
3338 emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3340 emitpcode (POC_MOVFW, popGet (aop, offset));
3344 /* genCmp performs a left < right comparison, stores
3345 * the outcome in result (if != NULL) and generates
3346 * control flow code for the ifx (if != NULL).
3348 * This version leaves in sequences like
3349 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3350 * which should be optmized by the peephole
3351 * optimizer - RN 2005-01-01 */
3352 static void genCmp (operand *left,operand *right,
3353 operand *result, iCode *ifx, int sign)
3363 int invert_result = 0;
3367 assert (AOP_SIZE(left) == AOP_SIZE(right));
3368 assert (left && right);
3370 size = AOP_SIZE(right) - 1;
3371 mask = (0x100UL << (size*8)) - 1;
3372 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3377 resolveIfx (&rIfx, ifx);
3379 /**********************************************************************
3380 * handle bits - bit compares are promoted to int compares seemingly! *
3381 **********************************************************************/
3383 // THIS IS COMPLETELY UNTESTED!
3384 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3385 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3386 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3387 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3390 // 1 < {0,1} is false --> clear C by skipping the next instruction
3391 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3392 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3393 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3394 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3395 emitCLRC; // only skipped for left=0 && right=1
3397 goto correct_result_in_carry;
3401 /*************************************************
3402 * make sure that left is register (or the like) *
3403 *************************************************/
3404 if (!isAOP_REGlike(left)) {
3405 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
3406 assert (isAOP_LIT(left));
3407 assert (isAOP_REGlike(right));
3408 // swap left and right
3409 // left < right <==> right > left <==> (right >= left + 1)
3410 lit = ulFromVal(AOP(left)->aopu.aop_lit);
3412 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
3413 // MAXVALUE < right? always false
3414 if (performedLt) emitCLRC; else emitSETC;
3415 goto correct_result_in_carry;
3418 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
3419 // that's why we handled it above.
3426 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
3427 } else if (isAOP_LIT(right)) {
3428 lit = ulFromVal(AOP(right)->aopu.aop_lit);
3431 assert (isAOP_REGlike(left)); // left must be register or the like
3432 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
3434 /*************************************************
3435 * special cases go here *
3436 *************************************************/
3438 if (isAOP_LIT(right)) {
3440 // unsigned comparison to a literal
3441 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
3443 // unsigned left < 0? always false
3444 if (performedLt) emitCLRC; else emitSETC;
3445 goto correct_result_in_carry;
3448 // signed comparison to a literal
3449 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
3450 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
3451 // signed left < 0x80000000? always false
3452 if (performedLt) emitCLRC; else emitSETC;
3453 goto correct_result_in_carry;
3454 } else if (lit == 0) {
3455 // compare left < 0; set CARRY if SIGNBIT(left) is set
3456 if (performedLt) emitSETC; else emitCLRC;
3457 emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
3458 if (performedLt) emitCLRC; else emitSETC;
3459 goto correct_result_in_carry;
3462 } // right is literal
3464 /*************************************************
3465 * perform a general case comparison *
3466 * make sure we get CARRY==1 <==> left >= right *
3467 *************************************************/
3468 // compare most significant bytes
3469 //DEBUGpc ("comparing bytes at offset %d", size);
3471 // unsigned comparison
3472 pic14_mov2w_regOrLit (AOP(right), lit, size);
3473 emitpcode (POC_SUBFW, popGet (AOP(left), size));
3475 // signed comparison
3476 // (add 2^n to both operands then perform an unsigned comparison)
3477 if (isAOP_LIT(right)) {
3478 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
3479 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
3481 if (litbyte == 0x80) {
3482 // left >= 0x80 -- always true, but more bytes to come
3483 mov2w (AOP(left), size);
3484 emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
3487 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
3488 mov2w (AOP(left), size);
3489 emitpcode (POC_ADDLW, popGetLit (0x80));
3490 emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
3493 pCodeOp *pctemp = popGetTempReg();
3494 mov2w (AOP(left), size);
3495 emitpcode (POC_ADDLW, popGetLit (0x80));
3496 emitpcode (POC_MOVWF, pctemp);
3497 mov2w (AOP(right), size);
3498 emitpcode (POC_ADDLW, popGetLit (0x80));
3499 emitpcode (POC_SUBFW, pctemp);
3500 popReleaseTempReg(pctemp);
3504 // compare remaining bytes (treat as unsigned case from above)
3505 templbl = newiTempLabel ( NULL );
3508 //DEBUGpc ("comparing bytes at offset %d", offs);
3510 emitpcode (POC_GOTO, popGetLabel (templbl->key));
3511 pic14_mov2w_regOrLit (AOP(right), lit, offs);
3512 emitpcode (POC_SUBFW, popGet (AOP(left), offs));
3514 emitpLabel (templbl->key);
3515 goto result_in_carry;
3519 /****************************************************
3520 * now CARRY contains the result of the comparison: *
3521 * SUBWF sets CARRY iff *
3522 * F-W >= 0 <==> F >= W <==> !(F < W) *
3523 * (F=left, W=right) *
3524 ****************************************************/
3528 // value will be used in the following genSkipc()
3529 rIfx.condition ^= 1;
3532 correct_result_in_carry:
3534 // assign result to variable (if neccessary)
3535 if (result && AOP_TYPE(result) != AOP_CRY) {
3536 //DEBUGpc ("assign result");
3537 size = AOP_SIZE(result);
3539 emitpcode (POC_CLRF, popGet (AOP(result), size));
3541 if (invert_result) {
3543 emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
3545 emitpcode (POC_RLF, popGet (AOP(result), 0));
3549 // perform conditional jump
3551 //DEBUGpc ("generate control flow");
3559 /* OLD VERSION -- BUGGY, DO NOT USE */
3561 /*-----------------------------------------------------------------*/
3562 /* genCmp :- greater or less than comparison */
3563 /*-----------------------------------------------------------------*/
3564 static void genCmp (operand *left,operand *right,
3565 operand *result, iCode *ifx, int sign)
3567 int size; //, offset = 0 ;
3568 unsigned long lit = 0L,i = 0;
3569 resolvedIfx rFalseIfx;
3570 // resolvedIfx rTrueIfx;
3574 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3577 DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
3578 DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
3582 resolveIfx(&rFalseIfx,ifx);
3583 truelbl = newiTempLabel(NULL);
3584 size = max(AOP_SIZE(left),AOP_SIZE(right));
3586 DEBUGpic14_AopType(__LINE__,left,right,result);
3590 /* if literal is on the right then swap with left */
3591 if ((AOP_TYPE(right) == AOP_LIT)) {
3592 operand *tmp = right ;
3593 unsigned long mask = (0x100 << (8*(size-1))) - 1;
3594 lit = ulFromVal(AOP(right)->aopu.aop_lit);
3597 lit = (lit - 1) & mask;
3600 rFalseIfx.condition ^= 1;
3603 } else if ((AOP_TYPE(left) == AOP_LIT)) {
3604 lit = ulFromVal(AOP(left)->aopu.aop_lit);
3608 //if(IC_TRUE(ifx) == NULL)
3609 /* if left & right are bit variables */
3610 if (AOP_TYPE(left) == AOP_CRY &&
3611 AOP_TYPE(right) == AOP_CRY ) {
3612 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3613 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3615 /* subtract right from left if at the
3616 end the carry flag is set then we know that
3617 left is greater than right */
3619 symbol *lbl = newiTempLabel(NULL);
3622 if(AOP_TYPE(right) == AOP_LIT) {
3624 //lit = ulFromVal(AOP(right)->aopu.aop_lit);
3626 DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
3633 genSkipCond(&rFalseIfx,left,size-1,7);
3635 /* no need to compare to 0...*/
3636 /* NOTE: this is a de-generate compare that most certainly
3637 * creates some dead code. */
3638 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3640 if(ifx) ifx->generated = 1;
3647 //i = (lit >> (size*8)) & 0xff;
3648 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3650 emitpcode(POC_MOVFW, popGet(AOP(left),size));
3652 i = ((0-lit) & 0xff);
3655 /* lit is 0x7f, all signed chars are less than
3656 * this except for 0x7f itself */
3657 emitpcode(POC_XORLW, popGetLit(0x7f));
3658 genSkipz2(&rFalseIfx,0);
3660 emitpcode(POC_ADDLW, popGetLit(0x80));
3661 emitpcode(POC_ADDLW, popGetLit(i^0x80));
3662 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
3667 genSkipz2(&rFalseIfx,1);
3669 emitpcode(POC_ADDLW, popGetLit(i));
3670 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
3674 if(ifx) ifx->generated = 1;
3678 /* chars are out of the way. now do ints and longs */
3681 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3688 genSkipCond(&rFalseIfx,left,size,7);
3689 if(ifx) ifx->generated = 1;
3694 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3696 //rFalseIfx.condition ^= 1;
3697 //genSkipCond(&rFalseIfx,left,size,7);
3698 //rFalseIfx.condition ^= 1;
3700 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3701 if(rFalseIfx.condition)
3702 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
3704 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
3706 emitpcode(POC_MOVLW, popGetLit(0x100-lit));
3707 emitpcode(POC_ADDFW, popGet(AOP(left),0));
3708 emitpcode(POC_MOVFW, popGet(AOP(left),1));
3711 emitpcode(POC_IORFW, popGet(AOP(left),size--));
3713 if(rFalseIfx.condition) {
3715 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
3721 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
3722 emitpLabel(truelbl->key);
3723 if(ifx) ifx->generated = 1;
3730 if( (lit & 0xff) == 0) {
3731 /* lower byte is zero */
3732 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3733 i = ((lit >> 8) & 0xff) ^0x80;
3734 emitpcode(POC_MOVFW, popGet(AOP(left),size));
3735 emitpcode(POC_ADDLW, popGetLit( 0x80));
3736 emitpcode(POC_ADDLW, popGetLit(0x100-i));
3737 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
3740 if(ifx) ifx->generated = 1;
3745 /* Special cases for signed longs */
3746 if( (lit & 0xffffff) == 0) {
3747 /* lower byte is zero */
3748 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3749 i = ((lit >> 8*3) & 0xff) ^0x80;
3750 emitpcode(POC_MOVFW, popGet(AOP(left),size));
3751 emitpcode(POC_ADDLW, popGetLit( 0x80));
3752 emitpcode(POC_ADDLW, popGetLit(0x100-i));
3753 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
3756 if(ifx) ifx->generated = 1;
3764 if(lit & (0x80 << (size*8))) {
3765 /* lit is negative */
3766 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3768 //genSkipCond(&rFalseIfx,left,size,7);
3770 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3772 if(rFalseIfx.condition)
3773 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
3775 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
3779 /* lit is positive */
3780 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3781 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3782 if(rFalseIfx.condition)
3783 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
3785 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
3789 /* There are no more special cases, so perform a general compare */
3791 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3792 emitpcode(POC_SUBFW, popGet(AOP(left),size));
3796 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3798 emitpcode(POC_SUBFW, popGet(AOP(left),size));
3800 //rFalseIfx.condition ^= 1;
3801 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
3803 emitpLabel(truelbl->key);
3805 if(ifx) ifx->generated = 1;
3812 /* sign is out of the way. So now do an unsigned compare */
3813 DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
3816 /* General case - compare to an unsigned literal on the right.*/
3818 i = (lit >> (size*8)) & 0xff;
3819 emitpcode(POC_MOVLW, popGetLit(i));
3820 emitpcode(POC_SUBFW, popGet(AOP(left),size));
3822 i = (lit >> (size*8)) & 0xff;
3825 emitpcode(POC_MOVLW, popGetLit(i));
3827 emitpcode(POC_SUBFW, popGet(AOP(left),size));
3829 /* this byte of the lit is zero,
3830 *if it's not the last then OR in the variable */
3832 emitpcode(POC_IORFW, popGet(AOP(left),size));
3837 emitpLabel(lbl->key);
3838 //if(emitFinalCheck)
3839 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
3841 emitpLabel(truelbl->key);
3843 if(ifx) ifx->generated = 1;
3850 if(AOP_TYPE(left) == AOP_LIT) {
3851 //symbol *lbl = newiTempLabel(NULL);
3853 //EXPERIMENTAL lit = ulFromVal(AOP(left)->aopu.aop_lit);
3856 DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
3859 if((lit == 0) && (sign == 0)){
3862 emitpcode(POC_MOVFW, popGet(AOP(right),size));
3864 emitpcode(POC_IORFW, popGet(AOP(right),--size));
3866 genSkipz2(&rFalseIfx,0);
3867 if(ifx) ifx->generated = 1;
3874 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
3875 /* degenerate compare can never be true */
3876 if(rFalseIfx.condition == 0)
3877 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3879 if(ifx) ifx->generated = 1;
3884 /* signed comparisons to a literal byte */
3886 int lp1 = (lit+1) & 0xff;
3888 DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
3891 rFalseIfx.condition ^= 1;
3892 genSkipCond(&rFalseIfx,right,0,7);
3895 emitpcode(POC_MOVFW, popGet(AOP(right),0));
3896 emitpcode(POC_XORLW, popGetLit(0x7f));
3897 genSkipz2(&rFalseIfx,1);
3900 emitpcode(POC_MOVFW, popGet(AOP(right),0));
3901 emitpcode(POC_ADDLW, popGetLit(0x80));
3902 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
3903 rFalseIfx.condition ^= 1;
3904 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
3907 if(ifx) ifx->generated = 1;
3909 /* unsigned comparisons to a literal byte */
3911 switch(lit & 0xff ) {
3913 emitpcode(POC_MOVFW, popGet(AOP(right),0));
3914 genSkipz2(&rFalseIfx,0);
3915 if(ifx) ifx->generated = 1;
3918 genSkipCond(&rFalseIfx,right,0,7);
3919 if(ifx) ifx->generated = 1;
3923 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
3924 emitpcode(POC_SUBFW, popGet(AOP(right),0));
3925 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3926 rFalseIfx.condition ^= 1;
3927 if (AOP_TYPE(result) == AOP_CRY) {
3928 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
3929 if(ifx) ifx->generated = 1;
3931 DEBUGpic14_emitcode ("; ***","%s %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
3932 emitpcode(POC_CLRF, popGet(AOP(result),0));
3933 emitpcode(POC_RLF, popGet(AOP(result),0));
3934 emitpcode(POC_MOVLW, popGetLit(0x01));
3935 emitpcode(POC_XORWF, popGet(AOP(result),0));
3946 /* Size is greater than 1 */
3954 /* this means lit = 0xffffffff, or -1 */
3957 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
3958 rFalseIfx.condition ^= 1;
3959 genSkipCond(&rFalseIfx,right,size,7);
3960 if(ifx) ifx->generated = 1;
3967 if(rFalseIfx.condition) {
3968 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
3969 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
3972 emitpcode(POC_MOVFW, popGet(AOP(right),size));
3974 emitpcode(POC_IORFW, popGet(AOP(right),size));
3978 if(rFalseIfx.condition) {
3979 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
3980 emitpLabel(truelbl->key);
3982 rFalseIfx.condition ^= 1;
3983 genSkipCond(&rFalseIfx,right,s,7);
3986 if(ifx) ifx->generated = 1;
3990 if((size == 1) && (0 == (lp1&0xff))) {
3991 /* lower byte of signed word is zero */
3992 DEBUGpic14_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
3993 i = ((lp1 >> 8) & 0xff) ^0x80;
3994 emitpcode(POC_MOVFW, popGet(AOP(right),size));
3995 emitpcode(POC_ADDLW, popGetLit( 0x80));
3996 emitpcode(POC_ADDLW, popGetLit(0x100-i));
3997 rFalseIfx.condition ^= 1;
3998 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4001 if(ifx) ifx->generated = 1;
4005 if(lit & (0x80 << (size*8))) {
4006 /* Lit is less than zero */
4007 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
4008 //rFalseIfx.condition ^= 1;
4009 //genSkipCond(&rFalseIfx,left,size,7);
4010 //rFalseIfx.condition ^= 1;
4011 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4012 //emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4014 if(rFalseIfx.condition)
4015 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4017 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4021 /* Lit is greater than or equal to zero */
4022 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
4023 //rFalseIfx.condition ^= 1;
4024 //genSkipCond(&rFalseIfx,right,size,7);
4025 //rFalseIfx.condition ^= 1;
4027 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4028 //emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4030 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4031 if(rFalseIfx.condition)
4032 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4034 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4039 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4040 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4044 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4046 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4048 rFalseIfx.condition ^= 1;
4049 //rFalseIfx.condition = 1;
4050 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4052 emitpLabel(truelbl->key);
4054 if(ifx) ifx->generated = 1;
4059 /* compare word or long to an unsigned literal on the right.*/
4064 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4067 break; /* handled above */
4070 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4072 emitpcode(POC_IORFW, popGet(AOP(right),size));
4073 genSkipz2(&rFalseIfx,0);
4077 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4079 emitpcode(POC_IORFW, popGet(AOP(right),size));
4082 if(rFalseIfx.condition)
4083 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4085 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4088 emitpcode(POC_MOVLW, popGetLit(lit+1));
4089 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4091 rFalseIfx.condition ^= 1;
4092 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4095 emitpLabel(truelbl->key);
4097 if(ifx) ifx->generated = 1;
4103 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4104 i = (lit >> (size*8)) & 0xff;
4106 emitpcode(POC_MOVLW, popGetLit(i));
4107 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4110 i = (lit >> (size*8)) & 0xff;
4113 emitpcode(POC_MOVLW, popGetLit(i));
4115 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4117 /* this byte of the lit is zero,
4118 *if it's not the last then OR in the variable */
4120 emitpcode(POC_IORFW, popGet(AOP(right),size));
4125 emitpLabel(lbl->key);
4127 rFalseIfx.condition ^= 1;
4128 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4132 emitpLabel(truelbl->key);
4133 if(ifx) ifx->generated = 1;
4137 /* Compare two variables */
4139 DEBUGpic14_emitcode(";sign","%d",sign);
4143 /* Sigh. thus sucks... */
4145 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4146 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4147 emitpcode(POC_MOVLW, popGetLit(0x80));
4148 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4149 emitpcode(POC_XORFW, popGet(AOP(right),size));
4150 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4152 /* Signed char comparison */
4153 /* Special thanks to Nikolai Golovchenko for this snippet */
4154 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4155 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4156 emitpcode(POC_RRFW, popGet(AOP(left),0)); /* could be any register */
4157 emitpcode(POC_XORFW, popGet(AOP(left),0));
4158 emitpcode(POC_XORFW, popGet(AOP(right),0));
4159 emitpcode(POC_ADDLW, popGetLit(0x80));
4161 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4162 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4164 if(ifx) ifx->generated = 1;
4170 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4171 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4175 /* The rest of the bytes of a multi-byte compare */
4179 emitpcode(POC_GOTO, popGetLabel(lbl->key));
4182 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4183 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4188 emitpLabel(lbl->key);
4190 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4191 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
4192 (AOP_TYPE(result) == AOP_REG)) {
4193 emitpcode(POC_CLRF, popGet(AOP(result),0));
4194 emitpcode(POC_RLF, popGet(AOP(result),0));
4196 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4198 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4199 if(ifx) ifx->generated = 1;
4206 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4207 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4208 pic14_outBitC(result);
4210 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4211 /* if the result is used in the next
4212 ifx conditional branch then generate
4213 code a little differently */
4215 genIfxJump (ifx,"c");
4217 pic14_outBitC(result);
4218 /* leave the result in acc */
4224 /*-----------------------------------------------------------------*/
4225 /* genCmpGt :- greater than comparison */
4226 /*-----------------------------------------------------------------*/
4227 static void genCmpGt (iCode *ic, iCode *ifx)
4229 operand *left, *right, *result;
4230 sym_link *letype , *retype;
4234 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4236 right= IC_RIGHT(ic);
4237 result = IC_RESULT(ic);
4239 letype = getSpec(operandType(left));
4240 retype =getSpec(operandType(right));
4241 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4242 /* assign the amsops */
4243 aopOp (left,ic,FALSE);
4244 aopOp (right,ic,FALSE);
4245 aopOp (result,ic,TRUE);
4247 genCmp(right, left, result, ifx, sign);
4249 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4250 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4251 freeAsmop(result,NULL,ic,TRUE);
4254 /*-----------------------------------------------------------------*/
4255 /* genCmpLt - less than comparisons */
4256 /*-----------------------------------------------------------------*/
4257 static void genCmpLt (iCode *ic, iCode *ifx)
4259 operand *left, *right, *result;
4260 sym_link *letype , *retype;
4264 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4266 right= IC_RIGHT(ic);
4267 result = IC_RESULT(ic);
4269 letype = getSpec(operandType(left));
4270 retype =getSpec(operandType(right));
4271 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4273 /* assign the amsops */
4274 aopOp (left,ic,FALSE);
4275 aopOp (right,ic,FALSE);
4276 aopOp (result,ic,TRUE);
4278 genCmp(left, right, result, ifx, sign);
4280 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4281 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4282 freeAsmop(result,NULL,ic,TRUE);
4285 /*-----------------------------------------------------------------*/
4286 /* genCmpEq - generates code for equal to */
4287 /*-----------------------------------------------------------------*/
4288 static void genCmpEq (iCode *ic, iCode *ifx)
4290 operand *left, *right, *result;
4292 symbol *false_label;
4295 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4298 DEBUGpic14_emitcode ("; ifx is non-null","");
4300 DEBUGpic14_emitcode ("; ifx is null","");
4302 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4303 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4304 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4306 DEBUGpic14_AopType(__LINE__,left,right,result);
4308 /* if literal, move literal to right */
4309 if (op_isLitLike (IC_LEFT(ic))) {
4310 operand *tmp = right ;
4316 if (ifx && !IC_TRUE(ifx))
4318 assert (IC_FALSE(ifx));
4319 false_label = IC_FALSE(ifx);
4322 size = min(AOP_SIZE(left),AOP_SIZE(right));
4323 assert(!pic14_sameRegs(AOP(result),AOP(left)));
4324 assert(!pic14_sameRegs(AOP(result),AOP(right)));
4326 /* assume left != right */
4329 for (i=0; i < AOP_SIZE(result); i++)
4331 emitpcode(POC_CLRF, popGet(AOP(result),i));
4335 if (AOP_TYPE(right) == AOP_LIT)
4337 unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit);
4339 size = AOP_SIZE(left);
4340 assert(!op_isLitLike(left));
4345 mov2w(AOP(left), 0);
4346 for (i=1; i < size; i++)
4347 emitpcode(POC_IORFW,popGet(AOP(left),i));
4348 /* now Z is set iff `left == right' */
4350 if (!false_label) false_label = newiTempLabel(NULL);
4351 emitpcode(POC_GOTO, popGetLabel(false_label->key));
4355 for (i=0; i < size; i++)
4358 emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
4359 /* now Z is cleared if `left != right' */
4361 if (!false_label) false_label = newiTempLabel(NULL);
4362 emitpcode(POC_GOTO, popGetLabel(false_label->key));
4369 /* right is no literal */
4372 for (i=0; i < size; i++)
4374 mov2w(AOP(right),i);
4375 emitpcode(POC_XORFW,popGet(AOP(left),i));
4376 /* now Z is cleared if `left != right' */
4378 if (!false_label) false_label = newiTempLabel(NULL);
4379 emitpcode(POC_GOTO, popGetLabel(false_label->key));
4383 /* if we reach here, left == right */
4385 if (AOP_SIZE(result) > 0)
4387 emitpcode(POC_INCF, popGet(AOP(result),0));
4390 if (ifx && IC_TRUE(ifx))
4392 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4395 if (false_label && (!ifx || IC_TRUE(ifx)))
4396 emitpLabel(false_label->key);
4398 if (ifx) ifx->generated = 1;
4400 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4401 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4402 freeAsmop(result,NULL,ic,TRUE);
4405 /*-----------------------------------------------------------------*/
4406 /* ifxForOp - returns the icode containing the ifx for operand */
4407 /*-----------------------------------------------------------------*/
4408 static iCode *ifxForOp ( operand *op, iCode *ic )
4411 /* if true symbol then needs to be assigned */
4412 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4413 if (IS_TRUE_SYMOP(op))
4416 /* if this has register type condition and
4417 the next instruction is ifx with the same operand
4418 and live to of the operand is upto the ifx only then */
4420 ic->next->op == IFX &&
4421 IC_COND(ic->next)->key == op->key &&
4422 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4426 ic->next->op == IFX &&
4427 IC_COND(ic->next)->key == op->key) {
4428 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
4432 DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
4434 ic->next->op == IFX)
4435 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
4438 ic->next->op == IFX &&
4439 IC_COND(ic->next)->key == op->key) {
4440 DEBUGpic14_emitcode ("; "," key is okay");
4441 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
4442 OP_SYMBOL(op)->liveTo,
4449 /*-----------------------------------------------------------------*/
4450 /* genAndOp - for && operation */
4451 /*-----------------------------------------------------------------*/
4452 static void genAndOp (iCode *ic)
4454 operand *left,*right, *result;
4458 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4459 /* note here that && operations that are in an
4460 if statement are taken away by backPatchLabels
4461 only those used in arthmetic operations remain */
4462 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4463 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4464 aopOp((result=IC_RESULT(ic)),ic,FALSE);
4466 DEBUGpic14_AopType(__LINE__,left,right,result);
4468 emitpcode(POC_MOVFW,popGet(AOP(left),0));
4469 emitpcode(POC_ANDFW,popGet(AOP(right),0));
4470 emitpcode(POC_MOVWF,popGet(AOP(result),0));
4472 /* if both are bit variables */
4473 /* if (AOP_TYPE(left) == AOP_CRY && */
4474 /* AOP_TYPE(right) == AOP_CRY ) { */
4475 /* pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
4476 /* pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
4477 /* pic14_outBitC(result); */
4479 /* tlbl = newiTempLabel(NULL); */
4480 /* pic14_toBoolean(left); */
4481 /* pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
4482 /* pic14_toBoolean(right); */
4483 /* pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
4484 /* pic14_outBitAcc(result); */
4487 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4488 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4489 freeAsmop(result,NULL,ic,TRUE);
4493 /*-----------------------------------------------------------------*/
4494 /* genOrOp - for || operation */
4495 /*-----------------------------------------------------------------*/
4498 modified this code, but it doesn't appear to ever get called
4501 static void genOrOp (iCode *ic)
4503 operand *left,*right, *result;
4507 /* note here that || operations that are in an
4508 if statement are taken away by backPatchLabels
4509 only those used in arthmetic operations remain */
4511 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4512 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4513 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4514 aopOp((result=IC_RESULT(ic)),ic,FALSE);
4516 DEBUGpic14_AopType(__LINE__,left,right,result);
4518 for (i=0; i < AOP_SIZE(result); i++)
4520 emitpcode(POC_CLRF, popGet(AOP(result), i));
4523 tlbl = newiTempLabel(NULL);
4524 pic14_toBoolean(left);
4526 emitpcode(POC_GOTO, popGetLabel(tlbl->key));
4527 pic14_toBoolean(right);
4528 emitpLabel(tlbl->key);
4529 /* here Z is clear IFF `left || right' */
4531 emitpcode(POC_INCF, popGet(AOP(result), 0));
4533 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4534 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4535 freeAsmop(result,NULL,ic,TRUE);
4538 /*-----------------------------------------------------------------*/
4539 /* isLiteralBit - test if lit == 2^n */
4540 /*-----------------------------------------------------------------*/
4541 static int isLiteralBit(unsigned long lit)
4543 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4544 0x100L,0x200L,0x400L,0x800L,
4545 0x1000L,0x2000L,0x4000L,0x8000L,
4546 0x10000L,0x20000L,0x40000L,0x80000L,
4547 0x100000L,0x200000L,0x400000L,0x800000L,
4548 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4549 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4553 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4554 for(idx = 0; idx < 32; idx++)
4560 /*-----------------------------------------------------------------*/
4561 /* continueIfTrue - */
4562 /*-----------------------------------------------------------------*/
4563 static void continueIfTrue (iCode *ic)
4566 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4570 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
4571 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4576 /*-----------------------------------------------------------------*/
4578 /*-----------------------------------------------------------------*/
4579 static void jumpIfTrue (iCode *ic)
4582 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4586 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
4587 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4592 /*-----------------------------------------------------------------*/
4593 /* jmpTrueOrFalse - */
4594 /*-----------------------------------------------------------------*/
4595 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4598 // ugly but optimized by peephole
4599 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4601 symbol *nlbl = newiTempLabel(NULL);
4602 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);
4603 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4604 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4605 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
4608 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4609 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4614 /*-----------------------------------------------------------------*/
4615 /* genAnd - code for and */
4616 /*-----------------------------------------------------------------*/
4617 static void genAnd (iCode *ic, iCode *ifx)
4619 operand *left, *right, *result;
4621 unsigned long lit = 0L;
4626 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4627 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4628 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4629 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4631 resolveIfx(&rIfx,ifx);
4633 /* if left is a literal & right is not then exchange them */
4634 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4635 AOP_NEEDSACC(left)) {
4636 operand *tmp = right ;
4641 /* if result = right then exchange them */
4642 if(pic14_sameRegs(AOP(result),AOP(right))){
4643 operand *tmp = right ;
4648 /* if right is bit then exchange them */
4649 if (AOP_TYPE(right) == AOP_CRY &&
4650 AOP_TYPE(left) != AOP_CRY){
4651 operand *tmp = right ;
4655 if(AOP_TYPE(right) == AOP_LIT)
4656 lit = ulFromVal (AOP(right)->aopu.aop_lit);
4658 size = AOP_SIZE(result);
4660 DEBUGpic14_AopType(__LINE__,left,right,result);
4663 // result = bit & yy;
4664 if (AOP_TYPE(left) == AOP_CRY){
4665 // c = bit & literal;
4666 if(AOP_TYPE(right) == AOP_LIT){
4668 if(size && pic14_sameRegs(AOP(result),AOP(left)))
4671 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4674 if(size && (AOP_TYPE(result) == AOP_CRY)){
4675 pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4678 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4682 pic14_emitcode("clr","c");
4685 if (AOP_TYPE(right) == AOP_CRY){
4687 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4688 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4691 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
4693 pic14_emitcode("rrc","a");
4694 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4700 pic14_outBitC(result);
4702 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4703 genIfxJump(ifx, "c");
4707 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4708 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4709 if((AOP_TYPE(right) == AOP_LIT) &&
4710 (AOP_TYPE(result) == AOP_CRY) &&
4711 (AOP_TYPE(left) != AOP_CRY)){
4712 int posbit = isLiteralBit(lit);
4716 //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
4719 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
4724 while (posbit > 7) {
4728 emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
4729 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
4730 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4737 symbol *tlbl = newiTempLabel(NULL);
4738 int sizel = AOP_SIZE(left);
4740 pic14_emitcode("setb","c");
4742 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4743 mov2w( AOP(left), offset);
4745 if((posbit = isLiteralBit(bytelit)) != 0) {
4746 emitpcode(rIfx.condition ? POC_BTFSC : POC_BTFSS, // XXX: or the other way round?
4747 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit - 1, 0));
4748 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
4751 emitpcode(POC_ANDLW, newpCodeOpLit(bytelit & 0x0ff));
4752 if (rIfx.condition) emitSKPZ;
4755 if(bytelit != 0x0FFL)
4757 pic14_emitcode("anl","a,%s",
4758 aopGet(AOP(right),offset,FALSE,TRUE));
4760 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
4763 emitpcode(POC_GOTO, popGetLabel(rIfx.lbl->key));
4769 // bit = left & literal
4771 pic14_emitcode("clr","c");
4772 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4774 // if(left & literal)
4777 jmpTrueOrFalse(ifx, tlbl);
4781 pic14_outBitC(result);
4785 /* if left is same as result */
4786 if(pic14_sameRegs(AOP(result),AOP(left))){
4788 for(;size--; offset++,lit>>=8) {
4789 if(AOP_TYPE(right) == AOP_LIT){
4790 switch(lit & 0xff) {
4792 /* and'ing with 0 has clears the result */
4793 emitpcode(POC_CLRF,popGet(AOP(result),offset));
4796 /* and'ing with 0xff is a nop when the result and left are the same */
4801 int p = my_powof2( (~lit) & 0xff );
4803 /* only one bit is set in the literal, so use a bcf instruction */
4804 emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
4807 if(know_W != (int)(lit&0xff))
4808 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
4810 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
4815 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
4816 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
4821 // left & result in different registers
4822 if(AOP_TYPE(result) == AOP_CRY){
4824 // if(size), result in bit
4825 // if(!size && ifx), conditional oper: if(left & right)
4826 symbol *tlbl = newiTempLabel(NULL);
4827 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4829 pic14_emitcode("setb","c");
4831 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4832 pic14_emitcode("anl","a,%s",
4833 aopGet(AOP(left),offset,FALSE,FALSE));
4834 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
4839 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4840 pic14_outBitC(result);
4842 jmpTrueOrFalse(ifx, tlbl);
4844 for(;(size--);offset++) {
4846 // result = left & right
4847 if(AOP_TYPE(right) == AOP_LIT){
4848 int t = (lit >> (offset*8)) & 0x0FFL;
4851 emitpcode(POC_CLRF,popGet(AOP(result),offset));
4854 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4855 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
4858 emitpcode(POC_MOVLW, popGetLit(t));
4859 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
4860 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
4865 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
4866 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
4867 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
4873 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4874 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4875 freeAsmop(result,NULL,ic,TRUE);
4878 /*-----------------------------------------------------------------*/
4879 /* genOr - code for or */
4880 /*-----------------------------------------------------------------*/
4881 static void genOr (iCode *ic, iCode *ifx)
4883 operand *left, *right, *result;
4885 unsigned long lit = 0L;
4888 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4890 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4891 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4892 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4894 DEBUGpic14_AopType(__LINE__,left,right,result);
4896 /* if left is a literal & right is not then exchange them */
4897 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4898 AOP_NEEDSACC(left)) {
4899 operand *tmp = right ;
4904 /* if result = right then exchange them */
4905 if(pic14_sameRegs(AOP(result),AOP(right))){
4906 operand *tmp = right ;
4911 /* if right is bit then exchange them */
4912 if (AOP_TYPE(right) == AOP_CRY &&
4913 AOP_TYPE(left) != AOP_CRY){
4914 operand *tmp = right ;
4919 DEBUGpic14_AopType(__LINE__,left,right,result);
4921 if(AOP_TYPE(right) == AOP_LIT)
4922 lit = ulFromVal (AOP(right)->aopu.aop_lit);
4924 size = AOP_SIZE(result);
4928 if (AOP_TYPE(left) == AOP_CRY){
4929 if(AOP_TYPE(right) == AOP_LIT){
4930 // c = bit & literal;
4932 // lit != 0 => result = 1
4933 if(AOP_TYPE(result) == AOP_CRY){
4935 emitpcode(POC_BSF, popGet(AOP(result),0));
4936 //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
4937 // AOP(result)->aopu.aop_dir,
4938 // AOP(result)->aopu.aop_dir);
4940 continueIfTrue(ifx);
4944 // lit == 0 => result = left
4945 if(size && pic14_sameRegs(AOP(result),AOP(left)))
4947 pic14_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
4950 if (AOP_TYPE(right) == AOP_CRY){
4951 if(pic14_sameRegs(AOP(result),AOP(left))){
4953 emitpcode(POC_BCF, popGet(AOP(result),0));
4954 emitpcode(POC_BTFSC, popGet(AOP(right),0));
4955 emitpcode(POC_BSF, popGet(AOP(result),0));
4957 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
4958 AOP(result)->aopu.aop_dir,
4959 AOP(result)->aopu.aop_dir);
4960 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
4961 AOP(right)->aopu.aop_dir,
4962 AOP(right)->aopu.aop_dir);
4963 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
4964 AOP(result)->aopu.aop_dir,
4965 AOP(result)->aopu.aop_dir);
4967 emitpcode(POC_BCF, popGet(AOP(result),0));
4968 emitpcode(POC_BTFSS, popGet(AOP(right),0));
4969 emitpcode(POC_BTFSC, popGet(AOP(left),0));
4970 emitpcode(POC_BSF, popGet(AOP(result),0));
4974 symbol *tlbl = newiTempLabel(NULL);
4975 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4978 emitpcode(POC_BCF, popGet(AOP(result),0));
4980 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4981 pic14_emitcode(";XXX setb","c");
4982 pic14_emitcode(";XXX jb","%s,%05d_DS_",
4983 AOP(left)->aopu.aop_dir,tlbl->key+100);
4984 pic14_toBoolean(right);
4985 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
4986 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4987 jmpTrueOrFalse(ifx, tlbl);
4991 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4998 pic14_outBitC(result);
5000 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5001 genIfxJump(ifx, "c");
5005 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5006 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5007 if((AOP_TYPE(right) == AOP_LIT) &&
5008 (AOP_TYPE(result) == AOP_CRY) &&
5009 (AOP_TYPE(left) != AOP_CRY)){
5011 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5014 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5016 continueIfTrue(ifx);
5019 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5020 // lit = 0, result = boolean(left)
5022 pic14_emitcode(";XXX setb","c");
5023 pic14_toBoolean(right);
5025 symbol *tlbl = newiTempLabel(NULL);
5026 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5028 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5030 genIfxJump (ifx,"a");
5034 pic14_outBitC(result);
5038 /* if left is same as result */
5039 if(pic14_sameRegs(AOP(result),AOP(left))){
5041 for(;size--; offset++,lit>>=8) {
5042 if(AOP_TYPE(right) == AOP_LIT){
5043 if((lit & 0xff) == 0)
5044 /* or'ing with 0 has no effect */
5047 int p = my_powof2(lit & 0xff);
5049 /* only one bit is set in the literal, so use a bsf instruction */
5051 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5053 if(know_W != (int)(lit & 0xff))
5054 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5055 know_W = lit & 0xff;
5056 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5061 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
5062 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5066 // left & result in different registers
5067 if(AOP_TYPE(result) == AOP_CRY){
5069 // if(size), result in bit
5070 // if(!size && ifx), conditional oper: if(left | right)
5071 symbol *tlbl = newiTempLabel(NULL);
5072 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5073 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5077 pic14_emitcode(";XXX setb","c");
5079 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5080 pic14_emitcode(";XXX orl","a,%s",
5081 aopGet(AOP(left),offset,FALSE,FALSE));
5082 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5087 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5088 pic14_outBitC(result);
5090 jmpTrueOrFalse(ifx, tlbl);
5091 } else for(;(size--);offset++){
5093 // result = left | right
5094 if(AOP_TYPE(right) == AOP_LIT){
5095 int t = (lit >> (offset*8)) & 0x0FFL;
5098 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
5099 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5103 emitpcode(POC_MOVLW, popGetLit(t));
5104 emitpcode(POC_IORFW, popGet(AOP(left),offset));
5105 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5110 // faster than result <- left, anl result,right
5111 // and better if result is SFR
5112 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5113 emitpcode(POC_IORFW,popGet(AOP(left),offset));
5114 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5119 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5120 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5121 freeAsmop(result,NULL,ic,TRUE);
5124 /*-----------------------------------------------------------------*/
5125 /* genXor - code for xclusive or */
5126 /*-----------------------------------------------------------------*/
5127 static void genXor (iCode *ic, iCode *ifx)
5129 operand *left, *right, *result;
5131 unsigned long lit = 0L;
5134 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5136 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5137 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5138 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5140 /* if left is a literal & right is not ||
5141 if left needs acc & right does not */
5142 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5143 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5144 operand *tmp = right ;
5149 /* if result = right then exchange them */
5150 if(pic14_sameRegs(AOP(result),AOP(right))){
5151 operand *tmp = right ;
5156 /* if right is bit then exchange them */
5157 if (AOP_TYPE(right) == AOP_CRY &&
5158 AOP_TYPE(left) != AOP_CRY){
5159 operand *tmp = right ;
5163 if(AOP_TYPE(right) == AOP_LIT)
5164 lit = ulFromVal (AOP(right)->aopu.aop_lit);
5166 size = AOP_SIZE(result);
5170 if (AOP_TYPE(left) == AOP_CRY){
5171 if(AOP_TYPE(right) == AOP_LIT){
5172 // c = bit & literal;
5174 // lit>>1 != 0 => result = 1
5175 if(AOP_TYPE(result) == AOP_CRY){
5177 {emitpcode(POC_BSF, popGet(AOP(result),offset));
5178 pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
5180 continueIfTrue(ifx);
5183 pic14_emitcode("setb","c");
5187 // lit == 0, result = left
5188 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5190 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5192 // lit == 1, result = not(left)
5193 if(size && pic14_sameRegs(AOP(result),AOP(left))){
5194 emitpcode(POC_MOVLW, popGet(AOP(result),offset));
5195 emitpcode(POC_XORWF, popGet(AOP(result),offset));
5196 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5199 assert ( !"incomplete genXor" );
5200 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5201 pic14_emitcode("cpl","c");
5208 symbol *tlbl = newiTempLabel(NULL);
5209 if (AOP_TYPE(right) == AOP_CRY){
5211 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5214 int sizer = AOP_SIZE(right);
5216 // if val>>1 != 0, result = 1
5217 pic14_emitcode("setb","c");
5219 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5221 // test the msb of the lsb
5222 pic14_emitcode("anl","a,#0xfe");
5223 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5227 pic14_emitcode("rrc","a");
5229 pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5230 pic14_emitcode("cpl","c");
5231 pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
5236 pic14_outBitC(result);
5238 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5239 genIfxJump(ifx, "c");
5243 if(pic14_sameRegs(AOP(result),AOP(left))){
5244 /* if left is same as result */
5245 for(;size--; offset++) {
5246 if(AOP_TYPE(right) == AOP_LIT){
5247 int t = (lit >> (offset*8)) & 0x0FFL;
5251 emitpcode(POC_MOVLW, popGetLit(t));
5252 emitpcode(POC_XORWF,popGet(AOP(left),offset));
5255 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5256 emitpcode(POC_XORWF,popGet(AOP(left),offset));
5260 // left & result in different registers
5261 if(AOP_TYPE(result) == AOP_CRY){
5263 // if(size), result in bit
5264 // if(!size && ifx), conditional oper: if(left ^ right)
5265 symbol *tlbl = newiTempLabel(NULL);
5266 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5268 pic14_emitcode("setb","c");
5270 if((AOP_TYPE(right) == AOP_LIT) &&
5271 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5272 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
5274 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5275 pic14_emitcode("xrl","a,%s",
5276 aopGet(AOP(left),offset,FALSE,FALSE));
5278 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5283 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5284 pic14_outBitC(result);
5286 jmpTrueOrFalse(ifx, tlbl);
5287 } else for(;(size--);offset++){
5289 // result = left & right
5290 if(AOP_TYPE(right) == AOP_LIT){
5291 int t = (lit >> (offset*8)) & 0x0FFL;
5294 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5295 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5298 emitpcode(POC_COMFW,popGet(AOP(left),offset));
5299 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5302 emitpcode(POC_MOVLW, popGetLit(t));
5303 emitpcode(POC_XORFW,popGet(AOP(left),offset));
5304 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5309 // faster than result <- left, anl result,right
5310 // and better if result is SFR
5311 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5312 emitpcode(POC_XORFW,popGet(AOP(left),offset));
5313 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5318 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5319 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5320 freeAsmop(result,NULL,ic,TRUE);
5323 /*-----------------------------------------------------------------*/
5324 /* genInline - write the inline code out */
5325 /*-----------------------------------------------------------------*/
5326 static void genInline (iCode *ic)
5328 char *buffer, *bp, *bp1;
5329 bool inComment = FALSE;
5332 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5334 _G.inLine += (!options.asmpeep);
5336 buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
5351 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
5356 /* Add \n for labels, not dirs such as c:\mydir */
5357 if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
5362 /* print label, use this special format with NULL directive
5363 * to denote that the argument should not be indented with tab */
5364 addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
5372 if ((bp1 != bp) && *bp1)
5373 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
5377 _G.inLine -= (!options.asmpeep);
5380 /*-----------------------------------------------------------------*/
5381 /* genRRC - rotate right with carry */
5382 /*-----------------------------------------------------------------*/
5383 static void genRRC (iCode *ic)
5385 operand *left , *result ;
5386 int size, offset = 0, same;
5389 /* rotate right with carry */
5391 result=IC_RESULT(ic);
5392 aopOp (left,ic,FALSE);
5393 aopOp (result,ic,FALSE);
5395 DEBUGpic14_AopType(__LINE__,left,NULL,result);
5397 same = pic14_sameRegs(AOP(result),AOP(left));
5399 size = AOP_SIZE(result);
5401 /* get the lsb and put it into the carry */
5402 emitpcode(POC_RRFW, popGet(AOP(left),size-1));
5409 emitpcode(POC_RRF, popGet(AOP(left),offset));
5411 emitpcode(POC_RRFW, popGet(AOP(left),offset));
5412 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5418 freeAsmop(left,NULL,ic,TRUE);
5419 freeAsmop(result,NULL,ic,TRUE);
5422 /*-----------------------------------------------------------------*/
5423 /* genRLC - generate code for rotate left with carry */
5424 /*-----------------------------------------------------------------*/
5425 static void genRLC (iCode *ic)
5427 operand *left , *result ;
5428 int size, offset = 0;
5432 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5433 /* rotate right with carry */
5435 result=IC_RESULT(ic);
5436 aopOp (left,ic,FALSE);
5437 aopOp (result,ic,FALSE);
5439 DEBUGpic14_AopType(__LINE__,left,NULL,result);
5441 same = pic14_sameRegs(AOP(result),AOP(left));
5443 /* move it to the result */
5444 size = AOP_SIZE(result);
5446 /* get the msb and put it into the carry */
5447 emitpcode(POC_RLFW, popGet(AOP(left),size-1));
5454 emitpcode(POC_RLF, popGet(AOP(left),offset));
5456 emitpcode(POC_RLFW, popGet(AOP(left),offset));
5457 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5464 freeAsmop(left,NULL,ic,TRUE);
5465 freeAsmop(result,NULL,ic,TRUE);
5468 /*-----------------------------------------------------------------*/
5469 /* genGetHbit - generates code get highest order bit */
5470 /*-----------------------------------------------------------------*/
5471 static void genGetHbit (iCode *ic)
5473 operand *left, *result;
5475 result=IC_RESULT(ic);
5476 aopOp (left,ic,FALSE);
5477 aopOp (result,ic,FALSE);
5480 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5481 /* get the highest order byte into a */
5482 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
5483 if(AOP_TYPE(result) == AOP_CRY){
5484 pic14_emitcode("rlc","a");
5485 pic14_outBitC(result);
5488 pic14_emitcode("rl","a");
5489 pic14_emitcode("anl","a,#0x01");
5490 pic14_outAcc(result);
5494 freeAsmop(left,NULL,ic,TRUE);
5495 freeAsmop(result,NULL,ic,TRUE);
5498 /*-----------------------------------------------------------------*/
5499 /* AccLsh - shift left accumulator by known count */
5500 /* MARK: pic14 always rotates through CARRY! */
5501 /*-----------------------------------------------------------------*/
5502 static void AccLsh (pCodeOp *pcop,int shCount)
5505 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5506 shCount &= 0x0007; // shCount : 0..7
5513 emitpcode(POC_RLF,pcop);
5517 emitpcode(POC_RLF,pcop);
5518 emitpcode(POC_RLF,pcop);
5521 emitpcode(POC_RLF,pcop);
5522 emitpcode(POC_RLF,pcop);
5523 emitpcode(POC_RLF,pcop);
5526 emitpcode(POC_SWAPF,pcop);
5529 emitpcode(POC_SWAPF,pcop);
5530 emitpcode(POC_RLF,pcop);
5533 emitpcode(POC_SWAPF,pcop);
5534 emitpcode(POC_RLF,pcop);
5535 emitpcode(POC_RLF,pcop);
5538 emitpcode(POC_RRFW,pcop);
5539 emitpcode(POC_RRF,pcop);
5542 /* clear invalid bits */
5543 emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
5544 emitpcode(POC_ANDWF, pcop);
5547 /*-----------------------------------------------------------------*/
5548 /* AccRsh - shift right accumulator by known count */
5549 /* MARK: pic14 always rotates through CARRY! */
5550 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
5551 /* 1: mask out invalid bits (zero-extend) */
5552 /* 2: sign-extend result (pretty slow) */
5553 /*-----------------------------------------------------------------*/
5554 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
5557 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5558 shCount &= 0x0007; // shCount : 0..7
5564 /* load sign if needed */
5565 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
5566 else if (mask_mode == 1) emitCLRC;
5567 emitpcode(POC_RRF,pcop);
5571 /* load sign if needed */
5572 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
5573 emitpcode(POC_RRF,pcop);
5574 /* load sign if needed */
5575 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
5576 emitpcode(POC_RRF,pcop);
5577 if (mask_mode == 2) return;
5580 /* load sign if needed */
5581 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
5582 emitpcode(POC_RRF,pcop);
5583 /* load sign if needed */
5584 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
5585 emitpcode(POC_RRF,pcop);
5586 /* load sign if needed */
5587 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
5588 emitpcode(POC_RRF,pcop);
5589 if (mask_mode == 2) return;
5592 emitpcode(POC_SWAPF,pcop);
5595 emitpcode(POC_SWAPF,pcop);
5596 emitpcode(POC_RRF,pcop);
5599 emitpcode(POC_SWAPF,pcop);
5600 emitpcode(POC_RRF,pcop);
5601 emitpcode(POC_RRF,pcop);
5607 emitpcode(POC_RLFW,pcop);
5608 emitpcode(POC_CLRF,pcop);
5610 emitpcode(POC_COMF,pcop);
5613 emitpcode(POC_RLFW,pcop);
5614 emitpcode(POC_RLF,pcop);
5621 /* leave invalid bits undefined */
5625 /* clear invalid bits -- zero-extend */
5626 emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
5627 emitpcode(POC_ANDWF, pcop);
5629 if (mask_mode == 2) {
5631 emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
5632 emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
5633 emitpcode(POC_IORWF, pcop);
5638 /*-----------------------------------------------------------------*/
5639 /* AccSRsh - signed right shift accumulator by known count */
5640 /*-----------------------------------------------------------------*/
5641 static void AccSRsh (int shCount)
5644 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5647 pic14_emitcode("mov","c,acc.7");
5648 pic14_emitcode("rrc","a");
5649 } else if(shCount == 2){
5650 pic14_emitcode("mov","c,acc.7");
5651 pic14_emitcode("rrc","a");
5652 pic14_emitcode("mov","c,acc.7");
5653 pic14_emitcode("rrc","a");
5655 tlbl = newiTempLabel(NULL);
5656 /* rotate right accumulator */
5657 AccRol(8 - shCount);
5658 /* and kill the higher order bits */
5659 pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
5660 pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5661 pic14_emitcode("orl","a,#0x%02x",
5662 (unsigned char)~SRMask[shCount]);
5663 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5668 /*-----------------------------------------------------------------*/
5669 /* shiftR1Left2Result - shift right one byte from left to result */
5670 /*-----------------------------------------------------------------*/
5671 static void shiftR1Left2ResultSigned (operand *left, int offl,
5672 operand *result, int offr,
5678 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5680 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
5684 emitpcode(POC_RLFW, popGet(AOP(left),offl));
5686 emitpcode(POC_RRF, popGet(AOP(result),offr));
5688 emitpcode(POC_RRFW, popGet(AOP(left),offl));
5689 emitpcode(POC_MOVWF, popGet(AOP(result),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));
5702 emitpcode(POC_RLFW, popGet(AOP(result),offr));
5703 emitpcode(POC_RRF, popGet(AOP(result),offr));
5709 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
5711 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
5712 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5715 emitpcode(POC_RLFW, popGet(AOP(result),offr));
5716 emitpcode(POC_RLFW, popGet(AOP(result),offr));
5717 emitpcode(POC_ANDLW, popGetLit(0x1f));
5719 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
5720 emitpcode(POC_IORLW, popGetLit(0xe0));
5722 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5726 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
5727 emitpcode(POC_ANDLW, popGetLit(0x0f));
5728 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
5729 emitpcode(POC_IORLW, popGetLit(0xf0));
5730 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5734 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
5736 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
5737 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5739 emitpcode(POC_RRFW, popGet(AOP(result),offr));
5740 emitpcode(POC_ANDLW, popGetLit(0x07));
5741 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
5742 emitpcode(POC_IORLW, popGetLit(0xf8));
5743 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5748 emitpcode(POC_MOVLW, popGetLit(0x00));
5749 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
5750 emitpcode(POC_MOVLW, popGetLit(0xfe));
5751 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
5752 emitpcode(POC_IORLW, popGetLit(0x01));
5753 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5755 emitpcode(POC_CLRF, popGet(AOP(result),offr));
5756 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
5757 emitpcode(POC_DECF, popGet(AOP(result),offr));
5758 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
5759 emitpcode(POC_BCF, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
5765 emitpcode(POC_MOVLW, popGetLit(0x00));
5766 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
5767 emitpcode(POC_MOVLW, popGetLit(0xff));
5768 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5770 emitpcode(POC_CLRF, popGet(AOP(result),offr));
5771 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
5772 emitpcode(POC_DECF, popGet(AOP(result),offr));
5780 /*-----------------------------------------------------------------*/
5781 /* shiftR1Left2Result - shift right one byte from left to result */
5782 /*-----------------------------------------------------------------*/
5783 static void shiftR1Left2Result (operand *left, int offl,
5784 operand *result, int offr,
5785 int shCount, int sign)
5790 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5792 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
5794 /* Copy the msb into the carry if signed. */
5796 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
5806 emitpcode(POC_RRF, popGet(AOP(result),offr));
5808 emitpcode(POC_RRFW, popGet(AOP(left),offl));
5809 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5815 emitpcode(POC_RRF, popGet(AOP(result),offr));
5817 emitpcode(POC_RRFW, popGet(AOP(left),offl));
5818 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5821 emitpcode(POC_RRF, popGet(AOP(result),offr));
5826 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
5828 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
5829 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5832 emitpcode(POC_RLFW, popGet(AOP(result),offr));
5833 emitpcode(POC_RLFW, popGet(AOP(result),offr));
5834 emitpcode(POC_ANDLW, popGetLit(0x1f));
5835 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5839 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
5840 emitpcode(POC_ANDLW, popGetLit(0x0f));
5841 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5845 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
5846 emitpcode(POC_ANDLW, popGetLit(0x0f));
5847 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5849 emitpcode(POC_RRF, popGet(AOP(result),offr));
5854 emitpcode(POC_RLFW, popGet(AOP(left),offl));
5855 emitpcode(POC_ANDLW, popGetLit(0x80));
5856 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5857 emitpcode(POC_RLF, popGet(AOP(result),offr));
5858 emitpcode(POC_RLF, popGet(AOP(result),offr));
5863 emitpcode(POC_RLFW, popGet(AOP(left),offl));
5864 emitpcode(POC_CLRF, popGet(AOP(result),offr));
5865 emitpcode(POC_RLF, popGet(AOP(result),offr));
5874 /*-----------------------------------------------------------------*/
5875 /* shiftL1Left2Result - shift left one byte from left to result */
5876 /*-----------------------------------------------------------------*/
5877 static void shiftL1Left2Result (operand *left, int offl,
5878 operand *result, int offr, int shCount)
5884 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5886 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
5887 DEBUGpic14_emitcode ("; ***","same = %d",same);
5888 // l = aopGet(AOP(left),offl,FALSE,FALSE);
5890 /* shift left accumulator */
5891 //AccLsh(shCount); // don't comment out just yet...
5892 // aopPut(AOP(result),"a",offr);
5896 /* Shift left 1 bit position */
5897 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
5899 emitpcode(POC_ADDWF, popGet(AOP(left),offl));
5901 emitpcode(POC_ADDFW, popGet(AOP(left),offl));
5902 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5906 emitpcode(POC_RLFW, popGet(AOP(left),offl));
5907 emitpcode(POC_ANDLW,popGetLit(0x7e));
5908 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
5909 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
5912 emitpcode(POC_RLFW, popGet(AOP(left),offl));
5913 emitpcode(POC_ANDLW,popGetLit(0x3e));
5914 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
5915 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
5916 emitpcode(POC_RLF, popGet(AOP(result),offr));
5919 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
5920 emitpcode(POC_ANDLW, popGetLit(0xf0));
5921 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
5924 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
5925 emitpcode(POC_ANDLW, popGetLit(0xf0));
5926 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
5927 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
5930 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
5931 emitpcode(POC_ANDLW, popGetLit(0x30));
5932 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
5933 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
5934 emitpcode(POC_RLF, popGet(AOP(result),offr));
5937 emitpcode(POC_RRFW, popGet(AOP(left),offl));
5938 emitpcode(POC_CLRF, popGet(AOP(result),offr));
5939 emitpcode(POC_RRF, popGet(AOP(result),offr));
5943 DEBUGpic14_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
5949 /*-----------------------------------------------------------------*/
5950 /* movLeft2Result - move byte from left to result */
5951 /*-----------------------------------------------------------------*/
5952 static void movLeft2Result (operand *left, int offl,
5953 operand *result, int offr)
5956 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5957 if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5958 aopGet(AOP(left),offl,FALSE,FALSE);
5960 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
5961 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5965 /*-----------------------------------------------------------------*/
5966 /* shiftLeft_Left2ResultLit - shift left by known count */
5967 /*-----------------------------------------------------------------*/
5969 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
5971 int size, same, offr, i;
5973 size = AOP_SIZE(left);
5974 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
5976 same = pic14_sameRegs (AOP(left), AOP(result));
5979 shCount = shCount & 0x07;
5985 case 0: /* takes 0 or 2N cycles (for offr==0) */
5986 if (!same || offr) {
5987 for (i=size-1; i >= 0; i--)
5988 movLeft2Result (left, i, result, offr + i);
5992 case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
5994 shiftLeft_Left2ResultLit (left, result, 8 * offr);
5995 shiftLeft_Left2ResultLit (result, result, shCount);
5996 return; /* prevent clearing result again */
5999 for (i=0; i < size; i++) {
6000 if (same && !offr) {
6001 emitpcode (POC_RLF, popGet (AOP(left), i));
6003 emitpcode (POC_RLFW, popGet (AOP(left), i));
6004 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6010 case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
6011 /* works in-place/with offr as well */
6012 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
6013 emitpcode (POC_ANDLW, popGetLit (0xF0));
6014 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
6016 for (i = size - 2; i >= 0; i--)
6018 emitpcode (POC_SWAPFW, popGet (AOP(left), i));
6019 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6020 emitpcode (POC_ANDLW, popGetLit (0x0F));
6021 emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
6022 emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
6026 case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
6027 /* works in-place/with offr as well */
6028 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
6029 for (i = size-2; i >= 0; i--) {
6030 emitpcode (POC_RRFW, popGet (AOP(left), i));
6031 emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
6033 emitpcode (POC_CLRF, popGet (AOP(result), offr));
6034 emitpcode (POC_RRF, popGet (AOP(result), offr));
6038 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
6039 shiftLeft_Left2ResultLit (result, result, 1);
6040 return; /* prevent clearing result again */
6046 emitpcode (POC_CLRF, popGet (AOP(result), offr));
6050 /*-----------------------------------------------------------------*/
6051 /* shiftRight_Left2ResultLit - shift right by known count */
6052 /*-----------------------------------------------------------------*/
6054 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
6056 int size, same, offr, i;
6058 size = AOP_SIZE(left);
6059 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6061 same = pic14_sameRegs (AOP(left), AOP(result));
6064 shCount = shCount & 0x07;
6072 case 0: /* takes 0 or 2N cycles (for offr==0) */
6073 if (!same || offr) {
6074 for (i=0; i < size; i++)
6075 movLeft2Result (left, i + offr, result, i);
6079 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
6080 emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
6082 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
6083 shiftRight_Left2ResultLit (result, result, shCount, sign);
6084 return; /* prevent sign-extending result again */
6088 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
6091 for (i = size-1; i >= 0; i--) {
6092 if (same && !offr) {
6093 emitpcode (POC_RRF, popGet (AOP(left), i));
6095 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
6096 emitpcode (POC_MOVWF, popGet (AOP(result), i));
6102 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
6103 /* works in-place/with offr as well */
6104 emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
6105 emitpcode (POC_ANDLW, popGetLit (0x0F));
6106 emitpcode (POC_MOVWF, popGet(AOP(result), 0));
6108 for (i = 1; i < size; i++)
6110 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
6111 emitpcode (POC_MOVWF, popGet (AOP(result), i));
6112 emitpcode (POC_ANDLW, popGetLit (0xF0));
6113 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
6114 emitpcode (POC_XORWF, popGet (AOP(result), i));
6119 emitpcode (POC_MOVLW, popGetLit (0xF0));
6120 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
6121 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
6125 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
6126 /* works in-place/with offr as well */
6127 emitpcode (POC_RLFW, popGet (AOP(left), offr));
6128 for (i = 0; i < size-1; i++) {
6129 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
6130 emitpcode (POC_MOVWF, popGet (AOP(result), i));
6132 emitpcode (POC_CLRF, popGet (AOP(result), size-1));
6134 emitpcode (POC_RLF, popGet (AOP(result), size-1));
6137 emitpcode (POC_DECF, popGet (AOP(result), size-1));
6142 shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
6143 shiftRight_Left2ResultLit (result, result, 1, sign);
6144 return; /* prevent sign extending result again */
6149 addSign (result, size, sign);
6153 /*-----------------------------------------------------------------*/
6154 /* shiftL2Left2Result - shift left two bytes from left to result */
6155 /*-----------------------------------------------------------------*/
6156 static void shiftL2Left2Result (operand *left, int offl,
6157 operand *result, int offr, int shCount)
6161 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6163 if(pic14_sameRegs(AOP(result), AOP(left))) {
6171 emitpcode(POC_MOVFW,popGet(AOP(result),offr));
6172 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6173 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6177 emitpcode(POC_RLF, popGet(AOP(result),offr));
6178 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6184 emitpcode(POC_MOVLW, popGetLit(0x0f));
6185 emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
6186 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6187 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6188 emitpcode(POC_ANDFW, popGet(AOP(result),offr));
6189 emitpcode(POC_XORWF, popGet(AOP(result),offr));
6190 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6192 emitpcode(POC_RLF, popGet(AOP(result),offr));
6193 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6197 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6198 emitpcode(POC_RRF, popGet(AOP(result),offr));
6199 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6200 emitpcode(POC_RRF, popGet(AOP(result),offr));
6201 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6202 emitpcode(POC_ANDLW,popGetLit(0xc0));
6203 emitpcode(POC_XORFW,popGet(AOP(result),offr));
6204 emitpcode(POC_XORWF,popGet(AOP(result),offr));
6205 emitpcode(POC_XORFW,popGet(AOP(result),offr));
6206 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6209 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6210 emitpcode(POC_RRFW, popGet(AOP(result),offr));
6211 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6212 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6213 emitpcode(POC_RRF, popGet(AOP(result),offr));
6223 /* note, use a mov/add for the shift since the mov has a
6224 chance of getting optimized out */
6225 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6226 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6227 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6228 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6229 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6233 emitpcode(POC_RLF, popGet(AOP(result),offr));
6234 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6240 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6241 emitpcode(POC_ANDLW, popGetLit(0xF0));
6242 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6243 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6244 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6245 emitpcode(POC_ANDLW, popGetLit(0xF0));
6246 emitpcode(POC_XORWF, popGet(AOP(result),offr));
6247 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6251 emitpcode(POC_RLF, popGet(AOP(result),offr));
6252 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6256 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6257 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6258 emitpcode(POC_RRFW, popGet(AOP(result),offl));
6259 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6261 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6262 emitpcode(POC_RRF, popGet(AOP(result),offr));
6263 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6264 emitpcode(POC_ANDLW,popGetLit(0xc0));
6265 emitpcode(POC_XORFW,popGet(AOP(result),offr));
6266 emitpcode(POC_XORWF,popGet(AOP(result),offr));
6267 emitpcode(POC_XORFW,popGet(AOP(result),offr));
6268 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6271 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6272 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6273 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6274 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6275 emitpcode(POC_RRF, popGet(AOP(result),offr));
6281 /*-----------------------------------------------------------------*/
6282 /* shiftR2Left2Result - shift right two bytes from left to result */
6283 /*-----------------------------------------------------------------*/
6284 static void shiftR2Left2Result (operand *left, int offl,
6285 operand *result, int offr,
6286 int shCount, int sign)
6291 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6292 same = pic14_sameRegs(AOP(result), AOP(left));
6294 if(same && ((offl + MSB16) == offr)){
6296 /* don't crash result[offr] */
6297 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6298 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6301 movLeft2Result(left,offl, result, offr);
6302 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6305 /* a:x >> shCount (x = lsb(result))*/
6308 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6310 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6319 emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
6324 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6325 emitpcode(POC_RRF,popGet(AOP(result),offr));
6327 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6328 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6329 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6330 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6335 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
6338 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6339 emitpcode(POC_RRF,popGet(AOP(result),offr));
6346 emitpcode(POC_MOVLW, popGetLit(0xf0));
6347 emitpcode(POC_ANDWF, popGet(AOP(result),offr));
6348 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6350 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6351 emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
6352 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6353 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6355 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6356 emitpcode(POC_ANDLW, popGetLit(0x0f));
6357 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6359 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6360 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6361 emitpcode(POC_ANDLW, popGetLit(0xf0));
6362 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6363 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6367 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6368 emitpcode(POC_RRF, popGet(AOP(result),offr));
6372 emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
6373 emitpcode(POC_BTFSC,
6374 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
6375 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6383 emitpcode(POC_RLF, popGet(AOP(result),offr));
6384 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6386 emitpcode(POC_RLF, popGet(AOP(result),offr));
6387 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6388 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6389 emitpcode(POC_ANDLW,popGetLit(0x03));
6391 emitpcode(POC_BTFSC,
6392 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
6393 emitpcode(POC_IORLW,popGetLit(0xfc));
6395 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6396 emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
6397 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6398 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6400 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6401 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6402 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6403 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6404 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6405 emitpcode(POC_RLF, popGet(AOP(result),offr));
6406 emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
6407 emitpcode(POC_ANDLW,popGetLit(0x03));
6409 emitpcode(POC_BTFSC,
6410 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
6411 emitpcode(POC_IORLW,popGetLit(0xfc));
6413 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6414 //emitpcode(POC_RLF, popGet(AOP(result),offr));
6421 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6422 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6423 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6424 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
6427 emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
6429 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6433 /*-----------------------------------------------------------------*/
6434 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
6435 /*-----------------------------------------------------------------*/
6436 static void shiftLLeftOrResult (operand *left, int offl,
6437 operand *result, int offr, int shCount)
6440 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6442 /* shift left accumulator */
6443 AccLsh(left,offl,shCount);
6444 /* or with result */
6445 emitpcode (POC_IORWF, popGet (AOP(result), offr));
6446 assert ( !"broken (modifies left, fails for left==result))" );
6449 /*-----------------------------------------------------------------*/
6450 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
6451 /*-----------------------------------------------------------------*/
6452 static void shiftRLeftOrResult (operand *left, int offl,
6453 operand *result, int offr, int shCount)
6456 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6458 /* shift right accumulator */
6459 AccRsh(left,offl,shCount);
6460 /* or with result */
6461 emitpcode (POC_IORWF, popGet (AOP(result), offr));
6462 assert ( !"broken (modifies left, fails for left==result))" );
6465 /*-----------------------------------------------------------------*/
6466 /* genlshOne - left shift a one byte quantity by known count */
6467 /*-----------------------------------------------------------------*/
6468 static void genlshOne (operand *result, operand *left, int shCount)
6471 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6472 shiftL1Left2Result(left, LSB, result, LSB, shCount);
6475 /*-----------------------------------------------------------------*/
6476 /* genlshTwo - left shift two bytes by known amount != 0 */
6477 /*-----------------------------------------------------------------*/
6478 static void genlshTwo (operand *result,operand *left, int shCount)
6483 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6484 size = pic14_getDataSize(result);
6486 /* if shCount >= 8 */
6492 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6494 movLeft2Result(left, LSB, result, MSB16);
6496 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
6499 /* 1 <= shCount <= 7 */
6502 shiftL1Left2Result(left, LSB, result, LSB, shCount);
6504 shiftL2Left2Result(left, LSB, result, LSB, shCount);
6508 /*-----------------------------------------------------------------*/
6509 /* shiftLLong - shift left one long from left to result */
6510 /* offl = LSB or MSB16 */
6511 /*-----------------------------------------------------------------*/
6512 static void shiftLLong (operand *left, operand *result, int offr )
6515 int size = AOP_SIZE(result);
6518 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6519 if(size >= LSB+offr){
6520 l = aopGet(AOP(left),LSB,FALSE,FALSE);
6522 pic14_emitcode("add","a,acc");
6523 if (pic14_sameRegs(AOP(left),AOP(result)) &&
6524 size >= MSB16+offr && offr != LSB )
6525 pic14_emitcode("xch","a,%s",
6526 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
6528 aopPut(AOP(result),"a",LSB+offr);
6531 if(size >= MSB16+offr){
6532 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6533 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
6536 pic14_emitcode("rlc","a");
6537 if (pic14_sameRegs(AOP(left),AOP(result)) &&
6538 size >= MSB24+offr && offr != LSB)
6539 pic14_emitcode("xch","a,%s",
6540 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
6542 aopPut(AOP(result),"a",MSB16+offr);
6545 if(size >= MSB24+offr){
6546 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
6547 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
6550 pic14_emitcode("rlc","a");
6551 if (pic14_sameRegs(AOP(left),AOP(result)) &&
6552 size >= MSB32+offr && offr != LSB )
6553 pic14_emitcode("xch","a,%s",
6554 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
6556 aopPut(AOP(result),"a",MSB24+offr);
6559 if(size > MSB32+offr){
6560 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
6561 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
6564 pic14_emitcode("rlc","a");
6565 aopPut(AOP(result),"a",MSB32+offr);
6568 aopPut(AOP(result),zero,LSB);
6571 /*-----------------------------------------------------------------*/
6572 /* genlshFour - shift four byte by a known amount != 0 */
6573 /*-----------------------------------------------------------------*/
6574 static void genlshFour (operand *result, operand *left, int shCount)
6579 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6580 size = AOP_SIZE(result);
6582 /* if shifting more that 3 bytes */
6583 if (shCount >= 24 ) {
6586 /* lowest order of left goes to the highest
6587 order of the destination */
6588 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6590 movLeft2Result(left, LSB, result, MSB32);
6591 aopPut(AOP(result),zero,LSB);
6592 aopPut(AOP(result),zero,MSB16);
6593 aopPut(AOP(result),zero,MSB32);
6597 /* more than two bytes */
6598 else if ( shCount >= 16 ) {
6599 /* lower order two bytes goes to higher order two bytes */
6601 /* if some more remaining */
6603 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6605 movLeft2Result(left, MSB16, result, MSB32);
6606 movLeft2Result(left, LSB, result, MSB24);
6608 aopPut(AOP(result),zero,MSB16);
6609 aopPut(AOP(result),zero,LSB);
6613 /* if more than 1 byte */
6614 else if ( shCount >= 8 ) {
6615 /* lower order three bytes goes to higher order three bytes */
6619 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6621 movLeft2Result(left, LSB, result, MSB16);
6623 else{ /* size = 4 */
6625 movLeft2Result(left, MSB24, result, MSB32);
6626 movLeft2Result(left, MSB16, result, MSB24);
6627 movLeft2Result(left, LSB, result, MSB16);
6628 aopPut(AOP(result),zero,LSB);
6630 else if(shCount == 1)
6631 shiftLLong(left, result, MSB16);
6633 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
6634 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6635 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6636 aopPut(AOP(result),zero,LSB);
6641 /* 1 <= shCount <= 7 */
6642 else if(shCount <= 2){
6643 shiftLLong(left, result, LSB);
6645 shiftLLong(result, result, LSB);
6647 /* 3 <= shCount <= 7, optimize */
6649 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6650 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6651 shiftL2Left2Result(left, LSB, result, LSB, shCount);
6657 /*-----------------------------------------------------------------*/
6658 /* genLeftShiftLiteral - left shifting by known count */
6659 /*-----------------------------------------------------------------*/
6660 static void genLeftShiftLiteral (operand *left,
6665 int shCount = (int) ulFromVal (AOP(right)->aopu.aop_lit);
6669 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6670 freeAsmop(right,NULL,ic,TRUE);
6672 aopOp(left,ic,FALSE);
6673 aopOp(result,ic,FALSE);
6675 size = getSize(operandType(result));
6678 pic14_emitcode("; shift left ","result %d, left %d",size,
6682 /* I suppose that the left size >= result size */
6685 movLeft2Result(left, size, result, size);
6689 else if(shCount >= (size * 8))
6691 aopPut(AOP(result),zero,size);
6695 genlshOne (result,left,shCount);
6700 genlshTwo (result,left,shCount);
6704 genlshFour (result,left,shCount);
6708 freeAsmop(left,NULL,ic,TRUE);
6709 freeAsmop(result,NULL,ic,TRUE);
6713 /*-----------------------------------------------------------------*
6714 * genMultiAsm - repeat assembly instruction for size of register.
6715 * if endian == 1, then the high byte (i.e base address + size of
6716 * register) is used first else the low byte is used first;
6717 *-----------------------------------------------------------------*/
6718 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
6724 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6737 emitpcode(poc, popGet(AOP(reg),offset));
6743 /*-----------------------------------------------------------------*/
6744 /* loadSignToC - load the operand's sign bit into CARRY */
6745 /*-----------------------------------------------------------------*/
6747 static void loadSignToC (operand *op)
6750 assert (op && AOP(op) && AOP_SIZE(op));
6753 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
6757 /*-----------------------------------------------------------------*/
6758 /* genRightShift - generate code for right shifting */
6759 /*-----------------------------------------------------------------*/
6760 static void genGenericShift (iCode *ic, int shiftRight)
6762 operand *right, *left, *result;
6765 symbol *tlbl, *tlbl1, *inverselbl;
6768 /* if signed then we do it the hard way preserve the
6769 sign bit moving it inwards */
6770 retype = getSpec(operandType(IC_RESULT(ic)));
6771 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6773 /* signed & unsigned types are treated the same : i.e. the
6774 signed is NOT propagated inwards : quoting from the
6775 ANSI - standard : "for E1 >> E2, is equivalent to division
6776 by 2**E2 if unsigned or if it has a non-negative value,
6777 otherwise the result is implementation defined ", MY definition
6778 is that the sign does not get propagated */
6780 right = IC_RIGHT(ic);
6782 result = IC_RESULT(ic);
6784 aopOp(right,ic,FALSE);
6785 aopOp(left,ic,FALSE);
6786 aopOp(result,ic,FALSE);
6788 /* if the shift count is known then do it
6789 as efficiently as possible */
6790 if (AOP_TYPE(right) == AOP_LIT) {
6791 int lit = (int) ulFromVal (AOP(right)->aopu.aop_lit);
6795 shiftRight = !shiftRight;
6799 shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
6801 shiftLeft_Left2ResultLit (left, result, lit);
6802 //genRightShiftLiteral (left,right,result,ic, 0);
6806 /* shift count is unknown then we have to form
6807 a loop get the loop count in B : Note: we take
6808 only the lower order byte since shifting
6809 more that 32 bits make no sense anyway, ( the
6810 largest size of an object can be only 32 bits ) */
6812 /* we must not overwrite the shift counter */
6813 assert (!pic14_sameRegs(AOP(right),AOP(result)));
6815 /* now move the left to the result if they are not the
6817 if (!pic14_sameRegs(AOP(left),AOP(result)))
6819 size = min(AOP_SIZE(result), AOP_SIZE(left));
6821 mov2w(AOP(left), size);
6822 movwf(AOP(result), size);
6824 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
6827 tlbl = newiTempLabel(NULL);
6828 tlbl1= newiTempLabel(NULL);
6830 size = AOP_SIZE(result);
6832 mov2w(AOP(right),0);
6833 if (!SPEC_USIGN(operandType(right)))
6835 inverselbl = newiTempLabel(NULL);
6836 /* signed shift count -- invert shift direction for c<0 */
6837 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
6838 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
6840 emitpcode(POC_SUBLW, popGetLit(0)); /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
6841 /* check for `a = b >> c' with `-c == 0' */
6843 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
6844 emitpLabel(tlbl->key);
6845 /* propagate the sign bit inwards for SIGNED result */
6846 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
6847 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
6848 emitpcode(POC_ADDLW, popGetLit(1)); /* clears CARRY (unless W==0 afterwards) */
6850 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
6852 if (!SPEC_USIGN(operandType(right)))
6854 symbol *inv_loop = newiTempLabel(NULL);
6856 shiftRight = !shiftRight; /* invert shift direction */
6858 /* we came here from the code above -- we are done */
6859 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
6861 /* emit code for shifting N<0 steps, count is already in W */
6862 emitpLabel(inverselbl->key);
6863 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
6864 emitpLabel(inv_loop->key);
6865 /* propagate the sign bit inwards for SIGNED result */
6866 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
6867 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
6868 emitpcode(POC_ADDLW, popGetLit(1));
6870 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
6873 emitpLabel(tlbl1->key);
6875 freeAsmop(left,NULL,ic,TRUE);
6876 freeAsmop (right,NULL,ic,TRUE);
6877 freeAsmop(result,NULL,ic,TRUE);
6880 static void genRightShift (iCode *ic)
6882 genGenericShift(ic, 1);
6885 static void genLeftShift (iCode *ic)
6887 genGenericShift(ic, 0);
6890 /*-----------------------------------------------------------------*/
6891 /* SetIrp - Set IRP bit */
6892 /*-----------------------------------------------------------------*/
6893 void SetIrp(operand *result) {
6895 if (AOP_TYPE(result) == AOP_LIT) {
6896 unsigned lit = (unsigned) double2ul (operandLitValue(result));
6902 if ((AOP_TYPE(result) == AOP_PCODE)
6903 && (AOP(result)->aopu.pcop->type == PO_LITERAL))
6905 int addrs = PCOL(AOP(result)->aopu.pcop)->lit;
6911 emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
6912 if(AOP_SIZE(result) > 1) {
6913 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
6921 setup_fsr (operand *ptr)
6924 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
6926 /* also setup-up IRP */
6930 /*-----------------------------------------------------------------*/
6931 /* emitPtrByteGet - emits code to get a byte into WREG from an */
6932 /* arbitrary pointer (__code, __data, generic) */
6933 /*-----------------------------------------------------------------*/
6935 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
6942 if (!alreadyAddressed) setup_fsr (src);
6943 emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
6947 assert( AOP_SIZE(src) == 2 );
6949 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
6951 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
6952 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
6953 call_libraryfunc ("__gptrget1");
6957 assert( AOP_SIZE(src) == 3 );
6959 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
6961 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
6963 call_libraryfunc ("__gptrget1");
6967 assert( !"unhandled pointer type" );
6972 /*-----------------------------------------------------------------*/
6973 /* emitPtrByteSet - emits code to set a byte from src through a */
6974 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR). */
6975 /*-----------------------------------------------------------------*/
6977 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
6984 if (!alreadyAddressed) setup_fsr (dst);
6985 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
6989 assert( !"trying to assign to __code pointer" );
6993 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
6995 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
6997 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
6999 call_libraryfunc ("__gptrput1");
7003 assert( !"unhandled pointer type" );
7008 /*-----------------------------------------------------------------*/
7009 /* genUnpackBits - generates code for unpacking bits */
7010 /*-----------------------------------------------------------------*/
7011 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
7013 int rsize; /* result size */
7014 sym_link *etype; /* bitfield type information */
7015 int blen; /* bitfield length */
7016 int bstr; /* bitfield starting bit within byte */
7019 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7020 etype = getSpec(operandType(result));
7021 rsize = getSize (operandType (result));
7022 blen = SPEC_BLEN (etype);
7023 bstr = SPEC_BSTR (etype);
7025 /* single bit field case */
7027 if (ifx) { /* that is for an if statement */
7030 resolveIfx(&rIfx,ifx);
7031 if (ptype == -1) /* direct */
7032 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
7034 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
7035 emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
7036 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
7040 assert (!pic14_sameRegs (AOP(result), AOP(left)));
7041 for (i=0; i < AOP_SIZE(result); i++)
7042 emitpcode (POC_CLRF, popGet (AOP(result), i));
7047 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
7048 /* adjust result below */
7055 emitPtrByteGet (left, ptype, FALSE);
7056 emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
7058 /* adjust result below */
7062 assert( !"unhandled pointer type" );
7065 /* move sign-/zero extended bit to result */
7066 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
7067 emitpcode (POC_INCF, popGet (AOP(result), 0));
7069 emitpcode (POC_DECF, popGet (AOP(result), 0));
7071 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
7075 else if (blen <= 8 && ((blen + bstr) <= 8))
7080 for (i=0; i < AOP_SIZE(result); i++)
7081 emitpcode (POC_CLRF, popGet (AOP(result), i));
7086 mov2w(AOP(left), 0);
7093 emitPtrByteGet (left, ptype, FALSE);
7097 assert( !"unhandled pointer type" );
7101 emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
7102 movwf(AOP(result), 0);
7103 AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
7105 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
7107 /* signed bitfield */
7108 assert (bstr + blen > 0);
7109 emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
7110 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
7111 emitpcode(POC_IORWF, popGet(AOP(result),0));
7113 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
7117 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
7121 /*-----------------------------------------------------------------*/
7122 /* genDataPointerGet - generates code when ptr offset is known */
7123 /*-----------------------------------------------------------------*/
7124 static void genDataPointerGet (operand *left,
7128 int size , offset = 0;
7131 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7134 /* optimization - most of the time, left and result are the same
7135 * address, but different types. for the pic code, we could omit
7138 aopOp(result,ic,TRUE);
7140 if (pic14_sameRegs (AOP(left), AOP(result)))
7143 DEBUGpic14_AopType(__LINE__,left,NULL,result);
7145 //emitpcode(POC_MOVFW, popGet(AOP(left),0));
7147 size = AOP_SIZE(result);
7148 if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
7152 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
7153 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7157 freeAsmop(left,NULL,ic,TRUE);
7158 freeAsmop(result,NULL,ic,TRUE);
7162 /*-----------------------------------------------------------------*/
7163 /* genNearPointerGet - pic14_emitcode for near pointer fetch */
7164 /*-----------------------------------------------------------------*/
7165 static void genNearPointerGet (operand *left,
7170 sym_link *ltype = operandType(left);
7171 sym_link *rtype = operandType(result);
7172 sym_link *retype= getSpec(rtype); /* bitfield type information */
7176 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7179 aopOp(left,ic,FALSE);
7181 /* if left is rematerialisable and
7182 result is not bit variable type and
7183 the left is pointer to data space i.e
7184 lower 128 bytes of space */
7185 if (AOP_TYPE(left) == AOP_PCODE && //AOP_TYPE(left) == AOP_IMMD &&
7186 !IS_BITVAR(retype) &&
7187 PIC_IS_DATA_PTR(ltype)) {
7188 genDataPointerGet (left,result,ic);
7192 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7193 aopOp (result,ic,FALSE);
7195 /* Check if can access directly instead of via a pointer */
7196 if ((AOP_TYPE(left) == AOP_PCODE)
7197 && (AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
7198 && (AOP_SIZE(result) == 1))
7203 if (IS_BITFIELD(getSpec(operandType(result))))
7205 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
7209 /* If the pointer value is not in a the FSR then need to put it in */
7210 /* Must set/reset IRP bit for use with FSR. */
7215 /* if bitfield then unpack the bits */
7217 /* we have can just get the values */
7218 int size = AOP_SIZE(result);
7221 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7225 emitpcode(POC_MOVWF,popGet(AOP(left),0));
7227 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
7228 if (AOP_TYPE(result) == AOP_LIT) {
7229 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
7231 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
7233 if (size && !direct)
7234 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
7239 /* now some housekeeping stuff */
7241 /* we had to allocate for this iCode */
7242 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7243 freeAsmop(NULL,aop,ic,TRUE);
7245 /* we did not allocate which means left
7246 already in a pointer register, then
7247 if size > 0 && this could be used again
7248 we have to point it back to where it
7250 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7251 if (AOP_SIZE(result) > 1 &&
7252 !OP_SYMBOL(left)->remat &&
7253 ( OP_SYMBOL(left)->liveTo > ic->seq ||
7255 int size = AOP_SIZE(result) - 1;
7257 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
7263 freeAsmop(left,NULL,ic,TRUE);
7264 freeAsmop(result,NULL,ic,TRUE);
7268 /*-----------------------------------------------------------------*/
7269 /* genGenPointerGet - gget value from generic pointer space */
7270 /*-----------------------------------------------------------------*/
7271 static void genGenPointerGet (operand *left,
7272 operand *result, iCode *ic)
7275 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7276 aopOp(left,ic,FALSE);
7277 aopOp(result,ic,FALSE);
7280 DEBUGpic14_AopType(__LINE__,left,NULL,result);
7282 if (IS_BITFIELD(getSpec(operandType(result))))
7284 genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
7289 /* emit call to __gptrget */
7290 char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
7291 int size = AOP_SIZE(result);
7294 assert (size > 0 && size <= 4);
7296 /* pass arguments */
7297 assert (AOP_SIZE(left) == 3);
7298 mov2w(AOP(left), 0);
7299 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
7300 mov2w(AOP(left), 1);
7301 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
7302 mov2w(AOP(left), 2);
7303 call_libraryfunc (func[size]);
7306 movwf (AOP(result), --size);
7308 emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
7309 movwf (AOP(result), size);
7313 freeAsmop(left,NULL,ic,TRUE);
7314 freeAsmop(result,NULL,ic,TRUE);
7318 /*-----------------------------------------------------------------*/
7319 /* genConstPointerGet - get value from const generic pointer space */
7320 /*-----------------------------------------------------------------*/
7321 static void genConstPointerGet (operand *left,
7322 operand *result, iCode *ic)
7324 //sym_link *retype = getSpec(operandType(result));
7326 symbol *albl, *blbl;//, *clbl;
7333 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7334 aopOp(left,ic,FALSE);
7335 aopOp(result,ic,FALSE);
7337 size = AOP_SIZE(result);
7339 DEBUGpic14_AopType(__LINE__,left,NULL,result);
7341 DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
7343 lit = op_isLitLike (left);
7344 poc = lit ? POC_MOVLW : POC_MOVFW;
7346 if (IS_BITFIELD(getSpec(operandType(result))))
7348 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
7353 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
7354 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
7355 assert (size > 0 && size <= 4);
7358 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
7360 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
7361 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
7362 call_libraryfunc (func[size]);
7364 movwf(AOP(result),size-1);
7365 for (i = 1; i < size; i++)
7367 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
7368 movwf(AOP(result),size - 1 - i);
7373 freeAsmop(left,NULL,ic,TRUE);
7374 freeAsmop(result,NULL,ic,TRUE);
7377 /*-----------------------------------------------------------------*/
7378 /* genPointerGet - generate code for pointer get */
7379 /*-----------------------------------------------------------------*/
7380 static void genPointerGet (iCode *ic)
7382 operand *left, *result ;
7383 sym_link *type, *etype;
7387 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7390 result = IC_RESULT(ic) ;
7392 /* depending on the type of pointer we need to
7393 move it to the correct pointer register */
7394 type = operandType(left);
7395 etype = getSpec(type);
7397 if (IS_PTR_CONST(type))
7398 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
7400 /* if left is of type of pointer then it is simple */
7401 if (IS_PTR(type) && !IS_FUNC(type->next))
7402 p_type = DCL_TYPE(type);
7404 /* we have to go by the storage class */
7405 p_type = PTR_TYPE(SPEC_OCLS(etype));
7407 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
7409 if (SPEC_OCLS(etype)->codesp ) {
7410 DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
7411 //p_type = CPOINTER ;
7414 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
7415 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
7416 /*p_type = FPOINTER ;*/
7418 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
7419 DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
7420 /* p_type = PPOINTER; */
7422 if (SPEC_OCLS(etype) == idata )
7423 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
7424 /* p_type = IPOINTER; */
7426 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
7427 /* p_type = POINTER ; */
7430 /* now that we have the pointer type we assign
7431 the pointer values */
7437 genNearPointerGet (left,result,ic);
7441 genPagedPointerGet(left,result,ic);
7445 genFarPointerGet (left,result,ic);
7449 genConstPointerGet (left,result,ic);
7453 genGenPointerGet (left,result,ic);
7456 assert ( !"unhandled pointer type" );
7462 /*-----------------------------------------------------------------*/
7463 /* genPackBits - generates code for packed bit storage */
7464 /*-----------------------------------------------------------------*/
7465 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
7467 int blen; /* bitfield length */
7468 int bstr; /* bitfield starting bit within byte */
7469 int litval; /* source literal value (if AOP_LIT) */
7470 unsigned char mask; /* bitmask within current byte */
7473 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7475 blen = SPEC_BLEN (etype);
7476 bstr = SPEC_BSTR (etype);
7478 /* If the bitfield length is less than a byte and does not cross byte boundaries */
7479 if ((blen <= 8) && ((bstr + blen) <= 8))
7481 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7482 (unsigned char) (0xFF >> (8 - bstr)));
7484 if (AOP_TYPE (right) == AOP_LIT)
7486 /* Case with a bitfield length <8 and literal source */
7487 int lit = (int) ulFromVal (AOP (right)->aopu.aop_lit);
7494 if (AOP(result)->type == AOP_PCODE)
7495 pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
7497 pcop = popGet(AOP(result),0);
7498 emitpcode(lit?POC_BSF:POC_BCF,pcop);
7504 emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
7508 assert( !"trying to assign to bitfield via pointer to __code space" );
7512 emitPtrByteGet(result, p_type, FALSE);
7514 emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
7516 emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
7518 emitPtrByteSet(result, p_type, TRUE);
7522 assert( !"unhandled pointer type" );
7524 } // switch (p_type)
7527 litval = lit << bstr;
7528 litval &= (~mask) & 0x00ff;
7533 mov2w (AOP(result), 0);
7534 if ((litval|mask) != 0x00ff)
7535 emitpcode(POC_ANDLW, popGetLit (mask));
7537 emitpcode(POC_IORLW, popGetLit (litval));
7538 movwf (AOP(result), 0);
7544 emitPtrByteGet(result, p_type, FALSE);
7545 if ((litval|mask) != 0x00ff)
7546 emitpcode(POC_ANDLW, popGetLit (mask));
7548 emitpcode(POC_IORLW, popGetLit (litval));
7549 emitPtrByteSet(result, p_type, TRUE);
7553 assert( !"trying to assign to bitfield via pointer to __code space" );
7557 assert( !"unhandled pointer type" );
7564 /* right is no literal */
7569 /* Note more efficient code, of pre clearing bit then only setting it if required,
7570 * can only be done if it is known that the result is not a SFR */
7571 emitpcode(POC_RRFW,popGet(AOP(right),0));
7573 emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
7575 emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
7581 emitPtrByteGet (result, p_type, FALSE);
7582 emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
7583 emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
7584 emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
7585 emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
7586 emitPtrByteSet (result, p_type, TRUE);
7590 assert( !"trying to assign to bitfield via pointer to __code space" );
7594 assert( !"unhandled pointer type" );
7599 /* Case with a bitfield 1 < length <= 8 and arbitrary source */
7600 pCodeOp *temp = popGetTempReg ();
7602 mov2w (AOP(right), 0);
7604 emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
7606 emitpcode(POC_MOVWF, temp);
7608 AccLsh (temp, bstr);
7614 mov2w (AOP(result), 0);
7615 emitpcode(POC_ANDLW, popGetLit (mask));
7616 emitpcode(POC_IORFW, temp);
7617 movwf (AOP(result), 0);
7623 emitPtrByteGet (result, p_type, FALSE);
7624 emitpcode(POC_ANDLW, popGetLit (mask));
7625 emitpcode(POC_IORFW, temp);
7626 emitPtrByteSet (result, p_type, TRUE);
7630 assert( !"trying to assign to bitfield via pointer to __code space" );
7634 assert( !"unhandled pointer type" );
7638 popReleaseTempReg (temp);
7640 } // if (AOP(right)->type != AOP_LIT)
7642 } // if (blen <= 8 && ((blen + bstr) <= 8))
7644 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
7647 /*-----------------------------------------------------------------*/
7648 /* genDataPointerSet - remat pointer to data space */
7649 /*-----------------------------------------------------------------*/
7650 static void genDataPointerSet(operand *right,
7654 int size, offset = 0 ;
7658 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7659 aopOp(right,ic,FALSE);
7660 aopOp(result,ic,FALSE);
7662 assert (IS_SYMOP(result));
7663 assert (IS_PTR(OP_SYM_TYPE(result)));
7665 if (AOP_TYPE(right) == AOP_LIT)
7668 size = AOP_SIZE(right);
7669 ressize = getSize(OP_SYM_ETYPE(result));
7670 if (size > ressize) size = ressize;
7671 //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
7673 //assert( !"what's going on here?" );
7676 if ( AOP_TYPE(result) == AOP_PCODE) {
7677 fprintf(stderr,"genDataPointerSet %s, %d\n",
7678 AOP(result)->aopu.pcop->name,
7679 PCOI(AOP(result)->aopu.pcop)->offset);
7683 // tsd, was l+1 - the underline `_' prefix was being stripped
7685 emitpComment ("%s:%u: size=%d/%d, offset=%d, AOP_TYPE(res)=%d", __FILE__,__LINE__, size, ressize, offset, AOP_TYPE(result));
7687 if (AOP_TYPE(right) == AOP_LIT) {
7688 unsigned int lit = pic14aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
7689 //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
7691 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
7692 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
7694 emitpcode(POC_CLRF, popGet(AOP(result), offset));
7697 //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
7698 emitpcode(POC_MOVFW, popGet(AOP(right), offset));
7699 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
7705 freeAsmop(right,NULL,ic,TRUE);
7706 freeAsmop(result,NULL,ic,TRUE);
7709 /*-----------------------------------------------------------------*/
7710 /* genNearPointerSet - pic14_emitcode for near pointer put */
7711 /*-----------------------------------------------------------------*/
7712 static void genNearPointerSet (operand *right,
7717 sym_link *ptype = operandType(result);
7718 sym_link *retype = getSpec(operandType(right));
7719 sym_link *letype = getSpec(ptype);
7724 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7725 aopOp(result,ic,FALSE);
7728 /* if the result is rematerializable &
7729 in data space & not a bit variable */
7730 //if (AOP_TYPE(result) == AOP_IMMD &&
7731 if (AOP_TYPE(result) == AOP_PCODE &&
7732 PIC_IS_DATA_PTR(ptype) &&
7733 !IS_BITVAR (retype) &&
7734 !IS_BITVAR (letype)) {
7735 genDataPointerSet (right,result,ic);
7736 freeAsmop(result,NULL,ic,TRUE);
7741 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7742 aopOp(right,ic,FALSE);
7743 DEBUGpic14_AopType(__LINE__,NULL,right,result);
7745 /* Check if can access directly instead of via a pointer */
7746 if ((AOP_TYPE(result) == AOP_PCODE)
7747 && (AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
7748 && (AOP_SIZE(right) == 1))
7753 if (IS_BITFIELD (letype))
7755 genPackBits (letype, result, right, direct?-1:POINTER);
7759 /* If the pointer value is not in a the FSR then need to put it in */
7760 /* Must set/reset IRP bit for use with FSR. */
7761 /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
7766 /* we have can just get the values */
7767 int size = AOP_SIZE(right);
7770 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7772 char *l = aopGet(AOP(right),offset,FALSE,TRUE);
7774 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
7776 if (AOP_TYPE(right) == AOP_LIT) {
7777 emitpcode(POC_MOVLW,popGet(AOP(right),offset));
7779 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
7782 emitpcode(POC_MOVWF,popGet(AOP(result),0));
7784 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
7786 if (size && !direct)
7787 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
7792 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7793 /* now some housekeeping stuff */
7795 /* we had to allocate for this iCode */
7796 freeAsmop(NULL,aop,ic,TRUE);
7798 /* we did not allocate which means left
7799 already in a pointer register, then
7800 if size > 0 && this could be used again
7801 we have to point it back to where it
7803 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7804 if (AOP_SIZE(right) > 1 &&
7805 !OP_SYMBOL(result)->remat &&
7806 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7808 int size = AOP_SIZE(right) - 1;
7810 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
7814 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7817 freeAsmop(right,NULL,ic,TRUE);
7818 freeAsmop(result,NULL,ic,TRUE);
7821 /*-----------------------------------------------------------------*/
7822 /* genGenPointerSet - set value from generic pointer space */
7823 /*-----------------------------------------------------------------*/
7824 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
7826 sym_link *retype = getSpec(operandType(result));
7829 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7830 aopOp(right,ic,FALSE);
7831 aopOp(result,ic,FALSE);
7834 DEBUGpic14_AopType(__LINE__,right,NULL,result);
7836 if (IS_BITFIELD(retype))
7838 genPackBits (retype, result, right, GPOINTER);
7843 /* emit call to __gptrput */
7844 char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
7845 int size = AOP_SIZE(right);
7848 /* The following assertion fails for
7849 * struct foo { char a; char b; } bar;
7850 * void demo(struct foo *dst, char c) { dst->b = c; }
7851 * as size will be 1 (sizeof(c)), whereas dst->b will be accessed
7852 * using (((char *)dst)+1), whose OP_SYM_ETYPE still is struct foo
7854 * The frontend seems to guarantee that IC_LEFT has the correct size,
7855 * it works fine both for larger and smaller types of `char c'.
7857 //assert (size == getSize(OP_SYM_ETYPE(result)));
7858 assert (size > 0 && size <= 4);
7860 /* pass arguments */
7861 /* - value (MSB in Gstack_base_addr-2, growing downwards) */
7867 mov2w_op (right, off);
7868 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
7873 assert (AOP_SIZE(result) == 3);
7874 mov2w(AOP(result), 0);
7875 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
7876 mov2w(AOP(result), 1);
7877 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
7878 mov2w(AOP(result), 2);
7879 call_libraryfunc (func[size]);
7882 freeAsmop(right,NULL,ic,TRUE);
7883 freeAsmop(result,NULL,ic,TRUE);
7886 /*-----------------------------------------------------------------*/
7887 /* genPointerSet - stores the value into a pointer location */
7888 /*-----------------------------------------------------------------*/
7889 static void genPointerSet (iCode *ic)
7891 operand *right, *result ;
7892 sym_link *type, *etype;
7896 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7898 right = IC_RIGHT(ic);
7899 result = IC_RESULT(ic) ;
7901 /* depending on the type of pointer we need to
7902 move it to the correct pointer register */
7903 type = operandType(result);
7904 etype = getSpec(type);
7905 /* if left is of type of pointer then it is simple */
7906 if (IS_PTR(type) && !IS_FUNC(type->next)) {
7907 p_type = DCL_TYPE(type);
7910 /* we have to go by the storage class */
7911 p_type = PTR_TYPE(SPEC_OCLS(etype));
7913 /* if (SPEC_OCLS(etype)->codesp ) { */
7914 /* p_type = CPOINTER ; */
7917 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7918 /* p_type = FPOINTER ; */
7920 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7921 /* p_type = PPOINTER ; */
7923 /* if (SPEC_OCLS(etype) == idata ) */
7924 /* p_type = IPOINTER ; */
7926 /* p_type = POINTER ; */
7929 /* now that we have the pointer type we assign
7930 the pointer values */
7936 genNearPointerSet (right,result,ic);
7940 genPagedPointerSet (right,result,ic);
7944 genFarPointerSet (right,result,ic);
7948 genGenPointerSet (right,result,ic);
7952 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7953 "genPointerSet: illegal pointer type");
7957 /*-----------------------------------------------------------------*/
7958 /* genIfx - generate code for Ifx statement */
7959 /*-----------------------------------------------------------------*/
7960 static void genIfx (iCode *ic, iCode *popIc)
7962 operand *cond = IC_COND(ic);
7966 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7968 aopOp(cond,ic,FALSE);
7970 /* get the value into acc */
7971 if (AOP_TYPE(cond) != AOP_CRY)
7972 pic14_toBoolean(cond);
7976 /* if there was something to be popped then do it */
7982 /* This assumes that CARRY is set iff cond is true */
7985 assert (!IC_FALSE(ic));
7986 emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
7988 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
7990 assert (IC_FALSE(ic));
7991 emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
7993 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
7997 static int hasWarned = 0;
8000 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
8007 /* now Z is set iff !cond */
8010 assert (!IC_FALSE(ic));
8012 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
8015 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
8021 /* the result is now in the accumulator */
8022 freeAsmop(cond,NULL,ic,TRUE);
8025 /*-----------------------------------------------------------------*/
8026 /* genAddrOf - generates code for address of */
8027 /*-----------------------------------------------------------------*/
8028 static void genAddrOf (iCode *ic)
8030 operand *right, *result, *left;
8034 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8037 //aopOp(IC_RESULT(ic),ic,FALSE);
8039 aopOp((left=IC_LEFT(ic)),ic,FALSE);
8040 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
8041 aopOp((result=IC_RESULT(ic)),ic,TRUE);
8043 DEBUGpic14_AopType(__LINE__,left,right,result);
8044 assert (IS_SYMOP (left));
8046 /* sanity check: generic pointers to code space are not yet supported,
8047 * pionters to codespace must not be assigned addresses of __data values. */
8049 fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
8050 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)));
8051 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)));
8052 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)));
8053 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)));
8056 if (IS_SYMOP(result) && IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
8057 fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
8058 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
8059 OP_SYMBOL(left)->name);
8060 } else if (IS_SYMOP(result) && !IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
8061 fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
8062 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
8063 OP_SYMBOL(left)->name);
8066 size = AOP_SIZE(IC_RESULT(ic));
8067 if (IS_SYMOP(result) && IS_GENPTR(OP_SYM_TYPE(result))) {
8069 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
8074 /* fixing bug #863624, reported from (errolv) */
8075 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
8076 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
8079 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
8080 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8085 if (IS_SYMOP(result) && IS_GENPTR(OP_SYM_TYPE(result)))
8087 /* provide correct tag */
8088 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
8089 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
8090 movwf (AOP(result), 2);
8093 freeAsmop(left,NULL,ic,FALSE);
8094 freeAsmop(result,NULL,ic,TRUE);
8099 /*-----------------------------------------------------------------*/
8100 /* genFarFarAssign - assignment when both are in far space */
8101 /*-----------------------------------------------------------------*/
8102 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
8104 int size = AOP_SIZE(right);
8107 /* first push the right side on to the stack */
8109 l = aopGet(AOP(right),offset++,FALSE,FALSE);
8111 pic14_emitcode ("push","acc");
8114 freeAsmop(right,NULL,ic,FALSE);
8115 /* now assign DPTR to result */
8116 aopOp(result,ic,FALSE);
8117 size = AOP_SIZE(result);
8119 pic14_emitcode ("pop","acc");
8120 aopPut(AOP(result),"a",--offset);
8122 freeAsmop(result,NULL,ic,FALSE);
8127 /*-----------------------------------------------------------------*/
8128 /* genAssign - generate code for assignment */
8129 /*-----------------------------------------------------------------*/
8130 static void genAssign (iCode *ic)
8132 operand *result, *right;
8133 int size, offset,know_W;
8134 unsigned long lit = 0L;
8136 result = IC_RESULT(ic);
8137 right = IC_RIGHT(ic) ;
8140 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8142 /* if they are the same */
8143 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
8146 aopOp(right,ic,FALSE);
8147 aopOp(result,ic,TRUE);
8149 DEBUGpic14_AopType(__LINE__,NULL,right,result);
8151 /* if they are the same registers */
8152 if (pic14_sameRegs(AOP(right),AOP(result)))
8155 /* special case: assign from __code */
8156 if (!IS_ITEMP(right) /* --> iTemps never reside in __code */
8157 && IS_SYMOP (right) /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
8158 && !IS_FUNC(OP_SYM_TYPE(right)) /* --> we would want its address instead of the first instruction */
8159 && !IS_CODEPTR(OP_SYM_TYPE(right)) /* --> get symbols address instread */
8160 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
8162 emitpComment ("genAssign from CODESPACE");
8163 genConstPointerGet (right, result, ic);
8167 /* just for symmetry reasons... */
8168 if (!IS_ITEMP(result)
8169 && IS_SYMOP (result)
8170 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
8172 assert ( !"cannot write to CODESPACE" );
8175 /* if the result is a bit */
8176 if (AOP_TYPE(result) == AOP_CRY) {
8178 /* if the right size is a literal then
8179 we know what the value is */
8180 if (AOP_TYPE(right) == AOP_LIT) {
8182 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
8183 popGet(AOP(result),0));
8185 if (((int) operandLitValue(right)))
8186 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
8187 AOP(result)->aopu.aop_dir,
8188 AOP(result)->aopu.aop_dir);
8190 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
8191 AOP(result)->aopu.aop_dir,
8192 AOP(result)->aopu.aop_dir);
8196 /* the right is also a bit variable */
8197 if (AOP_TYPE(right) == AOP_CRY) {
8198 emitpcode(POC_BCF, popGet(AOP(result),0));
8199 emitpcode(POC_BTFSC, popGet(AOP(right),0));
8200 emitpcode(POC_BSF, popGet(AOP(result),0));
8202 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
8203 AOP(result)->aopu.aop_dir,
8204 AOP(result)->aopu.aop_dir);
8205 pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
8206 AOP(right)->aopu.aop_dir,
8207 AOP(right)->aopu.aop_dir);
8208 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
8209 AOP(result)->aopu.aop_dir,
8210 AOP(result)->aopu.aop_dir);
8215 emitpcode(POC_BCF, popGet(AOP(result),0));
8216 pic14_toBoolean(right);
8218 emitpcode(POC_BSF, popGet(AOP(result),0));
8219 //aopPut(AOP(result),"a",0);
8223 /* bit variables done */
8225 size = AOP_SIZE(result);
8227 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
8228 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8229 if(aopIdx(AOP(result),0) == 4) {
8230 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8231 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8232 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8235 DEBUGpic14_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
8241 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8242 if(AOP_TYPE(right) == AOP_LIT) {
8243 lit = (unsigned long)pic14aopLiteral(AOP(right)->aopu.aop_lit, offset) & 0x0ff;
8245 if(know_W != (int)(lit&0xff))
8246 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
8248 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8250 emitpcode(POC_CLRF, popGet(AOP(result),offset));
8252 } else if (AOP_TYPE(right) == AOP_CRY) {
8253 emitpcode(POC_CLRF, popGet(AOP(result),offset));
8255 emitpcode(POC_BTFSS, popGet(AOP(right),0));
8256 emitpcode(POC_INCF, popGet(AOP(result),0));
8259 mov2w_op (right, offset);
8260 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8268 freeAsmop (right,NULL,ic,FALSE);
8269 freeAsmop (result,NULL,ic,TRUE);
8272 /*-----------------------------------------------------------------*/
8273 /* genJumpTab - genrates code for jump table */
8274 /*-----------------------------------------------------------------*/
8275 static void genJumpTab (iCode *ic)
8281 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8283 aopOp(IC_JTCOND(ic),ic,FALSE);
8284 /* get the condition into accumulator */
8285 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
8287 /* multiply by three */
8288 pic14_emitcode("add","a,acc");
8289 pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
8291 jtab = newiTempLabel(NULL);
8292 pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
8293 pic14_emitcode("jmp","@a+dptr");
8294 pic14_emitcode("","%05d_DS_:",jtab->key+100);
8296 emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
8297 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
8298 emitpcode(POC_MOVLW, popGetLabel(jtab->key));
8299 emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
8301 emitpcode(POC_INCF, popCopyReg(&pc_pclath));
8302 emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
8303 emitpLabel(jtab->key);
8305 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
8307 /* now generate the jump labels */
8308 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
8309 jtab = setNextItem(IC_JTLABELS(ic))) {
8310 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
8311 emitpcode(POC_GOTO,popGetLabel(jtab->key));
8317 /*-----------------------------------------------------------------*/
8318 /* genMixedOperation - gen code for operators between mixed types */
8319 /*-----------------------------------------------------------------*/
8321 TSD - Written for the PIC port - but this unfortunately is buggy.
8322 This routine is good in that it is able to efficiently promote
8323 types to different (larger) sizes. Unfortunately, the temporary
8324 variables that are optimized out by this routine are sometimes
8325 used in other places. So until I know how to really parse the
8326 iCode tree, I'm going to not be using this routine :(.
8328 static int genMixedOperation (iCode *ic)
8332 operand *result = IC_RESULT(ic);
8333 sym_link *ctype = operandType(IC_LEFT(ic));
8334 operand *right = IC_RIGHT(ic);
8340 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
8342 pic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
8348 nextright = IC_RIGHT(nextic);
8349 nextleft = IC_LEFT(nextic);
8350 nextresult = IC_RESULT(nextic);
8352 aopOp(right,ic,FALSE);
8353 aopOp(result,ic,FALSE);
8354 aopOp(nextright, nextic, FALSE);
8355 aopOp(nextleft, nextic, FALSE);
8356 aopOp(nextresult, nextic, FALSE);
8358 if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
8364 pic14_emitcode(";remove right +","");
8366 } else if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
8372 pic14_emitcode(";remove left +","");
8376 big = AOP_SIZE(nextleft);
8377 small = AOP_SIZE(nextright);
8379 switch(nextic->op) {
8382 pic14_emitcode(";optimize a +","");
8383 /* if unsigned or not an integral type */
8384 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
8385 pic14_emitcode(";add a bit to something","");
8388 pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
8390 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
8391 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
8392 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
8394 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
8402 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8403 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8404 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8407 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8409 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
8410 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
8411 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
8412 pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8413 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
8416 pic14_emitcode("rlf","known_zero,w");
8423 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8424 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8425 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8427 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8437 freeAsmop(right,NULL,ic,TRUE);
8438 freeAsmop(result,NULL,ic,TRUE);
8439 freeAsmop(nextright,NULL,ic,TRUE);
8440 freeAsmop(nextleft,NULL,ic,TRUE);
8442 nextic->generated = 1;
8449 /*-----------------------------------------------------------------*/
8450 /* genCast - gen code for casting */
8451 /*-----------------------------------------------------------------*/
8452 static void genCast (iCode *ic)
8454 operand *result = IC_RESULT(ic);
8455 sym_link *restype = operandType(result);
8456 sym_link *rtype = operandType(IC_RIGHT(ic));
8457 operand *right = IC_RIGHT(ic);
8461 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
8462 /* if they are equivalent then do nothing */
8463 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
8466 aopOp(right,ic,FALSE) ;
8467 aopOp(result,ic,FALSE);
8469 DEBUGpic14_AopType(__LINE__,NULL,right,result);
8471 /* if the result is a bit */
8472 if (AOP_TYPE(result) == AOP_CRY) {
8473 assert(!"assigning to bit variables is not supported");
8476 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
8478 size = AOP_SIZE(result);
8480 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
8482 emitpcode(POC_CLRF, popGet(AOP(result),0));
8483 emitpcode(POC_BTFSC, popGet(AOP(right),0));
8484 emitpcode(POC_INCF, popGet(AOP(result),0));
8487 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
8492 if (IS_PTR(restype))
8494 operand *result = IC_RESULT(ic);
8495 //operand *left = IC_LEFT(ic);
8496 operand *right = IC_RIGHT(ic);
8499 /* copy common part */
8500 int max, size = AOP_SIZE(result);
8501 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
8502 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
8504 /* warn if we discard generic opinter tag */
8505 if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
8507 //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
8513 mov2w_op (right, size);
8514 movwf (AOP(result), size);
8517 /* upcast into generic pointer type? */
8518 if (IS_GENPTR(restype)
8519 && (size < AOP_SIZE(result))
8520 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
8522 //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
8525 switch (DCL_TYPE(rtype))
8527 case POINTER: /* __data */
8528 case FPOINTER: /* __data */
8529 assert (AOP_SIZE(right) == 2);
8533 case CPOINTER: /* __code */
8534 assert (AOP_SIZE(right) == 2);
8538 case GPOINTER: /* unknown destination, __data or __code */
8539 /* assume __data space (address of immediate) */
8540 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
8541 if (AOP(right)->code)
8548 assert (!"unhandled pointer type");
8551 /* convert other values into pointers to __data space */
8555 assert (AOP_SIZE(result) == 3);
8557 emitpcode(POC_CLRF, popGet(AOP(result), 2));
8559 emitpcode(POC_MOVLW, popGetLit(tag));
8560 movwf(AOP(result), 2);
8563 addSign(result, max, 0);
8568 /* if they are the same size : or less */
8569 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8571 /* if they are in the same place */
8572 if (pic14_sameRegs(AOP(right),AOP(result)))
8575 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
8576 if (IS_PTR_CONST(rtype))
8577 DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
8578 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
8579 DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
8581 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
8582 emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
8583 emitpcode(POC_MOVWF, popGet(AOP(result),0));
8584 emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
8585 emitpcode(POC_MOVWF, popGet(AOP(result),1));
8586 if(AOP_SIZE(result) <2)
8587 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
8591 /* if they in different places then copy */
8592 size = AOP_SIZE(result);
8595 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8596 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8598 //aopPut(AOP(result),
8599 // aopGet(AOP(right),offset,FALSE,FALSE),
8608 /* so we now know that the size of destination is greater
8609 than the size of the source.
8610 Now, if the next iCode is an operator then we might be
8611 able to optimize the operation without performing a cast.
8613 if(0 && genMixedOperation(ic)) {
8614 /* XXX: cannot optimize: must copy regs! */
8618 /* we move to result for the size of source */
8619 size = AOP_SIZE(right);
8622 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8623 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8627 addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
8630 freeAsmop(right,NULL,ic,TRUE);
8631 freeAsmop(result,NULL,ic,TRUE);
8635 /*-----------------------------------------------------------------*/
8636 /* genDjnz - generate decrement & jump if not zero instrucion */
8637 /*-----------------------------------------------------------------*/
8638 static int genDjnz (iCode *ic, iCode *ifx)
8642 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8647 /* if the if condition has a false label
8648 then we cannot save */
8652 /* if the minus is not of the form
8654 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8655 !IS_OP_LITERAL(IC_RIGHT(ic)))
8658 if (operandLitValue(IC_RIGHT(ic)) != 1)
8661 /* if the size of this greater than one then no
8663 if (getSize(operandType(IC_RESULT(ic))) > 1)
8666 /* otherwise we can save BIG */
8667 lbl = newiTempLabel(NULL);
8668 lbl1= newiTempLabel(NULL);
8670 aopOp(IC_RESULT(ic),ic,FALSE);
8672 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
8673 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
8675 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8680 /*-----------------------------------------------------------------*/
8681 /* genReceive - generate code for a receive iCode */
8682 /*-----------------------------------------------------------------*/
8683 static void genReceive (iCode *ic)
8686 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8688 if (isOperandInFarSpace(IC_RESULT(ic)) &&
8689 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8690 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8692 int size = getSize(operandType(IC_RESULT(ic)));
8693 int offset = fReturnSizePic - size;
8695 pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
8696 fReturn[fReturnSizePic - offset - 1] : "acc"));
8699 aopOp(IC_RESULT(ic),ic,FALSE);
8700 size = AOP_SIZE(IC_RESULT(ic));
8703 pic14_emitcode ("pop","acc");
8704 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8709 aopOp(IC_RESULT(ic),ic,FALSE);
8711 GpsuedoStkPtr = ic->parmBytes; // address used arg on stack
8712 assignResultValue(IC_RESULT(ic));
8715 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8718 /*-----------------------------------------------------------------*/
8719 /* genDummyRead - generate code for dummy read of volatiles */
8720 /*-----------------------------------------------------------------*/
8722 genDummyRead (iCode * ic)
8725 pic14_emitcode ("; genDummyRead","");
8726 pic14_emitcode ("; not implemented","");
8731 /*-----------------------------------------------------------------*/
8732 /* genpic14Code - generate code for pic14 based controllers */
8733 /*-----------------------------------------------------------------*/
8735 * At this point, ralloc.c has gone through the iCode and attempted
8736 * to optimize in a way suitable for a PIC. Now we've got to generate
8737 * PIC instructions that correspond to the iCode.
8739 * Once the instructions are generated, we'll pass through both the
8740 * peep hole optimizer and the pCode optimizer.
8741 *-----------------------------------------------------------------*/
8743 void genpic14Code (iCode *lic)
8750 lineHead = lineCurr = NULL;
8752 pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
8755 /* if debug information required */
8756 if (options.debug && debugFile && currFunc) {
8757 debugFile->writeFunction (currFunc, lic);
8761 for (ic = lic ; ic ; ic = ic->next ) {
8763 //DEBUGpic14_emitcode(";ic","");
8764 //fprintf (stderr, "in ic loop\n");
8765 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
8766 //ic->lineno, printCLine(ic->filename, ic->lineno));
8768 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
8770 //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
8771 cline = printCLine (ic->filename, ic->lineno);
8772 if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
8773 addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
8774 //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
8777 if (options.iCodeInAsm) {
8778 const char *iLine = printILine(ic);
8779 emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
8782 /* if the result is marked as
8783 spilt and rematerializable or code for
8784 this has already been generated then
8786 if (resultRemat(ic) || ic->generated )
8789 /* depending on the operation */
8808 /* IPOP happens only when trying to restore a
8809 spilt live range, if there is an ifx statement
8810 following this pop then the if statement might
8811 be using some of the registers being popped which
8812 would destory the contents of the register so
8813 we need to check for this condition and handle it */
8815 ic->next->op == IFX &&
8816 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
8817 genIfx (ic->next,ic);
8835 genEndFunction (ic);
8855 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8872 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
8876 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8883 /* note these two are xlated by algebraic equivalence
8884 during parsing SDCC.y */
8885 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8886 "got '>=' or '<=' shouldn't have come here");
8890 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8902 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8906 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8910 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8937 case GET_VALUE_AT_ADDRESS:
8942 if (POINTER_SET(ic))
8969 addSet(&_G.sendSet,ic);
8972 case DUMMY_READ_VOLATILE:
8977 fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
8984 /* now we are ready to call the
8985 peep hole optimizer */
8986 if (!options.nopeep) {
8987 peepHole (&lineHead);
8989 /* now do the actual printing */
8990 printLine (lineHead,codeOutBuf);
8993 DFPRINTF((stderr,"printing pBlock\n\n"));
8994 printpBlock(stdout,pb);
9000 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
9001 * (meaning: representing its own address) or not (referencing its contents).
9002 * This can only be decided based on the operand's type. */
9004 aop_isLitLike (asmop *aop)
9007 if (aop->type == AOP_LIT) return 1;
9008 if (aop->type == AOP_IMMD) return 1;
9009 if ((aop->type == AOP_PCODE) &&
9010 ((aop->aopu.pcop->type == PO_LITERAL)))
9012 /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
9013 * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
9020 op_isLitLike (operand *op)
9023 if (aop_isLitLike (AOP(op))) return 1;
9024 if (IS_SYMOP(op) && IS_FUNC(OP_SYM_TYPE(op))) return 1;
9025 if (IS_SYMOP(op) && IS_PTR(OP_SYM_TYPE(op))
9026 && (AOP_TYPE(op) == AOP_PCODE)
9027 && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {