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@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"
46 /* When changing these, you must also update the assembler template
47 * in device/lib/libsdcc/macros.inc */
48 #define GPTRTAG_DATA 0x00
49 #define GPTRTAG_CODE 0x80
51 /* The PIC port(s) need not differentiate between POINTER and FPOINTER. */
52 #define PIC_IS_DATA_PTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
53 #define PIC_IS_FARPTR(x) (PIC_IS_DATA_PTR(x))
55 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
56 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
57 void genMult8X8_8 (operand *, operand *,operand *);
58 extern void printpBlock(FILE *of, pBlock *pb);
60 static int labelOffset=0;
61 extern int debug_verbose;
62 //static int optimized_for_speed = 0;
64 /* max_key keeps track of the largest label number used in
65 a function. This is then used to adjust the label offset
66 for the next function.
69 static int GpsuedoStkPtr=0;
71 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
72 extern char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
73 unsigned int pic14aopLiteral (value *val, int offset);
74 const char *AopType(short type);
76 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0x00ff)
78 /* this is the down and dirty file with all kinds of
79 kludgy & hacky stuff. This is what it is all about
80 CODE GENERATION for a specific MCU . some of the
81 routines may be reusable, will have to see */
83 static char *zero = "#0x00";
84 static char *one = "#0x01";
85 static char *spname = "sp";
87 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
88 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
89 static char **fReturn = fReturnpic14;
91 //static char *accUse[] = {"a","b"};
93 //static short rbank = -1;
105 /* Resolved ifx structure. This structure stores information
106 about an iCode ifx that makes it easier to generate code.
108 typedef struct resolvedIfx {
109 symbol *lbl; /* pointer to a label */
110 int condition; /* true or false ifx */
111 int generated; /* set true when the code associated with the ifx
115 extern int pic14_ptrRegReq ;
116 extern int pic14_nRegs;
117 extern FILE *codeOutFile;
118 static void saverbank (int, iCode *,bool);
120 static lineNode *lineHead = NULL;
121 static lineNode *lineCurr = NULL;
124 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
125 0xE0, 0xC0, 0x80, 0x00};
126 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
127 0x07, 0x03, 0x01, 0x00};
132 /*-----------------------------------------------------------------*/
133 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
134 /* exponent of 2 is returned, otherwise -1 is */
136 /* note that this is similar to the function `powof2' in SDCCsymt */
140 /*-----------------------------------------------------------------*/
141 static int my_powof2 (unsigned long num)
144 if( (num & (num-1)) == 0) {
157 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
160 DEBUGpic14_emitcode ("; ","line = %d result %s=%s, size=%d, left %s=%s, size=%d, right %s=%s, size=%d",
162 ((result) ? AopType(AOP_TYPE(result)) : "-"),
163 ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
164 ((result) ? AOP_SIZE(result) : 0),
165 ((left) ? AopType(AOP_TYPE(left)) : "-"),
166 ((left) ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
167 ((left) ? AOP_SIZE(left) : 0),
168 ((right) ? AopType(AOP_TYPE(right)) : "-"),
169 ((right) ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
170 ((right) ? AOP_SIZE(right) : 0));
174 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
177 DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
179 ((result) ? AopType(AOP_TYPE(result)) : "-"),
180 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
181 ((left) ? AopType(AOP_TYPE(left)) : "-"),
182 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
183 ((right) ? AopType(AOP_TYPE(right)) : "-"),
184 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
188 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
191 char lb[INITIAL_INLINEASM];
192 unsigned char *lbp = lb;
194 if(!debug_verbose && !options.debug)
201 sprintf(lb,"%s\t",inst);
203 sprintf(lb,"%s",inst);
204 vsprintf(lb+(strlen(lb)),fmt,ap);
208 while (isspace(*lbp)) lbp++;
211 lineCurr = (lineCurr ?
212 connectLine(lineCurr,newLineNode(lb)) :
213 (lineHead = newLineNode(lb)));
214 lineCurr->isInline = _G.inLine;
215 lineCurr->isDebug = _G.debugLine;
217 addpCode2pBlock(pb,newpCodeCharP(lb));
222 static void Safe_vsnprintf (char *buf, size_t size, const char *fmt, va_list ap)
224 #if defined (HAVE_VSNPRINTF)
225 vsnprintf (buf, size, fmt, ap);
226 #elif defined (HAVE_VSPRINTF)
227 vsprintf (buf, size, fmt, ap);
228 if (strlen (buf) >= size)
230 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
232 #elif defined (HAVE_SNPRINTF)
233 snprintf (buf, size, "vs(n)printf required");
234 #elif defined (HAVE_SRINTF)
235 sprintf (buf, "vs(n)printf required");
236 if (strlen (buf) >= size)
238 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
241 assert ( !"neither vsnprintf nor vsprintf is present -- unable to proceed" );
245 void emitpComment (const char *fmt, ...)
252 Safe_vsnprintf (buffer, 4096, fmt, va);
253 //fprintf (stderr, "%s\n" ,buffer);
254 addpCode2pBlock (pb, newpCodeCharP (buffer));
257 Safe_vsnprintf (buffer, 4096, fmt, va);
258 fprintf (stderr, "No current pBlock -- discarding comment [%s]\n", buffer);
264 void emitpLabel(int key)
266 addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
269 /* gen.h defines a macro emitpcode that should be used to call emitpcode
270 * as this allows for easy debugging (ever asked the question: where was
271 * this instruction geenrated? Here is the answer... */
272 void emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
275 addpCode2pBlock(pb,newpCode(poc,pcop));
277 DEBUGpic14_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
280 void emitpcodeNULLop(PIC_OPCODE poc)
283 addpCode2pBlock(pb,newpCode(poc,NULL));
288 /*-----------------------------------------------------------------*/
289 /* pic14_emitcode - writes the code into a file : for now it is simple */
290 /*-----------------------------------------------------------------*/
291 void pic14_emitcode (char *inst,char *fmt, ...)
294 char lb[INITIAL_INLINEASM];
295 unsigned char *lbp = lb;
301 sprintf(lb,"%s\t",inst);
303 sprintf(lb,"%s",inst);
304 vsprintf(lb+(strlen(lb)),fmt,ap);
308 while (isspace(*lbp)) lbp++;
311 lineCurr = (lineCurr ?
312 connectLine(lineCurr,newLineNode(lb)) :
313 (lineHead = newLineNode(lb)));
314 lineCurr->isInline = _G.inLine;
315 lineCurr->isDebug = _G.debugLine;
318 addpCode2pBlock(pb,newpCodeCharP(lb));
323 /*-----------------------------------------------------------------*/
324 /* pic14_emitDebuggerSymbol - associate the current code location */
325 /* with a debugger symbol */
326 /*-----------------------------------------------------------------*/
328 pic14_emitDebuggerSymbol (char * debugSym)
331 pic14_emitcode ("", ";%s ==.", debugSym);
336 /*-----------------------------------------------------------------*/
337 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
338 /*-----------------------------------------------------------------*/
339 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
341 bool r0iu = FALSE , r1iu = FALSE;
342 bool r0ou = FALSE , r1ou = FALSE;
344 /* the logic: if r0 & r1 used in the instruction
345 then we are in trouble otherwise */
347 /* first check if r0 & r1 are used by this
348 instruction, in which case we are in trouble */
349 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
350 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
355 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
356 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
358 /* if no usage of r0 then return it */
359 if (!r0iu && !r0ou) {
360 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
361 (*aopp)->type = AOP_R0;
363 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
366 /* if no usage of r1 then return it */
367 if (!r1iu && !r1ou) {
368 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
369 (*aopp)->type = AOP_R1;
371 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
374 /* now we know they both have usage */
375 /* if r0 not used in this instruction */
377 /* push it if not already pushed */
379 //pic14_emitcode ("push","%s",
380 // pic14_regWithIdx(R0_IDX)->dname);
384 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
385 (*aopp)->type = AOP_R0;
387 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
390 /* if r1 not used then */
393 /* push it if not already pushed */
395 //pic14_emitcode ("push","%s",
396 // pic14_regWithIdx(R1_IDX)->dname);
400 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
401 (*aopp)->type = AOP_R1;
402 return pic14_regWithIdx(R1_IDX);
406 /* I said end of world but not quite end of world yet */
407 /* if this is a result then we can push it on the stack*/
409 (*aopp)->type = AOP_STK;
413 /* other wise this is true end of the world */
414 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
415 "getFreePtr should never reach here");
420 /*-----------------------------------------------------------------*/
421 /* newAsmop - creates a new asmOp */
422 /*-----------------------------------------------------------------*/
423 asmop *newAsmop (short type)
427 aop = Safe_calloc(1,sizeof(asmop));
432 static void genSetDPTR(int n)
436 pic14_emitcode(";", "Select standard DPTR");
437 pic14_emitcode("mov", "dps, #0x00");
441 pic14_emitcode(";", "Select alternate DPTR");
442 pic14_emitcode("mov", "dps, #0x01");
446 /*-----------------------------------------------------------------*/
447 /* resolveIfx - converts an iCode ifx into a form more useful for */
448 /* generating code */
449 /*-----------------------------------------------------------------*/
450 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
455 // DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
457 resIfx->condition = 1; /* assume that the ifx is true */
458 resIfx->generated = 0; /* indicate that the ifx has not been used */
461 resIfx->lbl = NULL; /* this is wrong: newiTempLabel(NULL); / * oops, there is no ifx. so create a label */
463 DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
464 __FUNCTION__,__LINE__,resIfx->lbl->key);
468 resIfx->lbl = IC_TRUE(ifx);
470 resIfx->lbl = IC_FALSE(ifx);
471 resIfx->condition = 0;
475 DEBUGpic14_emitcode("; ***","ifx true is non-null");
477 DEBUGpic14_emitcode("; ***","ifx false is non-null");
481 // DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
484 /*-----------------------------------------------------------------*/
485 /* pointerCode - returns the code for a pointer type */
486 /*-----------------------------------------------------------------*/
488 static int pointerCode (sym_link *etype)
491 return PTR_TYPE(SPEC_OCLS(etype));
496 /*-----------------------------------------------------------------*/
497 /* aopForSym - for a true symbol */
498 /*-----------------------------------------------------------------*/
499 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
502 memmap *space= SPEC_OCLS(sym->etype);
504 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
505 /* if already has one */
510 /* assign depending on the storage class */
511 /* if it is on the stack or indirectly addressable */
512 /* space we need to assign either r0 or r1 to it */
513 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
514 sym->aop = aop = newAsmop(0);
515 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
516 aop->size = getSize(sym->type);
518 /* now assign the address of the variable to
519 the pointer register */
520 if (aop->type != AOP_STK) {
524 pic14_emitcode("push","acc");
526 pic14_emitcode("mov","a,_bp");
527 pic14_emitcode("add","a,#0x%02x",
529 ((char)(sym->stack - _G.nRegsSaved )) :
530 ((char)sym->stack)) & 0xff);
531 pic14_emitcode("mov","%s,a",
532 aop->aopu.aop_ptr->name);
535 pic14_emitcode("pop","acc");
537 pic14_emitcode("mov","%s,#%s",
538 aop->aopu.aop_ptr->name,
540 aop->paged = space->paged;
542 aop->aopu.aop_stk = sym->stack;
546 if (sym->onStack && options.stack10bit)
548 /* It's on the 10 bit stack, which is located in
552 //DEBUGpic14_emitcode(";","%d",__LINE__);
555 pic14_emitcode("push","acc");
557 pic14_emitcode("mov","a,_bp");
558 pic14_emitcode("add","a,#0x%02x",
560 ((char)(sym->stack - _G.nRegsSaved )) :
561 ((char)sym->stack)) & 0xff);
564 pic14_emitcode ("mov","dpx1,#0x40");
565 pic14_emitcode ("mov","dph1,#0x00");
566 pic14_emitcode ("mov","dpl1, a");
570 pic14_emitcode("pop","acc");
572 sym->aop = aop = newAsmop(AOP_DPTR2);
573 aop->size = getSize(sym->type);
578 //DEBUGpic14_emitcode(";","%d",__LINE__);
579 /* if in bit space */
580 if (IN_BITSPACE(space)) {
581 sym->aop = aop = newAsmop (AOP_CRY);
582 aop->aopu.aop_dir = sym->rname ;
583 aop->size = getSize(sym->type);
584 //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
587 /* if it is in direct space */
588 if (IN_DIRSPACE(space)) {
589 sym->aop = aop = newAsmop (AOP_DIR);
590 aop->aopu.aop_dir = sym->rname ;
591 aop->size = getSize(sym->type);
592 DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
596 /* special case for a function */
597 if (IS_FUNC(sym->type)) {
599 sym->aop = aop = newAsmop(AOP_PCODE);
600 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
601 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
602 PCOI(aop->aopu.pcop)->_function = 1;
603 PCOI(aop->aopu.pcop)->index = 0;
604 aop->size = FPTRSIZE;
606 sym->aop = aop = newAsmop(AOP_IMMD);
607 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
608 strcpy(aop->aopu.aop_immd,sym->rname);
609 aop->size = FPTRSIZE;
611 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
615 if (IS_ARRAY(sym->type)) {
616 sym->aop = aop = newAsmop(AOP_PCODE);
617 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
618 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
619 PCOI(aop->aopu.pcop)->_function = 0;
620 PCOI(aop->aopu.pcop)->index = 0;
621 aop->size = getSize(sym->etype) * DCL_ELEM(sym->type);
623 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
627 /* only remaining is far space */
628 /* in which case DPTR gets the address */
629 sym->aop = aop = newAsmop(AOP_PCODE);
631 aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
632 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
633 PCOI(aop->aopu.pcop)->index = 0;
635 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
636 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
638 allocDirReg (IC_LEFT(ic));
640 aop->size = FPTRSIZE;
642 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
643 sym->aop = aop = newAsmop(AOP_DPTR);
644 pic14_emitcode ("mov","dptr,#%s", sym->rname);
645 aop->size = getSize(sym->type);
647 DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
650 /* if it is in code space */
651 if (IN_CODESPACE(space))
657 /*-----------------------------------------------------------------*/
658 /* aopForRemat - rematerialzes an object */
659 /*-----------------------------------------------------------------*/
660 static asmop *aopForRemat (operand *op) // x symbol *sym)
662 symbol *sym = OP_SYMBOL(op);
664 asmop *aop = newAsmop(AOP_PCODE);
668 ic = sym->rematiCode;
670 DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
671 if(IS_OP_POINTER(op)) {
672 DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
676 val += (int) operandLitValue(IC_RIGHT(ic));
677 } else if (ic->op == '-') {
678 val -= (int) operandLitValue(IC_RIGHT(ic));
682 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
685 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
686 aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
687 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
688 PCOI(aop->aopu.pcop)->index = val;
690 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
691 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
692 val, IS_PTR_CONST(operandType(op)));
694 // DEBUGpic14_emitcode(";","aop type %s",AopType(AOP_TYPE(IC_LEFT(ic))));
696 allocDirReg (IC_LEFT(ic));
701 int aopIdx (asmop *aop, int offset)
706 if(aop->type != AOP_REG)
709 return aop->aopu.aop_reg[offset]->rIdx;
712 /*-----------------------------------------------------------------*/
713 /* regsInCommon - two operands have some registers in common */
714 /*-----------------------------------------------------------------*/
715 static bool regsInCommon (operand *op1, operand *op2)
720 /* if they have registers in common */
721 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
724 sym1 = OP_SYMBOL(op1);
725 sym2 = OP_SYMBOL(op2);
727 if (sym1->nRegs == 0 || sym2->nRegs == 0)
730 for (i = 0 ; i < sym1->nRegs ; i++) {
735 for (j = 0 ; j < sym2->nRegs ;j++ ) {
739 if (sym2->regs[j] == sym1->regs[i])
747 /*-----------------------------------------------------------------*/
748 /* operandsEqu - equivalent */
749 /*-----------------------------------------------------------------*/
750 static bool operandsEqu ( operand *op1, operand *op2)
754 /* if they not symbols */
755 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
758 sym1 = OP_SYMBOL(op1);
759 sym2 = OP_SYMBOL(op2);
761 /* if both are itemps & one is spilt
762 and the other is not then false */
763 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
764 sym1->isspilt != sym2->isspilt )
767 /* if they are the same */
771 if (sym1->rname[0] && sym2->rname[0]
772 && strcmp (sym1->rname, sym2->rname) == 0)
776 /* if left is a tmp & right is not */
780 (sym1->usl.spillLoc == sym2))
787 (sym2->usl.spillLoc == sym1))
793 /*-----------------------------------------------------------------*/
794 /* pic14_sameRegs - two asmops have the same registers */
795 /*-----------------------------------------------------------------*/
796 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
803 if (aop1->type != AOP_REG ||
804 aop2->type != AOP_REG )
807 if (aop1->size != aop2->size )
810 for (i = 0 ; i < aop1->size ; i++ )
811 if (aop1->aopu.aop_reg[i] !=
812 aop2->aopu.aop_reg[i] )
818 /*-----------------------------------------------------------------*/
819 /* aopOp - allocates an asmop for an operand : */
820 /*-----------------------------------------------------------------*/
821 void aopOp (operand *op, iCode *ic, bool result)
830 /* if this a literal */
831 if (IS_OP_LITERAL(op)) {
832 op->aop = aop = newAsmop(AOP_LIT);
833 aop->aopu.aop_lit = op->operand.valOperand;
834 aop->size = getSize(operandType(op));
839 sym_link *type = operandType(op);
840 if(IS_PTR_CONST(type))
841 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
844 /* if already has a asmop then continue */
848 /* if the underlying symbol has a aop */
849 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
850 DEBUGpic14_emitcode(";","%d",__LINE__);
851 op->aop = OP_SYMBOL(op)->aop;
855 /* if this is a true symbol */
856 if (IS_TRUE_SYMOP(op)) {
857 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
858 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
862 /* this is a temporary : this has
868 e) can be a return use only */
873 /* if the type is a conditional */
874 if (sym->regType == REG_CND) {
875 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
880 /* if it is spilt then two situations
882 b) has a spill location */
883 if (sym->isspilt || sym->nRegs == 0) {
885 DEBUGpic14_emitcode(";","%d",__LINE__);
886 /* rematerialize it NOW */
889 sym->aop = op->aop = aop = aopForRemat (op);
890 aop->size = getSize(sym->type);
891 //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
896 /* WREG is not usable as an ordinary operand with PIC architecture,
897 * one might introduce a scratch register that can be used to make
898 * WREG accesible as an operand... disable WREG for now */
901 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
902 aop->size = getSize(sym->type);
903 for ( i = 0 ; i < 2 ; i++ )
904 aop->aopu.aop_str[i] = accUse[i];
905 DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
911 if(sym->isptr) { // && sym->uptr
912 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
913 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
915 //PCOI(aop->aopu.pcop)->_const = 0;
916 //PCOI(aop->aopu.pcop)->index = 0;
918 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
919 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
921 //allocDirReg (IC_LEFT(ic));
923 aop->size = getSize(sym->type);
924 DEBUGpic14_emitcode(";","%d",__LINE__);
931 aop = op->aop = sym->aop = newAsmop(AOP_STR);
932 aop->size = getSize(sym->type);
933 for ( i = 0 ; i < fReturnSizePic ; i++ )
934 aop->aopu.aop_str[i] = fReturn[i];
936 DEBUGpic14_emitcode(";","%d",__LINE__);
941 /* else spill location */
942 if (sym->usl.spillLoc)
944 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
946 /* force a new aop if sizes differ */
947 sym->usl.spillLoc->aop = NULL;
949 DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
950 __FUNCTION__,__LINE__,
951 sym->usl.spillLoc->rname,
952 sym->rname, sym->usl.spillLoc->offset);
954 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
955 //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
956 aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname,
958 sym->usl.spillLoc->offset);
959 aop->size = getSize(sym->type);
966 sym_link *type = operandType(op);
967 if(IS_PTR_CONST(type))
968 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
971 /* must be in a register */
972 DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
973 sym->aop = op->aop = aop = newAsmop(AOP_REG);
974 aop->size = sym->nRegs;
975 for ( i = 0 ; i < sym->nRegs ;i++)
976 aop->aopu.aop_reg[i] = sym->regs[i];
979 /*-----------------------------------------------------------------*/
980 /* freeAsmop - free up the asmop given to an operand */
981 /*----------------------------------------------------------------*/
982 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
999 /* depending on the asmop type only three cases need work AOP_RO
1000 , AOP_R1 && AOP_STK */
1002 switch (aop->type) {
1006 pic14_emitcode ("pop","ar0");
1010 bitVectUnSetBit(ic->rUsed,R0_IDX);
1016 pic14_emitcode ("pop","ar1");
1020 bitVectUnSetBit(ic->rUsed,R1_IDX);
1026 int stk = aop->aopu.aop_stk + aop->size;
1027 bitVectUnSetBit(ic->rUsed,R0_IDX);
1028 bitVectUnSetBit(ic->rUsed,R1_IDX);
1030 getFreePtr(ic,&aop,FALSE);
1032 if (options.stack10bit)
1034 /* I'm not sure what to do here yet... */
1037 "*** Warning: probably generating bad code for "
1038 "10 bit stack mode.\n");
1042 pic14_emitcode ("mov","a,_bp");
1043 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1044 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1046 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1050 pic14_emitcode("pop","acc");
1051 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1053 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1056 freeAsmop(op,NULL,ic,TRUE);
1058 pic14_emitcode("pop","ar0");
1063 pic14_emitcode("pop","ar1");
1071 /* all other cases just dealloc */
1075 OP_SYMBOL(op)->aop = NULL;
1076 /* if the symbol has a spill */
1078 SPIL_LOC(op)->aop = NULL;
1083 /*-----------------------------------------------------------------*/
1084 /* aopGet - for fetching value of the aop */
1085 /*-----------------------------------------------------------------*/
1086 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1091 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1092 /* offset is greater than
1094 if (offset > (aop->size - 1) &&
1095 aop->type != AOP_LIT)
1098 /* depending on type */
1099 switch (aop->type) {
1103 DEBUGpic14_emitcode(";","%d",__LINE__);
1104 /* if we need to increment it */
1105 while (offset > aop->coff) {
1106 pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);
1110 while (offset < aop->coff) {
1111 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1115 aop->coff = offset ;
1117 pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1118 return (dname ? "acc" : "a");
1120 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1121 rs = Safe_calloc(1,strlen(s)+1);
1127 DEBUGpic14_emitcode(";","%d",__LINE__);
1128 if (aop->type == AOP_DPTR2)
1133 while (offset > aop->coff) {
1134 pic14_emitcode ("inc","dptr");
1138 while (offset < aop->coff) {
1139 pic14_emitcode("lcall","__decdptr");
1145 pic14_emitcode("clr","a");
1146 pic14_emitcode("movc","a,@a+dptr");
1149 pic14_emitcode("movx","a,@dptr");
1152 if (aop->type == AOP_DPTR2)
1157 return (dname ? "acc" : "a");
1162 sprintf (s,"%s",aop->aopu.aop_immd);
1165 sprintf(s,"(%s >> %d)",
1170 aop->aopu.aop_immd);
1171 DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1172 rs = Safe_calloc(1,strlen(s)+1);
1178 sprintf(s,"(%s + %d)",
1181 DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1183 sprintf(s,"%s",aop->aopu.aop_dir);
1184 rs = Safe_calloc(1,strlen(s)+1);
1190 // return aop->aopu.aop_reg[offset]->dname;
1192 return aop->aopu.aop_reg[offset]->name;
1195 //pic14_emitcode(";","%d",__LINE__);
1196 return aop->aopu.aop_dir;
1199 DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1200 return "AOP_accumulator_bug";
1203 sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1204 rs = Safe_calloc(1,strlen(s)+1);
1209 aop->coff = offset ;
1210 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1213 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1215 return aop->aopu.aop_str[offset];
1219 pCodeOp *pcop = aop->aopu.pcop;
1220 DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1223 DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
1224 sprintf(s,"(%s+%d)", pcop->name,offset);
1226 DEBUGpic14_emitcode(";","%s",pcop->name);
1227 sprintf(s,"%s", pcop->name);
1230 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1233 rs = Safe_calloc(1,strlen(s)+1);
1239 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1240 "aopget got unsupported aop->type");
1245 /*-----------------------------------------------------------------*/
1246 /* popGetTempReg - create a new temporary pCodeOp */
1247 /*-----------------------------------------------------------------*/
1248 pCodeOp *popGetTempReg(void)
1253 pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1254 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1255 PCOR(pcop)->r->wasUsed=1;
1256 PCOR(pcop)->r->isFree=0;
1262 /*-----------------------------------------------------------------*/
1263 /* popReleaseTempReg - create a new temporary pCodeOp */
1264 /*-----------------------------------------------------------------*/
1265 void popReleaseTempReg(pCodeOp *pcop)
1268 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1269 PCOR(pcop)->r->isFree = 1;
1272 /*-----------------------------------------------------------------*/
1273 /* popGetLabel - create a new pCodeOp of type PO_LABEL */
1274 /*-----------------------------------------------------------------*/
1275 pCodeOp *popGetLabel(unsigned int key)
1278 DEBUGpic14_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1280 if(key>(unsigned int)max_key)
1283 return newpCodeOpLabel(NULL,key+100+labelOffset);
1286 /*-------------------------------------------------------------------*/
1287 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1288 /*-------------------------------------------------------------------*/
1289 pCodeOp *popGetHighLabel(unsigned int key)
1292 pcop = popGetLabel(key);
1293 PCOLAB(pcop)->offset = 1;
1297 /*-----------------------------------------------------------------*/
1298 /* popGetLit - asm operator to pcode operator conversion */
1299 /*-----------------------------------------------------------------*/
1300 pCodeOp *popGetLit(unsigned int lit)
1303 return newpCodeOpLit((unsigned char)lit);
1306 /*-----------------------------------------------------------------*/
1307 /* popGetImmd - asm operator to pcode immediate conversion */
1308 /*-----------------------------------------------------------------*/
1309 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1312 return newpCodeOpImmd(name, offset,index, 0, is_func);
1315 extern set *externs;
1317 /*-----------------------------------------------------------------*/
1318 /* popGetWithString - asm operator to pcode operator conversion */
1319 /*-----------------------------------------------------------------*/
1320 pCodeOp *popGetWithString(char *str, int isExtern)
1326 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1330 pcop = newpCodeOp(str,PO_STR);
1331 PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1336 pCodeOp *popGetExternal (char *str)
1338 pCodeOp *pcop = popGetWithString (str, 1);
1344 for (sym = setFirstItem (externs); !found && sym; sym = setNextItem (externs))
1346 if (!strcmp (str, sym->rname))
1352 sym = newSymbol(str, 0);
1353 strncpy(sym->rname, str, SDCC_NAME_MAX);
1354 addSet (&externs, sym);
1360 /*-----------------------------------------------------------------*/
1361 /* popRegFromString - */
1362 /*-----------------------------------------------------------------*/
1363 pCodeOp *popRegFromString(char *str, int size, int offset)
1366 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1367 pcop->type = PO_DIR;
1369 DEBUGpic14_emitcode(";","%d",__LINE__);
1374 pcop->name = Safe_calloc(1,strlen(str)+1);
1375 strcpy(pcop->name,str);
1377 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1379 PCOR(pcop)->r = dirregWithName(pcop->name);
1380 if(PCOR(pcop)->r == NULL) {
1381 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1382 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1383 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1385 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1387 PCOR(pcop)->instance = offset;
1392 /*-----------------------------------------------------------------*/
1393 /*-----------------------------------------------------------------*/
1394 pCodeOp *popRegFromIdx(int rIdx)
1398 DEBUGpic14_emitcode ("; ***","%s,%d , rIdx=0x%x",
1399 __FUNCTION__,__LINE__,rIdx);
1401 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1403 PCOR(pcop)->rIdx = rIdx;
1404 PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1405 PCOR(pcop)->r->isFree = 0;
1406 PCOR(pcop)->r->wasUsed = 1;
1408 pcop->type = PCOR(pcop)->r->pc_type;
1414 /*-----------------------------------------------------------------*/
1415 /* popGet - asm operator to pcode operator conversion */
1416 /*-----------------------------------------------------------------*/
1417 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1419 //char *s = buffer ;
1424 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1425 /* offset is greater than
1430 /* XXX: still needed for BIT operands (AOP_CRY) */
1431 if (offset > (aop->size - 1) &&
1432 aop->type != AOP_LIT)
1433 return NULL; //zero;
1435 /* depending on type */
1436 switch (aop->type) {
1443 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1447 DEBUGpic14_emitcode(";","%d",__LINE__);
1448 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1451 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1453 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1454 pcop->type = PO_DIR;
1456 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1457 strcpy(pcop->name,aop->aopu.aop_dir);
1458 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1459 if(PCOR(pcop)->r == NULL) {
1460 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1461 PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1462 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1464 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1466 PCOR(pcop)->instance = offset;
1474 assert (offset < aop->size);
1475 rIdx = aop->aopu.aop_reg[offset]->rIdx;
1477 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1478 PCOR(pcop)->rIdx = rIdx;
1479 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1480 PCOR(pcop)->r->wasUsed=1;
1481 PCOR(pcop)->r->isFree=0;
1483 PCOR(pcop)->instance = offset;
1484 pcop->type = PCOR(pcop)->r->pc_type;
1485 //rs = aop->aopu.aop_reg[offset]->name;
1486 DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1491 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1492 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1493 //if(PCOR(pcop)->r == NULL)
1494 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1498 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1501 DEBUGpic14_emitcode(";","%d %s",__LINE__,aop->aopu.aop_str[offset]);
1502 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1504 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1505 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1506 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1507 pcop->type = PCOR(pcop)->r->pc_type;
1508 pcop->name = PCOR(pcop)->r->name;
1515 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1517 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1518 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1519 switch (aop->aopu.pcop->type)
1522 pcop = pCodeOpCopy (aop->aopu.pcop);
1523 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1524 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1525 PCOI(pcop)->index += offset;
1526 //PCOI(pcop)->offset = 0;
1529 pcop = pCodeOpCopy (aop->aopu.pcop);
1530 PCOR(pcop)->instance = offset;
1533 assert ( !"unhandled pCode type" );
1539 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1540 "popGet got unsupported aop->type");
1544 /*-----------------------------------------------------------------*/
1545 /* popGetAddr - access the low/high word of a symbol (immediate) */
1546 /* (for non-PO_IMMEDIATEs this is the same as popGet) */
1547 /*-----------------------------------------------------------------*/
1548 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1550 if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1552 pCodeOp *pcop = aop->aopu.pcop;
1553 assert (offset <= GPTRSIZE);
1555 /* special case: index >= 2 should return GPOINTER-style values */
1558 pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1562 pcop = pCodeOpCopy (pcop);
1563 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1564 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1565 PCOI(pcop)->offset += offset;
1566 PCOI(pcop)->index += index;
1567 //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);
1570 return popGet (aop, offset + index);
1574 /*-----------------------------------------------------------------*/
1575 /* aopPut - puts a string for a aop */
1576 /*-----------------------------------------------------------------*/
1577 void aopPut (asmop *aop, char *s, int offset)
1582 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1584 if (aop->size && offset > ( aop->size - 1)) {
1585 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1586 "aopPut got offset > aop->size");
1590 /* will assign value to value */
1591 /* depending on where it is ofcourse */
1592 switch (aop->type) {
1595 sprintf(d,"(%s + %d)",
1596 aop->aopu.aop_dir,offset);
1597 fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1600 sprintf(d,"%s",aop->aopu.aop_dir);
1603 DEBUGpic14_emitcode(";","%d",__LINE__);
1605 pic14_emitcode("movf","%s,w",s);
1606 pic14_emitcode("movwf","%s",d);
1609 pic14_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
1610 if(offset >= aop->size) {
1611 emitpcode(POC_CLRF,popGet(aop,offset));
1614 emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
1617 emitpcode(POC_MOVWF,popGet(aop,offset));
1623 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1624 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1627 strcmp(s,"r0") == 0 ||
1628 strcmp(s,"r1") == 0 ||
1629 strcmp(s,"r2") == 0 ||
1630 strcmp(s,"r3") == 0 ||
1631 strcmp(s,"r4") == 0 ||
1632 strcmp(s,"r5") == 0 ||
1633 strcmp(s,"r6") == 0 ||
1634 strcmp(s,"r7") == 0 )
1635 pic14_emitcode("mov","%s,%s ; %d",
1636 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1640 if(strcmp(s,"W")==0 )
1641 pic14_emitcode("movf","%s,w ; %d",s,__LINE__);
1643 pic14_emitcode("movwf","%s",
1644 aop->aopu.aop_reg[offset]->name);
1646 if(strcmp(s,zero)==0) {
1647 emitpcode(POC_CLRF,popGet(aop,offset));
1649 } else if(strcmp(s,"W")==0) {
1650 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1651 pcop->type = PO_GPR_REGISTER;
1653 PCOR(pcop)->rIdx = -1;
1654 PCOR(pcop)->r = NULL;
1656 DEBUGpic14_emitcode(";","%d",__LINE__);
1657 pcop->name = Safe_strdup(s);
1658 emitpcode(POC_MOVFW,pcop);
1659 emitpcode(POC_MOVWF,popGet(aop,offset));
1660 } else if(strcmp(s,one)==0) {
1661 emitpcode(POC_CLRF,popGet(aop,offset));
1662 emitpcode(POC_INCF,popGet(aop,offset));
1664 emitpcode(POC_MOVWF,popGet(aop,offset));
1672 if (aop->type == AOP_DPTR2)
1678 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1679 "aopPut writting to code space");
1683 while (offset > aop->coff) {
1685 pic14_emitcode ("inc","dptr");
1688 while (offset < aop->coff) {
1690 pic14_emitcode("lcall","__decdptr");
1695 /* if not in accumulater */
1698 pic14_emitcode ("movx","@dptr,a");
1700 if (aop->type == AOP_DPTR2)
1708 while (offset > aop->coff) {
1710 pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1712 while (offset < aop->coff) {
1714 pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1720 pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1725 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1727 if (strcmp(s,"r0") == 0 ||
1728 strcmp(s,"r1") == 0 ||
1729 strcmp(s,"r2") == 0 ||
1730 strcmp(s,"r3") == 0 ||
1731 strcmp(s,"r4") == 0 ||
1732 strcmp(s,"r5") == 0 ||
1733 strcmp(s,"r6") == 0 ||
1734 strcmp(s,"r7") == 0 ) {
1736 sprintf(buffer,"a%s",s);
1737 pic14_emitcode("mov","@%s,%s",
1738 aop->aopu.aop_ptr->name,buffer);
1740 pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1745 if (strcmp(s,"a") == 0)
1746 pic14_emitcode("push","acc");
1748 pic14_emitcode("push","%s",s);
1753 /* if bit variable */
1754 if (!aop->aopu.aop_dir) {
1755 pic14_emitcode("clr","a");
1756 pic14_emitcode("rlc","a");
1759 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1762 pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1765 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1767 lbl = newiTempLabel(NULL);
1769 if (strcmp(s,"a")) {
1772 pic14_emitcode("clr","c");
1773 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1774 pic14_emitcode("cpl","c");
1775 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1776 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1783 if (strcmp(aop->aopu.aop_str[offset],s))
1784 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1789 if (!offset && (strcmp(s,"acc") == 0))
1792 if (strcmp(aop->aopu.aop_str[offset],s))
1793 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1797 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1798 "aopPut got unsupported aop->type");
1804 /*-----------------------------------------------------------------*/
1805 /* mov2w_op - generate either a MOVLW or MOVFW based operand type */
1806 /*-----------------------------------------------------------------*/
1807 static void mov2w_op (operand *op, int offset)
1812 /* for PO_IMMEDIATEs: use address or value? */
1813 if (op_isLitLike (op))
1815 /* access address of op */
1816 if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
1817 if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
1819 if (offset == GPTRSIZE-1)
1820 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1822 emitpcode (POC_MOVLW, popGetLit (0));
1825 emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
1827 /* access value stored in op */
1828 mov2w (AOP(op), offset);
1833 /*-----------------------------------------------------------------*/
1834 /* mov2w - generate either a MOVLW or MOVFW based operand type */
1835 /*-----------------------------------------------------------------*/
1836 void mov2w (asmop *aop, int offset)
1842 DEBUGpic14_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
1844 if ( aop_isLitLike (aop) )
1845 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1847 emitpcode(POC_MOVFW,popGet(aop,offset));
1851 static void movwf (asmop *op, int offset)
1853 emitpcode (POC_MOVWF, popGet(op, offset));
1856 static pCodeOp *get_argument_pcop (int idx)
1858 assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1859 return popRegFromIdx (Gstack_base_addr - (idx - 1));
1862 static pCodeOp *get_return_val_pcop (int offset)
1864 assert (offset > 0 && "the most significant byte is returned via WREG");
1865 return popRegFromIdx (Gstack_base_addr - (offset - 1));
1868 static void pass_argument (operand *op, int offset, int idx)
1871 mov2w_op (op, offset);
1873 emitpcode(POC_MOVWF, get_argument_pcop (idx));
1876 static void get_returnvalue (operand *op, int offset, int idx)
1879 emitpcode(POC_MOVFW, get_return_val_pcop (idx));
1880 movwf(AOP(op), offset);
1883 static void call_libraryfunc (char *name)
1885 /* library code might reside in different page... */
1886 emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1887 /* call the library function */
1888 emitpcode (POC_CALL, popGetExternal (name));
1889 /* might return from different page... */
1890 emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1893 /*-----------------------------------------------------------------*/
1894 /* reAdjustPreg - points a register back to where it should */
1895 /*-----------------------------------------------------------------*/
1896 static void reAdjustPreg (asmop *aop)
1900 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1902 if ((size = aop->size) <= 1)
1905 switch (aop->type) {
1909 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1913 if (aop->type == AOP_DPTR2)
1919 pic14_emitcode("lcall","__decdptr");
1922 if (aop->type == AOP_DPTR2)
1935 /*-----------------------------------------------------------------*/
1936 /* opIsGptr: returns non-zero if the passed operand is */
1937 /* a generic pointer type. */
1938 /*-----------------------------------------------------------------*/
1939 static int opIsGptr(operand *op)
1941 sym_link *type = operandType(op);
1943 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1944 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1952 /*-----------------------------------------------------------------*/
1953 /* pic14_getDataSize - get the operand data size */
1954 /*-----------------------------------------------------------------*/
1955 int pic14_getDataSize(operand *op)
1959 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1962 size = getSize(OP_SYM_ETYPE(op));
1964 //return AOP_SIZE(op);
1966 // tsd- in the pic port, the genptr size is 1, so this code here
1967 // fails. ( in the 8051 port, the size was 4).
1969 size = AOP_SIZE(op);
1970 if (IS_GENPTR(OP_SYM_TYPE(op)))
1972 sym_link *type = operandType(op);
1973 if (IS_GENPTR(type))
1975 /* generic pointer; arithmetic operations
1976 * should ignore the high byte (pointer type).
1979 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1986 /*-----------------------------------------------------------------*/
1987 /* pic14_outAcc - output Acc */
1988 /*-----------------------------------------------------------------*/
1989 void pic14_outAcc(operand *result)
1992 DEBUGpic14_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
1993 DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1996 size = pic14_getDataSize(result);
1998 emitpcode(POC_MOVWF,popGet(AOP(result),0));
2001 /* unsigned or positive */
2003 emitpcode(POC_CLRF,popGet(AOP(result),offset++));
2008 /*-----------------------------------------------------------------*/
2009 /* pic14_outBitC - output a bit C */
2010 /*-----------------------------------------------------------------*/
2011 void pic14_outBitC(operand *result)
2014 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2015 /* if the result is bit */
2016 if (AOP_TYPE(result) == AOP_CRY)
2017 aopPut(AOP(result),"c",0);
2019 pic14_emitcode("clr","a ; %d", __LINE__);
2020 pic14_emitcode("rlc","a");
2021 pic14_outAcc(result);
2025 /*-----------------------------------------------------------------*/
2026 /* pic14_toBoolean - emit code for orl a,operator(sizeop) */
2027 /*-----------------------------------------------------------------*/
2028 void pic14_toBoolean(operand *oper)
2030 int size = AOP_SIZE(oper);
2033 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2038 /* MOVFW does not load the flags... */
2039 if (AOP_TYPE(oper) == AOP_ACC) {
2040 emitpcode(POC_IORLW, popGetLit(0));
2043 emitpcode(POC_MOVLW, popGetLit(0));
2047 if ( AOP_TYPE(oper) != AOP_ACC) {
2048 emitpcode(POC_MOVFW,popGet(AOP(oper),0));
2053 while (offset < size) {
2054 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
2056 /* Z is set iff (oper == 0) */
2060 /*-----------------------------------------------------------------*/
2061 /* genNot - generate code for ! operation */
2062 /*-----------------------------------------------------------------*/
2063 static void genNot (iCode *ic)
2070 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2071 /* assign asmOps to operand & result */
2072 aopOp (IC_LEFT(ic),ic,FALSE);
2073 aopOp (IC_RESULT(ic),ic,TRUE);
2075 DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2076 /* if in bit space then a special case */
2077 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2078 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2079 emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
2080 emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
2082 emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
2083 emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
2084 emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
2089 size = AOP_SIZE(IC_LEFT(ic));
2090 mov2w (AOP(IC_LEFT(ic)),0);
2093 if (op_isLitLike (IC_LEFT(ic)))
2094 emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
2096 emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
2098 emitpcode(POC_MOVLW, popGetLit (0));
2100 emitpcode(POC_MOVLW, popGetLit (1));
2101 movwf(AOP(IC_RESULT(ic)), 0);
2103 for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
2105 emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
2110 /* release the aops */
2111 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2112 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2116 /*-----------------------------------------------------------------*/
2117 /* genCpl - generate code for complement */
2118 /*-----------------------------------------------------------------*/
2119 static void genCpl (iCode *ic)
2121 operand *left, *result;
2126 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2127 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2128 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2130 /* if both are in bit space then
2132 if (AOP_TYPE(result) == AOP_CRY &&
2133 AOP_TYPE(left) == AOP_CRY ) {
2135 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir);
2136 pic14_emitcode("cpl","c");
2137 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir);
2141 size = AOP_SIZE(result);
2142 if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
2145 if(AOP_TYPE(left) == AOP_ACC)
2146 emitpcode(POC_XORLW, popGetLit(0xff));
2148 emitpcode(POC_COMFW,popGet(AOP(left),offset));
2150 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
2153 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2157 /* release the aops */
2158 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2159 freeAsmop(result,NULL,ic,TRUE);
2162 /*-----------------------------------------------------------------*/
2163 /* genUminusFloat - unary minus for floating points */
2164 /*-----------------------------------------------------------------*/
2165 static void genUminusFloat(operand *op,operand *result)
2167 int size ,offset =0 ;
2172 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2173 /* for this we just need to flip the
2174 first it then copy the rest in place */
2175 size = AOP_SIZE(op) - 1;
2176 l = aopGet(AOP(op),3,FALSE,FALSE);
2180 pic14_emitcode("cpl","acc.7");
2181 aopPut(AOP(result),"a",3);
2185 aopGet(AOP(op),offset,FALSE,FALSE),
2191 /*-----------------------------------------------------------------*/
2192 /* genUminus - unary minus code generation */
2193 /*-----------------------------------------------------------------*/
2194 static void genUminus (iCode *ic)
2197 sym_link *optype, *rtype;
2201 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2203 aopOp(IC_LEFT(ic),ic,FALSE);
2204 aopOp(IC_RESULT(ic),ic,TRUE);
2206 /* if both in bit space then special
2208 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2209 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2211 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0));
2212 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2213 emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0));
2218 optype = operandType(IC_LEFT(ic));
2219 rtype = operandType(IC_RESULT(ic));
2221 /* if float then do float stuff */
2222 if (IS_FLOAT(optype)) {
2223 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2227 /* otherwise subtract from zero by taking the 2's complement */
2228 size = AOP_SIZE(IC_LEFT(ic));
2230 for(i=0; i<size; i++) {
2231 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2232 emitpcode(POC_COMF, popGet(AOP(IC_LEFT(ic)),i));
2234 emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2235 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2239 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0));
2240 for(i=1; i<size; i++) {
2242 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),i));
2246 /* release the aops */
2247 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2248 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2251 /*-----------------------------------------------------------------*/
2252 /* saveRegisters - will look for a call and save the registers */
2253 /*-----------------------------------------------------------------*/
2254 static void saveRegisters(iCode *lic)
2263 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2265 for (ic = lic ; ic ; ic = ic->next)
2266 if (ic->op == CALL || ic->op == PCALL)
2270 fprintf(stderr,"found parameter push with no function call\n");
2274 /* if the registers have been saved already then
2276 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2279 /* find the registers in use at this time
2280 and push them away to safety */
2281 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2285 if (options.useXstack) {
2286 if (bitVectBitValue(rsave,R0_IDX))
2287 pic14_emitcode("mov","b,r0");
2288 pic14_emitcode("mov","r0,%s",spname);
2289 for (i = 0 ; i < pic14_nRegs ; i++) {
2290 if (bitVectBitValue(rsave,i)) {
2292 pic14_emitcode("mov","a,b");
2294 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2295 pic14_emitcode("movx","@r0,a");
2296 pic14_emitcode("inc","r0");
2299 pic14_emitcode("mov","%s,r0",spname);
2300 if (bitVectBitValue(rsave,R0_IDX))
2301 pic14_emitcode("mov","r0,b");
2303 //for (i = 0 ; i < pic14_nRegs ; i++) {
2304 // if (bitVectBitValue(rsave,i))
2305 // pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2308 dtype = operandType(IC_LEFT(ic));
2309 if (currFunc && dtype &&
2310 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2311 IFFUNC_ISISR(currFunc->type) &&
2314 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2317 /*-----------------------------------------------------------------*/
2318 /* unsaveRegisters - pop the pushed registers */
2319 /*-----------------------------------------------------------------*/
2320 static void unsaveRegisters (iCode *ic)
2327 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2328 /* find the registers in use at this time
2329 and push them away to safety */
2330 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2333 if (options.useXstack) {
2334 pic14_emitcode("mov","r0,%s",spname);
2335 for (i = pic14_nRegs ; i >= 0 ; i--) {
2336 if (bitVectBitValue(rsave,i)) {
2337 pic14_emitcode("dec","r0");
2338 pic14_emitcode("movx","a,@r0");
2340 pic14_emitcode("mov","b,a");
2342 pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2346 pic14_emitcode("mov","%s,r0",spname);
2347 if (bitVectBitValue(rsave,R0_IDX))
2348 pic14_emitcode("mov","r0,b");
2350 //for (i = pic14_nRegs ; i >= 0 ; i--) {
2351 // if (bitVectBitValue(rsave,i))
2352 // pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2358 /*-----------------------------------------------------------------*/
2360 /*-----------------------------------------------------------------*/
2361 static void pushSide(operand * oper, int size)
2365 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2367 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2368 if (AOP_TYPE(oper) != AOP_REG &&
2369 AOP_TYPE(oper) != AOP_DIR &&
2371 pic14_emitcode("mov","a,%s",l);
2372 pic14_emitcode("push","acc");
2374 pic14_emitcode("push","%s",l);
2379 /*-----------------------------------------------------------------*/
2380 /* assignResultValue - */
2381 /*-----------------------------------------------------------------*/
2382 static void assignResultValue(operand * oper)
2384 int size = AOP_SIZE(oper);
2389 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2391 DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2393 /* assign MSB first (passed via WREG) */
2395 get_returnvalue (oper, size, offset + GpsuedoStkPtr);
2401 /*-----------------------------------------------------------------*/
2402 /* genIpush - genrate code for pushing this gets a little complex */
2403 /*-----------------------------------------------------------------*/
2404 static void genIpush (iCode *ic)
2408 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2410 int size, offset = 0 ;
2414 /* if this is not a parm push : ie. it is spill push
2415 and spill push is always done on the local stack */
2416 if (!ic->parmPush) {
2418 /* and the item is spilt then do nothing */
2419 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2422 aopOp(IC_LEFT(ic),ic,FALSE);
2423 size = AOP_SIZE(IC_LEFT(ic));
2424 /* push it on the stack */
2426 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2431 pic14_emitcode("push","%s",l);
2436 /* this is a paramter push: in this case we call
2437 the routine to find the call and save those
2438 registers that need to be saved */
2441 /* then do the push */
2442 aopOp(IC_LEFT(ic),ic,FALSE);
2445 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2446 size = AOP_SIZE(IC_LEFT(ic));
2449 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2450 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
2451 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2453 pic14_emitcode("mov","a,%s",l);
2454 pic14_emitcode("push","acc");
2456 pic14_emitcode("push","%s",l);
2459 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2463 /*-----------------------------------------------------------------*/
2464 /* genIpop - recover the registers: can happen only for spilling */
2465 /*-----------------------------------------------------------------*/
2466 static void genIpop (iCode *ic)
2470 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2471 assert (!"genIpop -- unimplemented");
2476 /* if the temp was not pushed then */
2477 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2480 aopOp(IC_LEFT(ic),ic,FALSE);
2481 size = AOP_SIZE(IC_LEFT(ic));
2484 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2487 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2491 /*-----------------------------------------------------------------*/
2492 /* unsaverbank - restores the resgister bank from stack */
2493 /*-----------------------------------------------------------------*/
2494 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2498 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2504 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2506 if (options.useXstack) {
2508 r = getFreePtr(ic,&aop,FALSE);
2511 pic14_emitcode("mov","%s,_spx",r->name);
2512 pic14_emitcode("movx","a,@%s",r->name);
2513 pic14_emitcode("mov","psw,a");
2514 pic14_emitcode("dec","%s",r->name);
2517 pic14_emitcode ("pop","psw");
2520 for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2521 if (options.useXstack) {
2522 pic14_emitcode("movx","a,@%s",r->name);
2523 //pic14_emitcode("mov","(%s+%d),a",
2524 // regspic14[i].base,8*bank+regspic14[i].offset);
2525 pic14_emitcode("dec","%s",r->name);
2528 pic14_emitcode("pop",""); //"(%s+%d)",
2529 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2532 if (options.useXstack) {
2534 pic14_emitcode("mov","_spx,%s",r->name);
2535 freeAsmop(NULL,aop,ic,TRUE);
2541 /*-----------------------------------------------------------------*/
2542 /* saverbank - saves an entire register bank on the stack */
2543 /*-----------------------------------------------------------------*/
2544 static void saverbank (int bank, iCode *ic, bool pushPsw)
2548 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2554 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2555 if (options.useXstack) {
2558 r = getFreePtr(ic,&aop,FALSE);
2559 pic14_emitcode("mov","%s,_spx",r->name);
2563 for (i = 0 ; i < pic14_nRegs ;i++) {
2564 if (options.useXstack) {
2565 pic14_emitcode("inc","%s",r->name);
2566 //pic14_emitcode("mov","a,(%s+%d)",
2567 // regspic14[i].base,8*bank+regspic14[i].offset);
2568 pic14_emitcode("movx","@%s,a",r->name);
2570 pic14_emitcode("push","");// "(%s+%d)",
2571 //regspic14[i].base,8*bank+regspic14[i].offset);
2575 if (options.useXstack) {
2576 pic14_emitcode("mov","a,psw");
2577 pic14_emitcode("movx","@%s,a",r->name);
2578 pic14_emitcode("inc","%s",r->name);
2579 pic14_emitcode("mov","_spx,%s",r->name);
2580 freeAsmop (NULL,aop,ic,TRUE);
2583 pic14_emitcode("push","psw");
2585 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2591 /*-----------------------------------------------------------------*/
2592 /* genCall - generates a call statement */
2593 /*-----------------------------------------------------------------*/
2594 static void genCall (iCode *ic)
2598 unsigned char *name;
2603 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2605 /* if caller saves & we have not saved then */
2609 /* if we are calling a function that is not using
2610 the same register bank then we need to save the
2611 destination registers on the stack */
2612 dtype = operandType(IC_LEFT(ic));
2613 if (currFunc && dtype &&
2614 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2615 IFFUNC_ISISR(currFunc->type) &&
2618 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2620 /* if send set is not empty the assign */
2623 /* For the Pic port, there is no data stack.
2624 * So parameters passed to functions are stored
2625 * in registers. (The pCode optimizer will get
2626 * rid of most of these :).
2628 int psuedoStkPtr=-1;
2629 int firstTimeThruLoop = 1;
2631 _G.sendSet = reverseSet(_G.sendSet);
2633 /* First figure how many parameters are getting passed */
2634 for (sic = setFirstItem(_G.sendSet) ; sic ;
2635 sic = setNextItem(_G.sendSet)) {
2637 aopOp(IC_LEFT(sic),sic,FALSE);
2638 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2639 freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2642 for (sic = setFirstItem(_G.sendSet) ; sic ;
2643 sic = setNextItem(_G.sendSet)) {
2644 int size, offset = 0;
2646 aopOp(IC_LEFT(sic),sic,FALSE);
2647 size = AOP_SIZE(IC_LEFT(sic));
2650 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2651 AopType(AOP_TYPE(IC_LEFT(sic))));
2653 if(!firstTimeThruLoop) {
2654 /* If this is not the first time we've been through the loop
2655 * then we need to save the parameter in a temporary
2656 * register. The last byte of the last parameter is
2658 emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2661 firstTimeThruLoop=0;
2663 mov2w_op (IC_LEFT(sic), offset);
2666 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2671 sym = OP_SYMBOL(IC_LEFT(ic));
2672 name = sym->rname[0] ? sym->rname : sym->name;
2673 isExtern = IS_EXTERN(sym->etype);
2675 emitpcode(POC_PAGESEL,popGetWithString(name,1)); /* Extern functions maybe on another page - must call pagesel */
2677 emitpcode(POC_CALL,popGetWithString(name,isExtern));
2679 emitpcode(POC_PAGESEL,popGetWithString("$",0)); /* May have returned from another page - must call pagesel to restore PCLATH before next goto or call instruction */
2682 /* if we need assign a result value */
2683 if ((IS_ITEMP(IC_RESULT(ic)) &&
2684 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2685 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2686 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2689 aopOp(IC_RESULT(ic),ic,FALSE);
2692 assignResultValue(IC_RESULT(ic));
2694 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2695 AopType(AOP_TYPE(IC_RESULT(ic))));
2697 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2700 /* if register bank was saved then pop them */
2702 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2704 /* if we hade saved some registers then unsave them */
2705 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2706 unsaveRegisters (ic);
2711 /*-----------------------------------------------------------------*/
2712 /* genPcall - generates a call by pointer statement */
2713 /*-----------------------------------------------------------------*/
2714 static void genPcall (iCode *ic)
2717 symbol *albl = newiTempLabel(NULL);
2718 symbol *blbl = newiTempLabel(NULL);
2725 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2726 /* if caller saves & we have not saved then */
2730 /* if we are calling a function that is not using
2731 the same register bank then we need to save the
2732 destination registers on the stack */
2733 dtype = operandType(IC_LEFT(ic));
2734 if (currFunc && dtype &&
2735 IFFUNC_ISISR(currFunc->type) &&
2736 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2737 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2740 aopOp(left,ic,FALSE);
2741 DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2743 poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2745 pushSide(IC_LEFT(ic), FPTRSIZE);
2747 /* if send set is not empty, assign parameters */
2750 DEBUGpic14_emitcode ("; ***","%s %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2751 /* no way to pass args - W always gets used to make the call */
2753 /* first idea - factor out a common helper function and call it.
2754 But don't know how to get it generated only once in its own block
2756 if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2759 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2760 DEBUGpic14_emitcode ("; ***","%s %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2761 buffer = Safe_calloc(1,strlen(rname)+16);
2762 sprintf(buffer, "%s_goto_helper", rname);
2763 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2767 emitpcode(POC_CALL,popGetLabel(albl->key));
2768 pcop = popGetLabel(blbl->key);
2769 emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
2770 emitpcode(POC_GOTO,pcop);
2771 emitpLabel(albl->key);
2773 emitpcode(poc,popGetAddr(AOP(left),1,0));
2774 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2775 emitpcode(poc,popGetAddr(AOP(left),0,0));
2776 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2778 emitpLabel(blbl->key);
2780 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2782 /* if we need to assign a result value */
2783 if ((IS_ITEMP(IC_RESULT(ic)) &&
2784 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2785 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2786 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2789 aopOp(IC_RESULT(ic),ic,FALSE);
2794 assignResultValue(IC_RESULT(ic));
2796 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2799 /* if register bank was saved then unsave them */
2800 if (currFunc && dtype &&
2801 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2802 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2804 /* if we hade saved some registers then
2807 unsaveRegisters (ic);
2811 /*-----------------------------------------------------------------*/
2812 /* resultRemat - result is rematerializable */
2813 /*-----------------------------------------------------------------*/
2814 static int resultRemat (iCode *ic)
2816 // DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2819 if (SKIP_IC(ic) || ic->op == IFX)
2822 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2823 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2824 if (sym->remat && !POINTER_SET(ic))
2831 #if defined(__BORLANDC__) || defined(_MSC_VER)
2832 #define STRCASECMP stricmp
2834 #define STRCASECMP strcasecmp
2838 /*-----------------------------------------------------------------*/
2839 /* inExcludeList - return 1 if the string is in exclude Reg list */
2840 /*-----------------------------------------------------------------*/
2841 static bool inExcludeList(char *s)
2843 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2846 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2847 if (options.excludeRegs[i] &&
2848 STRCASECMP(options.excludeRegs[i],"none") == 0)
2851 for ( i = 0 ; options.excludeRegs[i]; i++) {
2852 if (options.excludeRegs[i] &&
2853 STRCASECMP(s,options.excludeRegs[i]) == 0)
2860 /*-----------------------------------------------------------------*/
2861 /* genFunction - generated code for function entry */
2862 /*-----------------------------------------------------------------*/
2863 static void genFunction (iCode *ic)
2870 DEBUGpic14_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2872 labelOffset += (max_key+4);
2876 /* create the function header */
2877 pic14_emitcode(";","-----------------------------------------");
2878 pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2879 pic14_emitcode(";","-----------------------------------------");
2881 pic14_emitcode("","%s:",sym->rname);
2882 addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2884 ftype = operandType(IC_LEFT(ic));
2886 /* if critical function then turn interrupts off */
2887 if (IFFUNC_ISCRITICAL(ftype))
2888 pic14_emitcode("clr","ea");
2890 /* here we need to generate the equates for the
2891 register bank if required */
2893 if (FUNC_REGBANK(ftype) != rbank) {
2896 rbank = FUNC_REGBANK(ftype);
2897 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2898 if (strcmp(regspic14[i].base,"0") == 0)
2899 pic14_emitcode("","%s = 0x%02x",
2901 8*rbank+regspic14[i].offset);
2903 pic14_emitcode ("","%s = %s + 0x%02x",
2906 8*rbank+regspic14[i].offset);
2911 /* if this is an interrupt service routine */
2912 if (IFFUNC_ISISR(sym->type)) {
2913 /* already done in pic14createInterruptVect() - delete me
2914 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2915 emitpcodeNULLop(POC_NOP);
2916 emitpcodeNULLop(POC_NOP);
2917 emitpcodeNULLop(POC_NOP);
2919 emitpcode(POC_MOVWF, popCopyReg(&pc_wsave));
2920 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2921 emitpcode(POC_CLRF, popCopyReg(&pc_status));
2922 emitpcode(POC_MOVWF, popCopyReg(&pc_ssave));
2923 emitpcode(POC_MOVFW, popCopyReg(&pc_pclath));
2924 emitpcode(POC_MOVWF, popCopyReg(&pc_psave));
2925 emitpcode(POC_CLRF, popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2927 pBlockConvert2ISR(pb);
2929 if (!inExcludeList("acc"))
2930 pic14_emitcode ("push","acc");
2931 if (!inExcludeList("b"))
2932 pic14_emitcode ("push","b");
2933 if (!inExcludeList("dpl"))
2934 pic14_emitcode ("push","dpl");
2935 if (!inExcludeList("dph"))
2936 pic14_emitcode ("push","dph");
2937 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2939 pic14_emitcode ("push", "dpx");
2940 /* Make sure we're using standard DPTR */
2941 pic14_emitcode ("push", "dps");
2942 pic14_emitcode ("mov", "dps, #0x00");
2943 if (options.stack10bit)
2945 /* This ISR could conceivably use DPTR2. Better save it. */
2946 pic14_emitcode ("push", "dpl1");
2947 pic14_emitcode ("push", "dph1");
2948 pic14_emitcode ("push", "dpx1");
2951 /* if this isr has no bank i.e. is going to
2952 run with bank 0 , then we need to save more
2954 if (!FUNC_REGBANK(sym->type)) {
2956 /* if this function does not call any other
2957 function then we can be economical and
2958 save only those registers that are used */
2959 if (! IFFUNC_HASFCALL(sym->type)) {
2962 /* if any registers used */
2963 if (sym->regsUsed) {
2964 /* save the registers used */
2965 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2966 if (bitVectBitValue(sym->regsUsed,i) ||
2967 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2968 pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);
2973 /* this function has a function call cannot
2974 determines register usage so we will have the
2976 saverbank(0,ic,FALSE);
2981 /* if callee-save to be used for this function
2982 then save the registers being used in this function */
2983 if (IFFUNC_CALLEESAVES(sym->type)) {
2986 /* if any registers used */
2987 if (sym->regsUsed) {
2988 /* save the registers used */
2989 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2990 if (bitVectBitValue(sym->regsUsed,i) ||
2991 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2992 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
3000 /* set the register bank to the desired value */
3001 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
3002 pic14_emitcode("push","psw");
3003 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);
3006 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3008 if (options.useXstack) {
3009 pic14_emitcode("mov","r0,%s",spname);
3010 pic14_emitcode("mov","a,_bp");
3011 pic14_emitcode("movx","@r0,a");
3012 pic14_emitcode("inc","%s",spname);
3016 /* set up the stack */
3017 pic14_emitcode ("push","_bp"); /* save the callers stack */
3019 pic14_emitcode ("mov","_bp,%s",spname);
3022 /* adjust the stack for the function */
3027 werror(W_STACK_OVERFLOW,sym->name);
3029 if (i > 3 && sym->recvSize < 4) {
3031 pic14_emitcode ("mov","a,sp");
3032 pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3033 pic14_emitcode ("mov","sp,a");
3038 pic14_emitcode("inc","sp");
3043 pic14_emitcode ("mov","a,_spx");
3044 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3045 pic14_emitcode ("mov","_spx,a");
3050 /*-----------------------------------------------------------------*/
3051 /* genEndFunction - generates epilogue for functions */
3052 /*-----------------------------------------------------------------*/
3053 static void genEndFunction (iCode *ic)
3055 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3059 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3061 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3063 pic14_emitcode ("mov","%s,_bp",spname);
3066 /* if use external stack but some variables were
3067 added to the local stack then decrement the
3069 if (options.useXstack && sym->stack) {
3070 pic14_emitcode("mov","a,sp");
3071 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3072 pic14_emitcode("mov","sp,a");
3076 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3077 if (options.useXstack) {
3078 pic14_emitcode("mov","r0,%s",spname);
3079 pic14_emitcode("movx","a,@r0");
3080 pic14_emitcode("mov","_bp,a");
3081 pic14_emitcode("dec","%s",spname);
3085 pic14_emitcode ("pop","_bp");
3089 /* restore the register bank */
3090 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3091 pic14_emitcode ("pop","psw");
3093 if (IFFUNC_ISISR(sym->type)) {
3095 /* now we need to restore the registers */
3096 /* if this isr has no bank i.e. is going to
3097 run with bank 0 , then we need to save more
3099 if (!FUNC_REGBANK(sym->type)) {
3101 /* if this function does not call any other
3102 function then we can be economical and
3103 save only those registers that are used */
3104 if (! IFFUNC_HASFCALL(sym->type)) {
3107 /* if any registers used */
3108 if (sym->regsUsed) {
3109 /* save the registers used */
3110 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3111 if (bitVectBitValue(sym->regsUsed,i) ||
3112 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3113 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3118 /* this function has a function call cannot
3119 determines register usage so we will have the
3121 unsaverbank(0,ic,FALSE);
3125 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3127 if (options.stack10bit)
3129 pic14_emitcode ("pop", "dpx1");
3130 pic14_emitcode ("pop", "dph1");
3131 pic14_emitcode ("pop", "dpl1");
3133 pic14_emitcode ("pop", "dps");
3134 pic14_emitcode ("pop", "dpx");
3136 if (!inExcludeList("dph"))
3137 pic14_emitcode ("pop","dph");
3138 if (!inExcludeList("dpl"))
3139 pic14_emitcode ("pop","dpl");
3140 if (!inExcludeList("b"))
3141 pic14_emitcode ("pop","b");
3142 if (!inExcludeList("acc"))
3143 pic14_emitcode ("pop","acc");
3145 if (IFFUNC_ISCRITICAL(sym->type))
3146 pic14_emitcode("setb","ea");
3149 /* if debug then send end of function */
3150 /* if (options.debug && currFunc) { */
3152 debugFile->writeEndFunction (currFunc, ic, 1);
3155 pic14_emitcode ("reti","");
3156 emitpcode(POC_MOVFW, popCopyReg(&pc_psave));
3157 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
3158 emitpcode(POC_CLRF, popCopyReg(&pc_status));
3159 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3160 emitpcode(POC_MOVWF, popCopyReg(&pc_status));
3161 emitpcode(POC_SWAPF, popCopyReg(&pc_wsave));
3162 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3163 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3164 emitpcodeNULLop(POC_RETFIE);
3167 if (IFFUNC_ISCRITICAL(sym->type))
3168 pic14_emitcode("setb","ea");
3170 if (IFFUNC_CALLEESAVES(sym->type)) {
3173 /* if any registers used */
3174 if (sym->regsUsed) {
3175 /* save the registers used */
3176 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3177 if (bitVectBitValue(sym->regsUsed,i) ||
3178 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3179 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3185 /* if debug then send end of function */
3187 debugFile->writeEndFunction (currFunc, ic, 1);
3190 pic14_emitcode ("return","");
3191 emitpcodeNULLop(POC_RETURN);
3193 /* Mark the end of a function */
3194 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3199 /*-----------------------------------------------------------------*/
3200 /* genRet - generate code for return statement */
3201 /*-----------------------------------------------------------------*/
3202 static void genRet (iCode *ic)
3204 int size,offset = 0;
3208 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3209 /* if we have no return value then
3210 just generate the "ret" */
3214 /* we have something to return then
3215 move the return value into place */
3216 aopOp(IC_LEFT(ic),ic,FALSE);
3217 size = AOP_SIZE(IC_LEFT(ic));
3219 for (offset = 0; offset < size; offset++)
3221 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
3224 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3227 /* generate a jump to the return label
3228 if the next is not the return statement */
3229 if (!(ic->next && ic->next->op == LABEL &&
3230 IC_LABEL(ic->next) == returnLabel)) {
3232 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3237 /*-----------------------------------------------------------------*/
3238 /* genLabel - generates a label */
3239 /*-----------------------------------------------------------------*/
3240 static void genLabel (iCode *ic)
3244 /* special case never generate */
3245 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3246 if (IC_LABEL(ic) == entryLabel)
3249 emitpLabel(IC_LABEL(ic)->key);
3250 pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3253 /*-----------------------------------------------------------------*/
3254 /* genGoto - generates a goto */
3255 /*-----------------------------------------------------------------*/
3257 static void genGoto (iCode *ic)
3261 emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3262 pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3266 /*-----------------------------------------------------------------*/
3267 /* genMultbits :- multiplication of bits */
3268 /*-----------------------------------------------------------------*/
3269 static void genMultbits (operand *left,
3274 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3276 if(!pic14_sameRegs(AOP(result),AOP(right)))
3277 emitpcode(POC_BSF, popGet(AOP(result),0));
3279 emitpcode(POC_BTFSC,popGet(AOP(right),0));
3280 emitpcode(POC_BTFSS,popGet(AOP(left),0));
3281 emitpcode(POC_BCF, popGet(AOP(result),0));
3286 /*-----------------------------------------------------------------*/
3287 /* genMultOneByte : 8 bit multiplication & division */
3288 /*-----------------------------------------------------------------*/
3289 static void genMultOneByte (operand *left,
3293 char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
3301 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3302 DEBUGpic14_AopType(__LINE__,left,right,result);
3303 DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3305 /* (if two literals, the value is computed before) */
3306 /* if one literal, literal on the right */
3307 if (AOP_TYPE(left) == AOP_LIT){
3313 assert (AOP_SIZE(left) == AOP_SIZE(right));
3315 size = min(AOP_SIZE(result),AOP_SIZE(left));
3316 offset = Gstack_base_addr - (2*size - 1);
3318 /* pass right operand as argument */
3319 for (i=0; i < size; i++)
3321 mov2w (AOP(right), i);
3322 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3325 /* pass left operand as argument */
3326 for (i=0; i < size; i++)
3328 mov2w (AOP(left), i);
3329 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3331 assert (offset == Gstack_base_addr);
3333 /* call library routine */
3334 assert (size > 0 && size <= 4);
3335 call_libraryfunc (func[size]);
3338 movwf (AOP(result), size-1);
3339 for (i=0; i < size - 1; i++)
3341 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
3342 movwf (AOP(result), size - 2 - i);
3345 /* now (zero-/sign) extend the result to its size */
3346 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
3349 /*-----------------------------------------------------------------*/
3350 /* genMult - generates code for multiplication */
3351 /*-----------------------------------------------------------------*/
3352 static void genMult (iCode *ic)
3354 operand *left = IC_LEFT(ic);
3355 operand *right = IC_RIGHT(ic);
3356 operand *result= IC_RESULT(ic);
3360 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3361 /* assign the amsops */
3362 aopOp (left,ic,FALSE);
3363 aopOp (right,ic,FALSE);
3364 aopOp (result,ic,TRUE);
3366 DEBUGpic14_AopType(__LINE__,left,right,result);
3368 /* special cases first */
3370 if (AOP_TYPE(left) == AOP_CRY &&
3371 AOP_TYPE(right)== AOP_CRY) {
3372 genMultbits(left,right,result);
3376 /* if both are of size == 1 */
3377 if (AOP_SIZE(left) == 1 &&
3378 AOP_SIZE(right) == 1 ) {
3379 genMultOneByte(left,right,result);
3383 /* should have been converted to function call */
3387 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3388 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3389 freeAsmop(result,NULL,ic,TRUE);
3392 /*-----------------------------------------------------------------*/
3393 /* genDivbits :- division of bits */
3394 /*-----------------------------------------------------------------*/
3395 static void genDivbits (operand *left,
3404 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3405 /* the result must be bit */
3406 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3407 l = aopGet(AOP(left),0,FALSE,FALSE);
3411 pic14_emitcode("div","ab");
3412 pic14_emitcode("rrc","a");
3413 aopPut(AOP(result),"c",0);
3416 /*-----------------------------------------------------------------*/
3417 /* genDivOneByte : 8 bit division */
3418 /*-----------------------------------------------------------------*/
3419 static void genDivOneByte (operand *left,
3426 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3428 assert (AOP_SIZE(result) == 1);
3429 assert (AOP_SIZE(right) == 1);
3430 assert (AOP_SIZE(left) == 1);
3432 size = min(AOP_SIZE(result),AOP_SIZE(left));
3434 if (AOP_TYPE(right) == AOP_LIT)
3436 /* XXX: might add specialized code */
3439 if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3441 /* unsigned division */
3443 mov2w(AOP(right),0);
3444 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3446 call_libraryfunc("__divuchar");
3447 movwf(AOP(result),0);
3452 temp = popGetTempReg();
3453 lbl = newiTempLabel(NULL);
3455 /* XXX: improve this naive approach:
3456 [result] = [a] / [b]
3457 ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
3461 movwf temp // temp <-- left
3462 movf right,W // W <-- right
3466 subwf temp,F // temp <-- temp - W
3467 skipNC // subwf clears CARRY (i.e. sets BORROW) if temp < W
3469 decf result // we just subtract once too often
3472 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3473 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
3476 emitpcode(POC_MOVWF, temp);
3477 mov2w(AOP(right),0);
3478 emitpcode(POC_CLRF, popGet(AOP(result),0));
3480 emitpLabel(lbl->key);
3481 emitpcode(POC_INCF, popGet(AOP(result),0));
3482 emitpcode(POC_SUBWF, temp);
3484 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3485 emitpcode(POC_DECF, popGet(AOP(result),0));
3490 /* signed division */
3491 mov2w(AOP(right),0);
3492 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3494 call_libraryfunc("__divschar");
3495 movwf(AOP(result),0);
3498 /* now performed the signed/unsigned division -- extend result */
3499 addSign(result, 1, !SPEC_USIGN(operandType(result)));
3502 /*-----------------------------------------------------------------*/
3503 /* genDiv - generates code for division */
3504 /*-----------------------------------------------------------------*/
3505 static void genDiv (iCode *ic)
3507 operand *left = IC_LEFT(ic);
3508 operand *right = IC_RIGHT(ic);
3509 operand *result= IC_RESULT(ic);
3512 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3513 /* assign the amsops */
3514 aopOp (left,ic,FALSE);
3515 aopOp (right,ic,FALSE);
3516 aopOp (result,ic,TRUE);
3518 /* special cases first */
3520 if (AOP_TYPE(left) == AOP_CRY &&
3521 AOP_TYPE(right)== AOP_CRY) {
3522 genDivbits(left,right,result);
3526 /* if both are of size == 1 */
3527 if (AOP_SIZE(left) == 1 &&
3528 AOP_SIZE(right) == 1 ) {
3529 genDivOneByte(left,right,result);
3533 /* should have been converted to function call */
3536 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3537 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3538 freeAsmop(result,NULL,ic,TRUE);
3541 /*-----------------------------------------------------------------*/
3542 /* genModbits :- modulus of bits */
3543 /*-----------------------------------------------------------------*/
3544 static void genModbits (operand *left,
3552 /* the result must be bit */
3553 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3554 l = aopGet(AOP(left),0,FALSE,FALSE);
3558 pic14_emitcode("div","ab");
3559 pic14_emitcode("mov","a,b");
3560 pic14_emitcode("rrc","a");
3561 aopPut(AOP(result),"c",0);
3564 /*-----------------------------------------------------------------*/
3565 /* genModOneByte : 8 bit modulus */
3566 /*-----------------------------------------------------------------*/
3567 static void genModOneByte (operand *left,
3574 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3576 assert (AOP_SIZE(result) == 1);
3577 assert (AOP_SIZE(right) == 1);
3578 assert (AOP_SIZE(left) == 1);
3580 size = min(AOP_SIZE(result),AOP_SIZE(left));
3582 if (AOP_TYPE(right) == AOP_LIT)
3584 /* XXX: might add specialized code */
3587 if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3589 /* unsigned division */
3591 mov2w(AOP(right),0);
3592 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3594 call_libraryfunc("__moduchar");
3595 movwf(AOP(result),0);
3600 lbl = newiTempLabel(NULL);
3602 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3604 /* XXX: improve this naive approach:
3605 [result] = [a] % [b]
3606 ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3610 movwf result // result <-- left
3611 movf right,W // W <-- right
3613 subwf result,F // result <-- result - W
3614 skipNC // subwf clears CARRY (i.e. sets BORROW) if result < W
3616 addwf result, F // we just subtract once too often
3619 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3620 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3622 if (!pic14_sameRegs(AOP(left), AOP(result)))
3625 emitpcode(POC_MOVWF, popGet(AOP(result),0));
3627 mov2w(AOP(right),0);
3629 emitpLabel(lbl->key);
3630 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3632 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3633 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3638 /* signed division */
3639 mov2w(AOP(right),0);
3640 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3642 call_libraryfunc("__modschar");
3643 movwf(AOP(result),0);
3646 /* now we performed the signed/unsigned modulus -- extend result */
3647 addSign(result, 1, !SPEC_USIGN(operandType(result)));
3650 /*-----------------------------------------------------------------*/
3651 /* genMod - generates code for division */
3652 /*-----------------------------------------------------------------*/
3653 static void genMod (iCode *ic)
3655 operand *left = IC_LEFT(ic);
3656 operand *right = IC_RIGHT(ic);
3657 operand *result= IC_RESULT(ic);
3660 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3661 /* assign the amsops */
3662 aopOp (left,ic,FALSE);
3663 aopOp (right,ic,FALSE);
3664 aopOp (result,ic,TRUE);
3666 /* special cases first */
3668 if (AOP_TYPE(left) == AOP_CRY &&
3669 AOP_TYPE(right)== AOP_CRY) {
3670 genModbits(left,right,result);
3674 /* if both are of size == 1 */
3675 if (AOP_SIZE(left) == 1 &&
3676 AOP_SIZE(right) == 1 ) {
3677 genModOneByte(left,right,result);
3681 /* should have been converted to function call */
3685 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3686 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3687 freeAsmop(result,NULL,ic,TRUE);
3690 /*-----------------------------------------------------------------*/
3691 /* genIfxJump :- will create a jump depending on the ifx */
3692 /*-----------------------------------------------------------------*/
3694 note: May need to add parameter to indicate when a variable is in bit space.
3696 static void genIfxJump (iCode *ic, char *jval)
3700 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3701 /* if true label then we jump if condition
3703 if ( IC_TRUE(ic) ) {
3705 if(strcmp(jval,"a") == 0)
3707 else if (strcmp(jval,"c") == 0)
3710 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3711 emitpcode(POC_BTFSC, newpCodeOpBit(jval,-1,1));
3714 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3715 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3719 /* false label is present */
3720 if(strcmp(jval,"a") == 0)
3722 else if (strcmp(jval,"c") == 0)
3725 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3726 emitpcode(POC_BTFSS, newpCodeOpBit(jval,-1,1));
3729 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3730 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3735 /* mark the icode as generated */
3740 /*-----------------------------------------------------------------*/
3742 /*-----------------------------------------------------------------*/
3743 static void genSkip(iCode *ifx,int status_bit)
3749 if ( IC_TRUE(ifx) ) {
3750 switch(status_bit) {
3765 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3766 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3770 switch(status_bit) {
3784 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3785 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3792 /*-----------------------------------------------------------------*/
3794 /*-----------------------------------------------------------------*/
3795 static void genSkipc(resolvedIfx *rifx)
3806 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3807 emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3808 rifx->generated = 1;
3812 /*-----------------------------------------------------------------*/
3814 /*-----------------------------------------------------------------*/
3815 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3821 if( (rifx->condition ^ invert_condition) & 1)
3826 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3827 rifx->generated = 1;
3832 /*-----------------------------------------------------------------*/
3834 /*-----------------------------------------------------------------*/
3835 static void genSkipz(iCode *ifx, int condition)
3838 assert (ifx != NULL);
3846 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3848 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3851 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3853 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3859 /*-----------------------------------------------------------------*/
3861 /*-----------------------------------------------------------------*/
3862 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3869 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3871 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3874 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3875 rifx->generated = 1;
3880 /*-----------------------------------------------------------------*/
3881 /* genChkZeroes :- greater or less than comparison */
3882 /* For each byte in a literal that is zero, inclusive or the */
3883 /* the corresponding byte in the operand with W */
3884 /* returns true if any of the bytes are zero */
3885 /*-----------------------------------------------------------------*/
3886 static int genChkZeroes(operand *op, int lit, int size)
3893 i = (lit >> (size*8)) & 0xff;
3897 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3899 emitpcode(POC_IORFW, popGet(AOP(op),size));
3909 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3910 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
3911 #define DEBUGpc emitpComment
3913 /*-----------------------------------------------------------------*/
3914 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
3915 /* aop (if it's NOT a literal) or from lit (if */
3916 /* aop is a literal) */
3917 /*-----------------------------------------------------------------*/
3918 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3919 if (aop->type == AOP_LIT) {
3920 emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3922 emitpcode (POC_MOVFW, popGet (aop, offset));
3926 /* genCmp performs a left < right comparison, stores
3927 * the outcome in result (if != NULL) and generates
3928 * control flow code for the ifx (if != NULL).
3930 * This version leaves in sequences like
3931 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3932 * which should be optmized by the peephole
3933 * optimizer - RN 2005-01-01 */
3934 static void genCmp (operand *left,operand *right,
3935 operand *result, iCode *ifx, int sign)
3945 int invert_result = 0;
3949 assert (AOP_SIZE(left) == AOP_SIZE(right));
3950 assert (left && right);
3952 size = AOP_SIZE(right) - 1;
3953 mask = (0x100UL << (size*8)) - 1;
3954 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3959 resolveIfx (&rIfx, ifx);
3961 /**********************************************************************
3962 * handle bits - bit compares are promoted to int compares seemingly! *
3963 **********************************************************************/
3965 // THIS IS COMPLETELY UNTESTED!
3966 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3967 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3968 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3969 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3972 // 1 < {0,1} is false --> clear C by skipping the next instruction
3973 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3974 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3975 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3976 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3977 emitCLRC; // only skipped for left=0 && right=1
3979 goto correct_result_in_carry;
3983 /*************************************************
3984 * make sure that left is register (or the like) *
3985 *************************************************/
3986 if (!isAOP_REGlike(left)) {
3987 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
3988 assert (isAOP_LIT(left));
3989 assert (isAOP_REGlike(right));
3990 // swap left and right
3991 // left < right <==> right > left <==> (right >= left + 1)
3992 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3994 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
3995 // MAXVALUE < right? always false
3996 if (performedLt) emitCLRC; else emitSETC;
3997 goto correct_result_in_carry;
4000 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4001 // that's why we handled it above.
4008 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4009 } else if (isAOP_LIT(right)) {
4010 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4013 assert (isAOP_REGlike(left)); // left must be register or the like
4014 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4016 /*************************************************
4017 * special cases go here *
4018 *************************************************/
4020 if (isAOP_LIT(right)) {
4022 // unsigned comparison to a literal
4023 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4025 // unsigned left < 0? always false
4026 if (performedLt) emitCLRC; else emitSETC;
4027 goto correct_result_in_carry;
4030 // signed comparison to a literal
4031 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4032 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4033 // signed left < 0x80000000? always false
4034 if (performedLt) emitCLRC; else emitSETC;
4035 goto correct_result_in_carry;
4036 } else if (lit == 0) {
4037 // compare left < 0; set CARRY if SIGNBIT(left) is set
4038 if (performedLt) emitSETC; else emitCLRC;
4039 emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
4040 if (performedLt) emitCLRC; else emitSETC;
4041 goto correct_result_in_carry;
4044 } // right is literal
4046 /*************************************************
4047 * perform a general case comparison *
4048 * make sure we get CARRY==1 <==> left >= right *
4049 *************************************************/
4050 // compare most significant bytes
4051 //DEBUGpc ("comparing bytes at offset %d", size);
4053 // unsigned comparison
4054 pic14_mov2w_regOrLit (AOP(right), lit, size);
4055 emitpcode (POC_SUBFW, popGet (AOP(left), size));
4057 // signed comparison
4058 // (add 2^n to both operands then perform an unsigned comparison)
4059 if (isAOP_LIT(right)) {
4060 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4061 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4063 if (litbyte == 0x80) {
4064 // left >= 0x80 -- always true, but more bytes to come
4065 mov2w (AOP(left), size);
4066 emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
4069 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4070 mov2w (AOP(left), size);
4071 emitpcode (POC_ADDLW, popGetLit (0x80));
4072 emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4075 pCodeOp *pctemp = popGetTempReg();
4076 mov2w (AOP(left), size);
4077 emitpcode (POC_ADDLW, popGetLit (0x80));
4078 emitpcode (POC_MOVWF, pctemp);
4079 mov2w (AOP(right), size);
4080 emitpcode (POC_ADDLW, popGetLit (0x80));
4081 emitpcode (POC_SUBFW, pctemp);
4082 popReleaseTempReg(pctemp);
4086 // compare remaining bytes (treat as unsigned case from above)
4087 templbl = newiTempLabel ( NULL );
4090 //DEBUGpc ("comparing bytes at offset %d", offs);
4092 emitpcode (POC_GOTO, popGetLabel (templbl->key));
4093 pic14_mov2w_regOrLit (AOP(right), lit, offs);
4094 emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4096 emitpLabel (templbl->key);
4097 goto result_in_carry;
4101 /****************************************************
4102 * now CARRY contains the result of the comparison: *
4103 * SUBWF sets CARRY iff *
4104 * F-W >= 0 <==> F >= W <==> !(F < W) *
4105 * (F=left, W=right) *
4106 ****************************************************/
4110 // value will be used in the following genSkipc()
4111 rIfx.condition ^= 1;
4114 correct_result_in_carry:
4116 // assign result to variable (if neccessary)
4117 if (result && AOP_TYPE(result) != AOP_CRY) {
4118 //DEBUGpc ("assign result");
4119 size = AOP_SIZE(result);
4121 emitpcode (POC_CLRF, popGet (AOP(result), size));
4123 if (invert_result) {
4125 emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4127 emitpcode (POC_RLF, popGet (AOP(result), 0));
4131 // perform conditional jump
4133 //DEBUGpc ("generate control flow");
4141 /* OLD VERSION -- BUGGY, DO NOT USE */
4143 /*-----------------------------------------------------------------*/
4144 /* genCmp :- greater or less than comparison */
4145 /*-----------------------------------------------------------------*/
4146 static void genCmp (operand *left,operand *right,
4147 operand *result, iCode *ifx, int sign)
4149 int size; //, offset = 0 ;
4150 unsigned long lit = 0L,i = 0;
4151 resolvedIfx rFalseIfx;
4152 // resolvedIfx rTrueIfx;
4156 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4159 DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4160 DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4164 resolveIfx(&rFalseIfx,ifx);
4165 truelbl = newiTempLabel(NULL);
4166 size = max(AOP_SIZE(left),AOP_SIZE(right));
4168 DEBUGpic14_AopType(__LINE__,left,right,result);
4172 /* if literal is on the right then swap with left */
4173 if ((AOP_TYPE(right) == AOP_LIT)) {
4174 operand *tmp = right ;
4175 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4176 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4179 lit = (lit - 1) & mask;
4182 rFalseIfx.condition ^= 1;
4185 } else if ((AOP_TYPE(left) == AOP_LIT)) {
4186 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4190 //if(IC_TRUE(ifx) == NULL)
4191 /* if left & right are bit variables */
4192 if (AOP_TYPE(left) == AOP_CRY &&
4193 AOP_TYPE(right) == AOP_CRY ) {
4194 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4195 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4197 /* subtract right from left if at the
4198 end the carry flag is set then we know that
4199 left is greater than right */
4201 symbol *lbl = newiTempLabel(NULL);
4204 if(AOP_TYPE(right) == AOP_LIT) {
4206 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4208 DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4215 genSkipCond(&rFalseIfx,left,size-1,7);
4217 /* no need to compare to 0...*/
4218 /* NOTE: this is a de-generate compare that most certainly
4219 * creates some dead code. */
4220 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4222 if(ifx) ifx->generated = 1;
4229 //i = (lit >> (size*8)) & 0xff;
4230 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4232 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4234 i = ((0-lit) & 0xff);
4237 /* lit is 0x7f, all signed chars are less than
4238 * this except for 0x7f itself */
4239 emitpcode(POC_XORLW, popGetLit(0x7f));
4240 genSkipz2(&rFalseIfx,0);
4242 emitpcode(POC_ADDLW, popGetLit(0x80));
4243 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4244 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4249 genSkipz2(&rFalseIfx,1);
4251 emitpcode(POC_ADDLW, popGetLit(i));
4252 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4256 if(ifx) ifx->generated = 1;
4260 /* chars are out of the way. now do ints and longs */
4263 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4270 genSkipCond(&rFalseIfx,left,size,7);
4271 if(ifx) ifx->generated = 1;
4276 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4278 //rFalseIfx.condition ^= 1;
4279 //genSkipCond(&rFalseIfx,left,size,7);
4280 //rFalseIfx.condition ^= 1;
4282 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4283 if(rFalseIfx.condition)
4284 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4286 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4288 emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4289 emitpcode(POC_ADDFW, popGet(AOP(left),0));
4290 emitpcode(POC_MOVFW, popGet(AOP(left),1));
4293 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4295 if(rFalseIfx.condition) {
4297 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4303 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4304 emitpLabel(truelbl->key);
4305 if(ifx) ifx->generated = 1;
4312 if( (lit & 0xff) == 0) {
4313 /* lower byte is zero */
4314 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4315 i = ((lit >> 8) & 0xff) ^0x80;
4316 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4317 emitpcode(POC_ADDLW, popGetLit( 0x80));
4318 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4319 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4322 if(ifx) ifx->generated = 1;
4327 /* Special cases for signed longs */
4328 if( (lit & 0xffffff) == 0) {
4329 /* lower byte is zero */
4330 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4331 i = ((lit >> 8*3) & 0xff) ^0x80;
4332 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4333 emitpcode(POC_ADDLW, popGetLit( 0x80));
4334 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4335 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4338 if(ifx) ifx->generated = 1;
4346 if(lit & (0x80 << (size*8))) {
4347 /* lit is negative */
4348 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4350 //genSkipCond(&rFalseIfx,left,size,7);
4352 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4354 if(rFalseIfx.condition)
4355 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4357 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4361 /* lit is positive */
4362 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4363 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4364 if(rFalseIfx.condition)
4365 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4367 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4371 /* There are no more special cases, so perform a general compare */
4373 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4374 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4378 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4380 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4382 //rFalseIfx.condition ^= 1;
4383 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4385 emitpLabel(truelbl->key);
4387 if(ifx) ifx->generated = 1;
4394 /* sign is out of the way. So now do an unsigned compare */
4395 DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4398 /* General case - compare to an unsigned literal on the right.*/
4400 i = (lit >> (size*8)) & 0xff;
4401 emitpcode(POC_MOVLW, popGetLit(i));
4402 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4404 i = (lit >> (size*8)) & 0xff;
4407 emitpcode(POC_MOVLW, popGetLit(i));
4409 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4411 /* this byte of the lit is zero,
4412 *if it's not the last then OR in the variable */
4414 emitpcode(POC_IORFW, popGet(AOP(left),size));
4419 emitpLabel(lbl->key);
4420 //if(emitFinalCheck)
4421 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4423 emitpLabel(truelbl->key);
4425 if(ifx) ifx->generated = 1;
4432 if(AOP_TYPE(left) == AOP_LIT) {
4433 //symbol *lbl = newiTempLabel(NULL);
4435 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4438 DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4441 if((lit == 0) && (sign == 0)){
4444 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4446 emitpcode(POC_IORFW, popGet(AOP(right),--size));
4448 genSkipz2(&rFalseIfx,0);
4449 if(ifx) ifx->generated = 1;
4456 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4457 /* degenerate compare can never be true */
4458 if(rFalseIfx.condition == 0)
4459 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4461 if(ifx) ifx->generated = 1;
4466 /* signed comparisons to a literal byte */
4468 int lp1 = (lit+1) & 0xff;
4470 DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4473 rFalseIfx.condition ^= 1;
4474 genSkipCond(&rFalseIfx,right,0,7);
4477 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4478 emitpcode(POC_XORLW, popGetLit(0x7f));
4479 genSkipz2(&rFalseIfx,1);
4482 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4483 emitpcode(POC_ADDLW, popGetLit(0x80));
4484 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4485 rFalseIfx.condition ^= 1;
4486 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4489 if(ifx) ifx->generated = 1;
4491 /* unsigned comparisons to a literal byte */
4493 switch(lit & 0xff ) {
4495 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4496 genSkipz2(&rFalseIfx,0);
4497 if(ifx) ifx->generated = 1;
4500 genSkipCond(&rFalseIfx,right,0,7);
4501 if(ifx) ifx->generated = 1;
4505 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4506 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4507 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4508 rFalseIfx.condition ^= 1;
4509 if (AOP_TYPE(result) == AOP_CRY) {
4510 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4511 if(ifx) ifx->generated = 1;
4513 DEBUGpic14_emitcode ("; ***","%s %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4514 emitpcode(POC_CLRF, popGet(AOP(result),0));
4515 emitpcode(POC_RLF, popGet(AOP(result),0));
4516 emitpcode(POC_MOVLW, popGetLit(0x01));
4517 emitpcode(POC_XORWF, popGet(AOP(result),0));
4528 /* Size is greater than 1 */
4536 /* this means lit = 0xffffffff, or -1 */
4539 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4540 rFalseIfx.condition ^= 1;
4541 genSkipCond(&rFalseIfx,right,size,7);
4542 if(ifx) ifx->generated = 1;
4549 if(rFalseIfx.condition) {
4550 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4551 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4554 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4556 emitpcode(POC_IORFW, popGet(AOP(right),size));
4560 if(rFalseIfx.condition) {
4561 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4562 emitpLabel(truelbl->key);
4564 rFalseIfx.condition ^= 1;
4565 genSkipCond(&rFalseIfx,right,s,7);
4568 if(ifx) ifx->generated = 1;
4572 if((size == 1) && (0 == (lp1&0xff))) {
4573 /* lower byte of signed word is zero */
4574 DEBUGpic14_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
4575 i = ((lp1 >> 8) & 0xff) ^0x80;
4576 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4577 emitpcode(POC_ADDLW, popGetLit( 0x80));
4578 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4579 rFalseIfx.condition ^= 1;
4580 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4583 if(ifx) ifx->generated = 1;
4587 if(lit & (0x80 << (size*8))) {
4588 /* Lit is less than zero */
4589 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
4590 //rFalseIfx.condition ^= 1;
4591 //genSkipCond(&rFalseIfx,left,size,7);
4592 //rFalseIfx.condition ^= 1;
4593 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4594 //emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4596 if(rFalseIfx.condition)
4597 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4599 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4603 /* Lit is greater than or equal to zero */
4604 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
4605 //rFalseIfx.condition ^= 1;
4606 //genSkipCond(&rFalseIfx,right,size,7);
4607 //rFalseIfx.condition ^= 1;
4609 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4610 //emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4612 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4613 if(rFalseIfx.condition)
4614 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4616 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4621 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4622 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4626 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4628 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4630 rFalseIfx.condition ^= 1;
4631 //rFalseIfx.condition = 1;
4632 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4634 emitpLabel(truelbl->key);
4636 if(ifx) ifx->generated = 1;
4641 /* compare word or long to an unsigned literal on the right.*/
4646 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4649 break; /* handled above */
4652 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4654 emitpcode(POC_IORFW, popGet(AOP(right),size));
4655 genSkipz2(&rFalseIfx,0);
4659 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4661 emitpcode(POC_IORFW, popGet(AOP(right),size));
4664 if(rFalseIfx.condition)
4665 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4667 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4670 emitpcode(POC_MOVLW, popGetLit(lit+1));
4671 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4673 rFalseIfx.condition ^= 1;
4674 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4677 emitpLabel(truelbl->key);
4679 if(ifx) ifx->generated = 1;
4685 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4686 i = (lit >> (size*8)) & 0xff;
4688 emitpcode(POC_MOVLW, popGetLit(i));
4689 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4692 i = (lit >> (size*8)) & 0xff;
4695 emitpcode(POC_MOVLW, popGetLit(i));
4697 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4699 /* this byte of the lit is zero,
4700 *if it's not the last then OR in the variable */
4702 emitpcode(POC_IORFW, popGet(AOP(right),size));
4707 emitpLabel(lbl->key);
4709 rFalseIfx.condition ^= 1;
4710 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4714 emitpLabel(truelbl->key);
4715 if(ifx) ifx->generated = 1;
4719 /* Compare two variables */
4721 DEBUGpic14_emitcode(";sign","%d",sign);
4725 /* Sigh. thus sucks... */
4727 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4728 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4729 emitpcode(POC_MOVLW, popGetLit(0x80));
4730 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4731 emitpcode(POC_XORFW, popGet(AOP(right),size));
4732 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4734 /* Signed char comparison */
4735 /* Special thanks to Nikolai Golovchenko for this snippet */
4736 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4737 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4738 emitpcode(POC_RRFW, popGet(AOP(left),0)); /* could be any register */
4739 emitpcode(POC_XORFW, popGet(AOP(left),0));
4740 emitpcode(POC_XORFW, popGet(AOP(right),0));
4741 emitpcode(POC_ADDLW, popGetLit(0x80));
4743 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4744 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4746 if(ifx) ifx->generated = 1;
4752 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4753 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4757 /* The rest of the bytes of a multi-byte compare */
4761 emitpcode(POC_GOTO, popGetLabel(lbl->key));
4764 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4765 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4770 emitpLabel(lbl->key);
4772 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4773 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
4774 (AOP_TYPE(result) == AOP_REG)) {
4775 emitpcode(POC_CLRF, popGet(AOP(result),0));
4776 emitpcode(POC_RLF, popGet(AOP(result),0));
4778 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4780 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4781 if(ifx) ifx->generated = 1;
4788 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4789 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4790 pic14_outBitC(result);
4792 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4793 /* if the result is used in the next
4794 ifx conditional branch then generate
4795 code a little differently */
4797 genIfxJump (ifx,"c");
4799 pic14_outBitC(result);
4800 /* leave the result in acc */
4806 /*-----------------------------------------------------------------*/
4807 /* genCmpGt :- greater than comparison */
4808 /*-----------------------------------------------------------------*/
4809 static void genCmpGt (iCode *ic, iCode *ifx)
4811 operand *left, *right, *result;
4812 sym_link *letype , *retype;
4816 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4818 right= IC_RIGHT(ic);
4819 result = IC_RESULT(ic);
4821 letype = getSpec(operandType(left));
4822 retype =getSpec(operandType(right));
4823 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4824 /* assign the amsops */
4825 aopOp (left,ic,FALSE);
4826 aopOp (right,ic,FALSE);
4827 aopOp (result,ic,TRUE);
4829 genCmp(right, left, result, ifx, sign);
4831 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4832 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4833 freeAsmop(result,NULL,ic,TRUE);
4836 /*-----------------------------------------------------------------*/
4837 /* genCmpLt - less than comparisons */
4838 /*-----------------------------------------------------------------*/
4839 static void genCmpLt (iCode *ic, iCode *ifx)
4841 operand *left, *right, *result;
4842 sym_link *letype , *retype;
4846 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4848 right= IC_RIGHT(ic);
4849 result = IC_RESULT(ic);
4851 letype = getSpec(operandType(left));
4852 retype =getSpec(operandType(right));
4853 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4855 /* assign the amsops */
4856 aopOp (left,ic,FALSE);
4857 aopOp (right,ic,FALSE);
4858 aopOp (result,ic,TRUE);
4860 genCmp(left, right, result, ifx, sign);
4862 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4863 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4864 freeAsmop(result,NULL,ic,TRUE);
4868 /*-----------------------------------------------------------------*/
4869 /* genc16bit2lit - compare a 16 bit value to a literal */
4870 /*-----------------------------------------------------------------*/
4871 static void genc16bit2lit(operand *op, int lit, int offset)
4876 DEBUGpic14_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
4877 if( (lit&0xff) == 0)
4882 switch( BYTEofLONG(lit,i)) {
4884 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4887 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4890 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4893 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4894 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4899 switch( BYTEofLONG(lit,i)) {
4901 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4905 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4909 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4912 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4914 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4922 /*-----------------------------------------------------------------*/
4923 /* gencjneshort - compare and jump if not equal */
4924 /*-----------------------------------------------------------------*/
4925 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4927 int size = min(AOP_SIZE(left),AOP_SIZE(right));
4932 //unsigned long lit = 0L;
4934 if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4935 emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4938 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4939 DEBUGpic14_AopType(__LINE__,left,right,result);
4941 assert (!pic14_sameRegs (AOP(left), AOP(result)));
4942 assert (!pic14_sameRegs (AOP(right), AOP(result)));
4943 if (AOP_SIZE(result)) {
4944 for (offset = 0; offset < AOP_SIZE(result); offset++)
4945 emitpcode (POC_CLRF, popGet (AOP(result), offset));
4948 assert (AOP_SIZE(left) == AOP_SIZE(right));
4949 //resolveIfx(&rIfx,ifx);
4950 lbl = newiTempLabel (NULL);
4953 mov2w (AOP(right),size);
4954 emitpcode (POC_XORFW, popGet (AOP(left), size));
4958 emitpcode (POC_GOTO, popGetLabel (lbl->key));
4961 emitpLabel (lbl->key);
4962 if (AOP_SIZE(result)) {
4964 emitpcode (POC_INCF, popGet (AOP(result), 0));
4967 genSkipz (ifx, NULL != IC_TRUE(ifx));
4974 DEBUGpic14_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
4975 assert (!pic14_sameRegs (AOP(result), AOP(left)));
4976 assert (!pic14_sameRegs (AOP(result), AOP(right)));
4977 for (offset=0; offset < AOP_SIZE(result); offset++)
4979 emitpcode (POC_CLRF, popGet (AOP(result), offset));
4984 /* if the left side is a literal or
4985 if the right is in a pointer register and left
4987 if ((AOP_TYPE(left) == AOP_LIT) ||
4988 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4993 if(AOP_TYPE(right) == AOP_LIT)
4994 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4996 /* if the right side is a literal then anything goes */
4997 if (AOP_TYPE(right) == AOP_LIT &&
4998 AOP_TYPE(left) != AOP_DIR ) {
5001 genc16bit2lit(left, lit, 0);
5003 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5009 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5010 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5012 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5016 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5024 /* if the right side is in a register or in direct space or
5025 if the left is a pointer register & right is not */
5026 else if (AOP_TYPE(right) == AOP_REG ||
5027 AOP_TYPE(right) == AOP_DIR ||
5028 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5029 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5030 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5031 int lbl_key = lbl->key;
5034 DEBUGpic14_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
5035 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
5036 __FUNCTION__,__LINE__);
5040 /* switch(size) { */
5042 /* genc16bit2lit(left, lit, 0); */
5044 /* emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
5050 if((AOP_TYPE(left) == AOP_DIR) &&
5051 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5053 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5054 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5056 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5058 switch (lit & 0xff) {
5060 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5063 emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
5064 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5065 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5069 emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5070 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5071 //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5072 emitpcode(POC_GOTO,popGetLabel(lbl_key));
5076 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5077 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5082 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5085 if(AOP_TYPE(result) == AOP_CRY) {
5086 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5091 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5093 /* fix me. probably need to check result size too */
5094 //emitpcode(POC_CLRF,popGet(AOP(result),0));
5099 emitpcode(POC_GOTO,popGetLabel(lbl_key));
5109 } else if(AOP_TYPE(right) == AOP_REG &&
5110 AOP_TYPE(left) != AOP_DIR){
5114 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5115 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5116 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5121 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5126 /* right is a pointer reg need both a & b */
5129 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5131 pic14_emitcode("mov","b,%s",l);
5132 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5133 pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
5138 emitpcode(POC_INCF,popGet(AOP(result),0));
5140 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5142 emitpLabel(lbl->key);
5144 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5153 /*-----------------------------------------------------------------*/
5154 /* gencjne - compare and jump if not equal */
5155 /*-----------------------------------------------------------------*/
5156 static void gencjne(operand *left, operand *right, iCode *ifx)
5158 symbol *tlbl = newiTempLabel(NULL);
5160 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5161 gencjneshort(left, right, lbl);
5163 pic14_emitcode("mov","a,%s",one);
5164 pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5165 pic14_emitcode("","%05d_DS_:",lbl->key+100);
5166 pic14_emitcode("clr","a");
5167 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5169 emitpLabel(lbl->key);
5170 emitpLabel(tlbl->key);
5175 /*-----------------------------------------------------------------*/
5176 /* genCmpEq - generates code for equal to */
5177 /*-----------------------------------------------------------------*/
5178 static void genCmpEq (iCode *ic, iCode *ifx)
5180 operand *left, *right, *result;
5182 symbol *false_label;
5185 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5188 DEBUGpic14_emitcode ("; ifx is non-null","");
5190 DEBUGpic14_emitcode ("; ifx is null","");
5192 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5193 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5194 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5196 DEBUGpic14_AopType(__LINE__,left,right,result);
5198 /* if literal, move literal to right */
5199 if (op_isLitLike (IC_LEFT(ic))) {
5200 operand *tmp = right ;
5206 if (ifx && !IC_TRUE(ifx))
5208 assert (IC_FALSE(ifx));
5209 false_label = IC_FALSE(ifx);
5212 size = min(AOP_SIZE(left),AOP_SIZE(right));
5213 assert(!pic14_sameRegs(AOP(result),AOP(left)));
5214 assert(!pic14_sameRegs(AOP(result),AOP(right)));
5216 /* assume left != right */
5219 for (i=0; i < AOP_SIZE(result); i++)
5221 emitpcode(POC_CLRF, popGet(AOP(result),i));
5225 if (AOP_TYPE(right) == AOP_LIT)
5227 unsigned long lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
5229 size = AOP_SIZE(left);
5230 assert(!op_isLitLike(left));
5235 mov2w(AOP(left), 0);
5236 for (i=1; i < size; i++)
5237 emitpcode(POC_IORFW,popGet(AOP(left),i));
5238 /* now Z is set iff `left == right' */
5240 if (!false_label) false_label = newiTempLabel(NULL);
5241 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5245 for (i=0; i < size; i++)
5248 emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
5249 /* now Z is cleared if `left != right' */
5251 if (!false_label) false_label = newiTempLabel(NULL);
5252 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5259 /* right is no literal */
5262 for (i=0; i < size; i++)
5264 mov2w(AOP(right),i);
5265 emitpcode(POC_XORFW,popGet(AOP(left),i));
5266 /* now Z is cleared if `left != right' */
5268 if (!false_label) false_label = newiTempLabel(NULL);
5269 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5273 /* if we reach here, left == right */
5275 if (AOP_SIZE(result) > 0)
5277 emitpcode(POC_INCF, popGet(AOP(result),0));
5280 if (ifx && IC_TRUE(ifx))
5282 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5285 if (false_label && (!ifx || IC_TRUE(ifx)))
5286 emitpLabel(false_label->key);
5288 if (ifx) ifx->generated = 1;
5290 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5291 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5292 freeAsmop(result,NULL,ic,TRUE);
5295 /*-----------------------------------------------------------------*/
5296 /* ifxForOp - returns the icode containing the ifx for operand */
5297 /*-----------------------------------------------------------------*/
5298 static iCode *ifxForOp ( operand *op, iCode *ic )
5301 /* if true symbol then needs to be assigned */
5302 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5303 if (IS_TRUE_SYMOP(op))
5306 /* if this has register type condition and
5307 the next instruction is ifx with the same operand
5308 and live to of the operand is upto the ifx only then */
5310 ic->next->op == IFX &&
5311 IC_COND(ic->next)->key == op->key &&
5312 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5316 ic->next->op == IFX &&
5317 IC_COND(ic->next)->key == op->key) {
5318 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5322 DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5324 ic->next->op == IFX)
5325 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5328 ic->next->op == IFX &&
5329 IC_COND(ic->next)->key == op->key) {
5330 DEBUGpic14_emitcode ("; "," key is okay");
5331 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5332 OP_SYMBOL(op)->liveTo,
5339 /*-----------------------------------------------------------------*/
5340 /* genAndOp - for && operation */
5341 /*-----------------------------------------------------------------*/
5342 static void genAndOp (iCode *ic)
5344 operand *left,*right, *result;
5348 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5349 /* note here that && operations that are in an
5350 if statement are taken away by backPatchLabels
5351 only those used in arthmetic operations remain */
5352 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5353 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5354 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5356 DEBUGpic14_AopType(__LINE__,left,right,result);
5358 emitpcode(POC_MOVFW,popGet(AOP(left),0));
5359 emitpcode(POC_ANDFW,popGet(AOP(right),0));
5360 emitpcode(POC_MOVWF,popGet(AOP(result),0));
5362 /* if both are bit variables */
5363 /* if (AOP_TYPE(left) == AOP_CRY && */
5364 /* AOP_TYPE(right) == AOP_CRY ) { */
5365 /* pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5366 /* pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5367 /* pic14_outBitC(result); */
5369 /* tlbl = newiTempLabel(NULL); */
5370 /* pic14_toBoolean(left); */
5371 /* pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5372 /* pic14_toBoolean(right); */
5373 /* pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5374 /* pic14_outBitAcc(result); */
5377 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5378 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5379 freeAsmop(result,NULL,ic,TRUE);
5383 /*-----------------------------------------------------------------*/
5384 /* genOrOp - for || operation */
5385 /*-----------------------------------------------------------------*/
5388 modified this code, but it doesn't appear to ever get called
5391 static void genOrOp (iCode *ic)
5393 operand *left,*right, *result;
5397 /* note here that || operations that are in an
5398 if statement are taken away by backPatchLabels
5399 only those used in arthmetic operations remain */
5401 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5402 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5403 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5404 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5406 DEBUGpic14_AopType(__LINE__,left,right,result);
5408 for (i=0; i < AOP_SIZE(result); i++)
5410 emitpcode(POC_CLRF, popGet(AOP(result), i));
5413 tlbl = newiTempLabel(NULL);
5414 pic14_toBoolean(left);
5416 emitpcode(POC_GOTO, popGetLabel(tlbl->key));
5417 pic14_toBoolean(right);
5418 emitpLabel(tlbl->key);
5419 /* here Z is clear IFF `left || right' */
5421 emitpcode(POC_INCF, popGet(AOP(result), 0));
5423 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5424 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5425 freeAsmop(result,NULL,ic,TRUE);
5428 /*-----------------------------------------------------------------*/
5429 /* isLiteralBit - test if lit == 2^n */
5430 /*-----------------------------------------------------------------*/
5431 static int isLiteralBit(unsigned long lit)
5433 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5434 0x100L,0x200L,0x400L,0x800L,
5435 0x1000L,0x2000L,0x4000L,0x8000L,
5436 0x10000L,0x20000L,0x40000L,0x80000L,
5437 0x100000L,0x200000L,0x400000L,0x800000L,
5438 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5439 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5443 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5444 for(idx = 0; idx < 32; idx++)
5450 /*-----------------------------------------------------------------*/
5451 /* continueIfTrue - */
5452 /*-----------------------------------------------------------------*/
5453 static void continueIfTrue (iCode *ic)
5456 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5458 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5462 /*-----------------------------------------------------------------*/
5464 /*-----------------------------------------------------------------*/
5465 static void jumpIfTrue (iCode *ic)
5468 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5470 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5474 /*-----------------------------------------------------------------*/
5475 /* jmpTrueOrFalse - */
5476 /*-----------------------------------------------------------------*/
5477 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5480 // ugly but optimized by peephole
5481 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5483 symbol *nlbl = newiTempLabel(NULL);
5484 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5485 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5486 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5487 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5490 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5491 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5496 /*-----------------------------------------------------------------*/
5497 /* genAnd - code for and */
5498 /*-----------------------------------------------------------------*/
5499 static void genAnd (iCode *ic, iCode *ifx)
5501 operand *left, *right, *result;
5503 unsigned long lit = 0L;
5508 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5509 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5510 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5511 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5513 resolveIfx(&rIfx,ifx);
5515 /* if left is a literal & right is not then exchange them */
5516 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5517 AOP_NEEDSACC(left)) {
5518 operand *tmp = right ;
5523 /* if result = right then exchange them */
5524 if(pic14_sameRegs(AOP(result),AOP(right))){
5525 operand *tmp = right ;
5530 /* if right is bit then exchange them */
5531 if (AOP_TYPE(right) == AOP_CRY &&
5532 AOP_TYPE(left) != AOP_CRY){
5533 operand *tmp = right ;
5537 if(AOP_TYPE(right) == AOP_LIT)
5538 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5540 size = AOP_SIZE(result);
5542 DEBUGpic14_AopType(__LINE__,left,right,result);
5545 // result = bit & yy;
5546 if (AOP_TYPE(left) == AOP_CRY){
5547 // c = bit & literal;
5548 if(AOP_TYPE(right) == AOP_LIT){
5550 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5553 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5556 if(size && (AOP_TYPE(result) == AOP_CRY)){
5557 pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5560 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5564 pic14_emitcode("clr","c");
5567 if (AOP_TYPE(right) == AOP_CRY){
5569 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5570 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5573 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5575 pic14_emitcode("rrc","a");
5576 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5582 pic14_outBitC(result);
5584 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5585 genIfxJump(ifx, "c");
5589 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5590 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5591 if((AOP_TYPE(right) == AOP_LIT) &&
5592 (AOP_TYPE(result) == AOP_CRY) &&
5593 (AOP_TYPE(left) != AOP_CRY)){
5594 int posbit = isLiteralBit(lit);
5598 //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5601 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5606 while (posbit > 7) {
5610 emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5611 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5612 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5619 symbol *tlbl = newiTempLabel(NULL);
5620 int sizel = AOP_SIZE(left);
5622 pic14_emitcode("setb","c");
5624 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5625 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5627 if((posbit = isLiteralBit(bytelit)) != 0)
5628 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5630 if(bytelit != 0x0FFL)
5631 pic14_emitcode("anl","a,%s",
5632 aopGet(AOP(right),offset,FALSE,TRUE));
5633 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5638 // bit = left & literal
5640 pic14_emitcode("clr","c");
5641 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5643 // if(left & literal)
5646 jmpTrueOrFalse(ifx, tlbl);
5650 pic14_outBitC(result);
5654 /* if left is same as result */
5655 if(pic14_sameRegs(AOP(result),AOP(left))){
5657 for(;size--; offset++,lit>>=8) {
5658 if(AOP_TYPE(right) == AOP_LIT){
5659 switch(lit & 0xff) {
5661 /* and'ing with 0 has clears the result */
5662 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5665 /* and'ing with 0xff is a nop when the result and left are the same */
5670 int p = my_powof2( (~lit) & 0xff );
5672 /* only one bit is set in the literal, so use a bcf instruction */
5673 emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5676 if(know_W != (int)(lit&0xff))
5677 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5679 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5684 if (AOP_TYPE(left) == AOP_ACC) {
5685 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5687 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5688 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5695 // left & result in different registers
5696 if(AOP_TYPE(result) == AOP_CRY){
5698 // if(size), result in bit
5699 // if(!size && ifx), conditional oper: if(left & right)
5700 symbol *tlbl = newiTempLabel(NULL);
5701 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5703 pic14_emitcode("setb","c");
5705 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5706 pic14_emitcode("anl","a,%s",
5707 aopGet(AOP(left),offset,FALSE,FALSE));
5708 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5713 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5714 pic14_outBitC(result);
5716 jmpTrueOrFalse(ifx, tlbl);
5718 for(;(size--);offset++) {
5720 // result = left & right
5721 if(AOP_TYPE(right) == AOP_LIT){
5722 int t = (lit >> (offset*8)) & 0x0FFL;
5725 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5728 if(AOP_TYPE(left) != AOP_ACC) {
5729 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5731 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5734 if(AOP_TYPE(left) == AOP_ACC) {
5735 emitpcode(POC_ANDLW, popGetLit(t));
5737 emitpcode(POC_MOVLW, popGetLit(t));
5738 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5740 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5745 if (AOP_TYPE(left) == AOP_ACC) {
5746 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5748 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5749 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5751 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5757 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5758 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5759 freeAsmop(result,NULL,ic,TRUE);
5762 /*-----------------------------------------------------------------*/
5763 /* genOr - code for or */
5764 /*-----------------------------------------------------------------*/
5765 static void genOr (iCode *ic, iCode *ifx)
5767 operand *left, *right, *result;
5769 unsigned long lit = 0L;
5772 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5774 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5775 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5776 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5778 DEBUGpic14_AopType(__LINE__,left,right,result);
5780 /* if left is a literal & right is not then exchange them */
5781 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5782 AOP_NEEDSACC(left)) {
5783 operand *tmp = right ;
5788 /* if result = right then exchange them */
5789 if(pic14_sameRegs(AOP(result),AOP(right))){
5790 operand *tmp = right ;
5795 /* if right is bit then exchange them */
5796 if (AOP_TYPE(right) == AOP_CRY &&
5797 AOP_TYPE(left) != AOP_CRY){
5798 operand *tmp = right ;
5803 DEBUGpic14_AopType(__LINE__,left,right,result);
5805 if(AOP_TYPE(right) == AOP_LIT)
5806 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5808 size = AOP_SIZE(result);
5812 if (AOP_TYPE(left) == AOP_CRY){
5813 if(AOP_TYPE(right) == AOP_LIT){
5814 // c = bit & literal;
5816 // lit != 0 => result = 1
5817 if(AOP_TYPE(result) == AOP_CRY){
5819 emitpcode(POC_BSF, popGet(AOP(result),0));
5820 //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5821 // AOP(result)->aopu.aop_dir,
5822 // AOP(result)->aopu.aop_dir);
5824 continueIfTrue(ifx);
5828 // lit == 0 => result = left
5829 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5831 pic14_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5834 if (AOP_TYPE(right) == AOP_CRY){
5835 if(pic14_sameRegs(AOP(result),AOP(left))){
5837 emitpcode(POC_BCF, popGet(AOP(result),0));
5838 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5839 emitpcode(POC_BSF, popGet(AOP(result),0));
5841 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5842 AOP(result)->aopu.aop_dir,
5843 AOP(result)->aopu.aop_dir);
5844 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5845 AOP(right)->aopu.aop_dir,
5846 AOP(right)->aopu.aop_dir);
5847 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5848 AOP(result)->aopu.aop_dir,
5849 AOP(result)->aopu.aop_dir);
5851 if( AOP_TYPE(result) == AOP_ACC) {
5852 emitpcode(POC_MOVLW, popGetLit(0));
5853 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5854 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5855 emitpcode(POC_MOVLW, popGetLit(1));
5859 emitpcode(POC_BCF, popGet(AOP(result),0));
5860 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5861 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5862 emitpcode(POC_BSF, popGet(AOP(result),0));
5864 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5865 AOP(result)->aopu.aop_dir,
5866 AOP(result)->aopu.aop_dir);
5867 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5868 AOP(right)->aopu.aop_dir,
5869 AOP(right)->aopu.aop_dir);
5870 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5871 AOP(left)->aopu.aop_dir,
5872 AOP(left)->aopu.aop_dir);
5873 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5874 AOP(result)->aopu.aop_dir,
5875 AOP(result)->aopu.aop_dir);
5880 symbol *tlbl = newiTempLabel(NULL);
5881 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5884 emitpcode(POC_BCF, popGet(AOP(result),0));
5885 if( AOP_TYPE(right) == AOP_ACC) {
5886 emitpcode(POC_IORLW, popGetLit(0));
5888 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5889 emitpcode(POC_BSF, popGet(AOP(result),0));
5894 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5895 pic14_emitcode(";XXX setb","c");
5896 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5897 AOP(left)->aopu.aop_dir,tlbl->key+100);
5898 pic14_toBoolean(right);
5899 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5900 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5901 jmpTrueOrFalse(ifx, tlbl);
5905 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5912 pic14_outBitC(result);
5914 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5915 genIfxJump(ifx, "c");
5919 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5920 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5921 if((AOP_TYPE(right) == AOP_LIT) &&
5922 (AOP_TYPE(result) == AOP_CRY) &&
5923 (AOP_TYPE(left) != AOP_CRY)){
5925 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5928 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5930 continueIfTrue(ifx);
5933 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5934 // lit = 0, result = boolean(left)
5936 pic14_emitcode(";XXX setb","c");
5937 pic14_toBoolean(right);
5939 symbol *tlbl = newiTempLabel(NULL);
5940 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5942 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5944 genIfxJump (ifx,"a");
5948 pic14_outBitC(result);
5952 /* if left is same as result */
5953 if(pic14_sameRegs(AOP(result),AOP(left))){
5955 for(;size--; offset++,lit>>=8) {
5956 if(AOP_TYPE(right) == AOP_LIT){
5957 if((lit & 0xff) == 0)
5958 /* or'ing with 0 has no effect */
5961 int p = my_powof2(lit & 0xff);
5963 /* only one bit is set in the literal, so use a bsf instruction */
5965 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5967 if(know_W != (int)(lit & 0xff))
5968 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5969 know_W = lit & 0xff;
5970 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5975 if (AOP_TYPE(left) == AOP_ACC) {
5976 emitpcode(POC_IORFW, popGet(AOP(right),offset));
5977 pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5979 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
5980 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5982 pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5983 pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5989 // left & result in different registers
5990 if(AOP_TYPE(result) == AOP_CRY){
5992 // if(size), result in bit
5993 // if(!size && ifx), conditional oper: if(left | right)
5994 symbol *tlbl = newiTempLabel(NULL);
5995 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5996 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6000 pic14_emitcode(";XXX setb","c");
6002 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6003 pic14_emitcode(";XXX orl","a,%s",
6004 aopGet(AOP(left),offset,FALSE,FALSE));
6005 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6010 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6011 pic14_outBitC(result);
6013 jmpTrueOrFalse(ifx, tlbl);
6014 } else for(;(size--);offset++){
6016 // result = left | right
6017 if(AOP_TYPE(right) == AOP_LIT){
6018 int t = (lit >> (offset*8)) & 0x0FFL;
6021 if (AOP_TYPE(left) != AOP_ACC) {
6022 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
6024 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6028 if (AOP_TYPE(left) == AOP_ACC) {
6029 emitpcode(POC_IORLW, popGetLit(t));
6031 emitpcode(POC_MOVLW, popGetLit(t));
6032 emitpcode(POC_IORFW, popGet(AOP(left),offset));
6034 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6039 // faster than result <- left, anl result,right
6040 // and better if result is SFR
6041 if (AOP_TYPE(left) == AOP_ACC) {
6042 emitpcode(POC_IORFW,popGet(AOP(right),offset));
6044 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6045 emitpcode(POC_IORFW,popGet(AOP(left),offset));
6047 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6052 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6053 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6054 freeAsmop(result,NULL,ic,TRUE);
6057 /*-----------------------------------------------------------------*/
6058 /* genXor - code for xclusive or */
6059 /*-----------------------------------------------------------------*/
6060 static void genXor (iCode *ic, iCode *ifx)
6062 operand *left, *right, *result;
6064 unsigned long lit = 0L;
6067 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6069 aopOp((left = IC_LEFT(ic)),ic,FALSE);
6070 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6071 aopOp((result=IC_RESULT(ic)),ic,TRUE);
6073 /* if left is a literal & right is not ||
6074 if left needs acc & right does not */
6075 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6076 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6077 operand *tmp = right ;
6082 /* if result = right then exchange them */
6083 if(pic14_sameRegs(AOP(result),AOP(right))){
6084 operand *tmp = right ;
6089 /* if right is bit then exchange them */
6090 if (AOP_TYPE(right) == AOP_CRY &&
6091 AOP_TYPE(left) != AOP_CRY){
6092 operand *tmp = right ;
6096 if(AOP_TYPE(right) == AOP_LIT)
6097 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6099 size = AOP_SIZE(result);
6103 if (AOP_TYPE(left) == AOP_CRY){
6104 if(AOP_TYPE(right) == AOP_LIT){
6105 // c = bit & literal;
6107 // lit>>1 != 0 => result = 1
6108 if(AOP_TYPE(result) == AOP_CRY){
6110 {emitpcode(POC_BSF, popGet(AOP(result),offset));
6111 pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6113 continueIfTrue(ifx);
6116 pic14_emitcode("setb","c");
6120 // lit == 0, result = left
6121 if(size && pic14_sameRegs(AOP(result),AOP(left)))
6123 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6125 // lit == 1, result = not(left)
6126 if(size && pic14_sameRegs(AOP(result),AOP(left))){
6127 emitpcode(POC_MOVLW, popGet(AOP(result),offset));
6128 emitpcode(POC_XORWF, popGet(AOP(result),offset));
6129 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6132 assert ( !"incomplete genXor" );
6133 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6134 pic14_emitcode("cpl","c");
6141 symbol *tlbl = newiTempLabel(NULL);
6142 if (AOP_TYPE(right) == AOP_CRY){
6144 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6147 int sizer = AOP_SIZE(right);
6149 // if val>>1 != 0, result = 1
6150 pic14_emitcode("setb","c");
6152 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6154 // test the msb of the lsb
6155 pic14_emitcode("anl","a,#0xfe");
6156 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6160 pic14_emitcode("rrc","a");
6162 pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6163 pic14_emitcode("cpl","c");
6164 pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6169 pic14_outBitC(result);
6171 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6172 genIfxJump(ifx, "c");
6176 if(pic14_sameRegs(AOP(result),AOP(left))){
6177 /* if left is same as result */
6178 for(;size--; offset++) {
6179 if(AOP_TYPE(right) == AOP_LIT){
6180 int t = (lit >> (offset*8)) & 0x0FFL;
6184 if (IS_AOP_PREG(left)) {
6185 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6186 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6187 aopPut(AOP(result),"a",offset);
6189 emitpcode(POC_MOVLW, popGetLit(t));
6190 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6191 pic14_emitcode("xrl","%s,%s",
6192 aopGet(AOP(left),offset,FALSE,TRUE),
6193 aopGet(AOP(right),offset,FALSE,FALSE));
6196 if (AOP_TYPE(left) == AOP_ACC)
6197 pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6199 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6200 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6202 if (IS_AOP_PREG(left)) {
6203 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6204 aopPut(AOP(result),"a",offset);
6206 pic14_emitcode("xrl","%s,a",
6207 aopGet(AOP(left),offset,FALSE,TRUE));
6213 // left & result in different registers
6214 if(AOP_TYPE(result) == AOP_CRY){
6216 // if(size), result in bit
6217 // if(!size && ifx), conditional oper: if(left ^ right)
6218 symbol *tlbl = newiTempLabel(NULL);
6219 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6221 pic14_emitcode("setb","c");
6223 if((AOP_TYPE(right) == AOP_LIT) &&
6224 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6225 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6227 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6228 pic14_emitcode("xrl","a,%s",
6229 aopGet(AOP(left),offset,FALSE,FALSE));
6231 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6236 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6237 pic14_outBitC(result);
6239 jmpTrueOrFalse(ifx, tlbl);
6240 } else for(;(size--);offset++){
6242 // result = left & right
6243 if(AOP_TYPE(right) == AOP_LIT){
6244 int t = (lit >> (offset*8)) & 0x0FFL;
6247 if (AOP_TYPE(left) != AOP_ACC) {
6248 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6250 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6251 pic14_emitcode("movf","%s,w",
6252 aopGet(AOP(left),offset,FALSE,FALSE));
6253 pic14_emitcode("movwf","%s",
6254 aopGet(AOP(result),offset,FALSE,FALSE));
6257 if (AOP_TYPE(left) == AOP_ACC) {
6258 emitpcode(POC_XORLW, popGetLit(t));
6260 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6262 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6265 if (AOP_TYPE(left) == AOP_ACC) {
6266 emitpcode(POC_XORLW, popGetLit(t));
6268 emitpcode(POC_MOVLW, popGetLit(t));
6269 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6271 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6272 pic14_emitcode("movlw","0x%x",t);
6273 pic14_emitcode("xorwf","%s,w",
6274 aopGet(AOP(left),offset,FALSE,FALSE));
6275 pic14_emitcode("movwf","%s",
6276 aopGet(AOP(result),offset,FALSE,FALSE));
6282 // faster than result <- left, anl result,right
6283 // and better if result is SFR
6284 if (AOP_TYPE(left) == AOP_ACC) {
6285 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6287 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6288 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6290 if ( AOP_TYPE(result) != AOP_ACC){
6291 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6297 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6298 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6299 freeAsmop(result,NULL,ic,TRUE);
6302 /*-----------------------------------------------------------------*/
6303 /* genInline - write the inline code out */
6304 /*-----------------------------------------------------------------*/
6305 static void genInline (iCode *ic)
6307 char *buffer, *bp, *bp1;
6310 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6312 _G.inLine += (!options.asmpeep);
6314 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6315 strcpy(buffer,IC_INLINE(ic));
6317 /* emit each line as a code */
6323 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6331 /* print label, use this special format with NULL directive
6332 * to denote that the argument should not be indented with tab */
6333 addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6340 if ((bp1 != bp) && *bp1)
6341 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6345 _G.inLine -= (!options.asmpeep);
6348 /*-----------------------------------------------------------------*/
6349 /* genRRC - rotate right with carry */
6350 /*-----------------------------------------------------------------*/
6351 static void genRRC (iCode *ic)
6353 operand *left , *result ;
6354 int size, offset = 0, same;
6357 /* rotate right with carry */
6359 result=IC_RESULT(ic);
6360 aopOp (left,ic,FALSE);
6361 aopOp (result,ic,FALSE);
6363 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6365 same = pic14_sameRegs(AOP(result),AOP(left));
6367 size = AOP_SIZE(result);
6369 /* get the lsb and put it into the carry */
6370 emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6377 emitpcode(POC_RRF, popGet(AOP(left),offset));
6379 emitpcode(POC_RRFW, popGet(AOP(left),offset));
6380 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6386 freeAsmop(left,NULL,ic,TRUE);
6387 freeAsmop(result,NULL,ic,TRUE);
6390 /*-----------------------------------------------------------------*/
6391 /* genRLC - generate code for rotate left with carry */
6392 /*-----------------------------------------------------------------*/
6393 static void genRLC (iCode *ic)
6395 operand *left , *result ;
6396 int size, offset = 0;
6400 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6401 /* rotate right with carry */
6403 result=IC_RESULT(ic);
6404 aopOp (left,ic,FALSE);
6405 aopOp (result,ic,FALSE);
6407 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6409 same = pic14_sameRegs(AOP(result),AOP(left));
6411 /* move it to the result */
6412 size = AOP_SIZE(result);
6414 /* get the msb and put it into the carry */
6415 emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6422 emitpcode(POC_RLF, popGet(AOP(left),offset));
6424 emitpcode(POC_RLFW, popGet(AOP(left),offset));
6425 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6432 freeAsmop(left,NULL,ic,TRUE);
6433 freeAsmop(result,NULL,ic,TRUE);
6436 /*-----------------------------------------------------------------*/
6437 /* genGetHbit - generates code get highest order bit */
6438 /*-----------------------------------------------------------------*/
6439 static void genGetHbit (iCode *ic)
6441 operand *left, *result;
6443 result=IC_RESULT(ic);
6444 aopOp (left,ic,FALSE);
6445 aopOp (result,ic,FALSE);
6448 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6449 /* get the highest order byte into a */
6450 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6451 if(AOP_TYPE(result) == AOP_CRY){
6452 pic14_emitcode("rlc","a");
6453 pic14_outBitC(result);
6456 pic14_emitcode("rl","a");
6457 pic14_emitcode("anl","a,#0x01");
6458 pic14_outAcc(result);
6462 freeAsmop(left,NULL,ic,TRUE);
6463 freeAsmop(result,NULL,ic,TRUE);
6466 /*-----------------------------------------------------------------*/
6467 /* AccLsh - shift left accumulator by known count */
6468 /* MARK: pic14 always rotates through CARRY! */
6469 /*-----------------------------------------------------------------*/
6470 static void AccLsh (pCodeOp *pcop,int shCount)
6473 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6474 shCount &= 0x0007; // shCount : 0..7
6481 emitpcode(POC_RLF,pcop);
6485 emitpcode(POC_RLF,pcop);
6486 emitpcode(POC_RLF,pcop);
6489 emitpcode(POC_RLF,pcop);
6490 emitpcode(POC_RLF,pcop);
6491 emitpcode(POC_RLF,pcop);
6494 emitpcode(POC_SWAPF,pcop);
6497 emitpcode(POC_SWAPF,pcop);
6498 emitpcode(POC_RLF,pcop);
6501 emitpcode(POC_SWAPF,pcop);
6502 emitpcode(POC_RLF,pcop);
6503 emitpcode(POC_RLF,pcop);
6506 emitpcode(POC_RRFW,pcop);
6507 emitpcode(POC_RRF,pcop);
6510 /* clear invalid bits */
6511 emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6512 emitpcode(POC_ANDWF, pcop);
6515 /*-----------------------------------------------------------------*/
6516 /* AccRsh - shift right accumulator by known count */
6517 /* MARK: pic14 always rotates through CARRY! */
6518 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6519 /* 1: mask out invalid bits (zero-extend) */
6520 /* 2: sign-extend result (pretty slow) */
6521 /*-----------------------------------------------------------------*/
6522 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6525 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6526 shCount &= 0x0007; // shCount : 0..7
6532 /* load sign if needed */
6533 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6534 else if (mask_mode == 1) emitCLRC;
6535 emitpcode(POC_RRF,pcop);
6539 /* load sign if needed */
6540 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6541 emitpcode(POC_RRF,pcop);
6542 /* load sign if needed */
6543 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6544 emitpcode(POC_RRF,pcop);
6545 if (mask_mode == 2) return;
6548 /* load sign if needed */
6549 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6550 emitpcode(POC_RRF,pcop);
6551 /* load sign if needed */
6552 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6553 emitpcode(POC_RRF,pcop);
6554 /* load sign if needed */
6555 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6556 emitpcode(POC_RRF,pcop);
6557 if (mask_mode == 2) return;
6560 emitpcode(POC_SWAPF,pcop);
6563 emitpcode(POC_SWAPF,pcop);
6564 emitpcode(POC_RRF,pcop);
6567 emitpcode(POC_SWAPF,pcop);
6568 emitpcode(POC_RRF,pcop);
6569 emitpcode(POC_RRF,pcop);
6575 emitpcode(POC_RLFW,pcop);
6576 emitpcode(POC_CLRF,pcop);
6578 emitpcode(POC_COMF,pcop);
6581 emitpcode(POC_RLFW,pcop);
6582 emitpcode(POC_RLF,pcop);
6589 /* leave invalid bits undefined */
6593 /* clear invalid bits -- zero-extend */
6594 emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6595 emitpcode(POC_ANDWF, pcop);
6597 if (mask_mode == 2) {
6599 emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6600 emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6601 emitpcode(POC_IORWF, pcop);
6606 /*-----------------------------------------------------------------*/
6607 /* AccSRsh - signed right shift accumulator by known count */
6608 /*-----------------------------------------------------------------*/
6609 static void AccSRsh (int shCount)
6612 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6615 pic14_emitcode("mov","c,acc.7");
6616 pic14_emitcode("rrc","a");
6617 } else if(shCount == 2){
6618 pic14_emitcode("mov","c,acc.7");
6619 pic14_emitcode("rrc","a");
6620 pic14_emitcode("mov","c,acc.7");
6621 pic14_emitcode("rrc","a");
6623 tlbl = newiTempLabel(NULL);
6624 /* rotate right accumulator */
6625 AccRol(8 - shCount);
6626 /* and kill the higher order bits */
6627 pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6628 pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6629 pic14_emitcode("orl","a,#0x%02x",
6630 (unsigned char)~SRMask[shCount]);
6631 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6636 /*-----------------------------------------------------------------*/
6637 /* shiftR1Left2Result - shift right one byte from left to result */
6638 /*-----------------------------------------------------------------*/
6639 static void shiftR1Left2ResultSigned (operand *left, int offl,
6640 operand *result, int offr,
6646 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6648 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6652 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6654 emitpcode(POC_RRF, popGet(AOP(result),offr));
6656 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6657 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6663 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6665 emitpcode(POC_RRF, popGet(AOP(result),offr));
6667 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6668 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6670 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6671 emitpcode(POC_RRF, popGet(AOP(result),offr));
6677 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6679 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6680 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6683 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6684 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6685 emitpcode(POC_ANDLW, popGetLit(0x1f));
6687 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6688 emitpcode(POC_IORLW, popGetLit(0xe0));
6690 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6694 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6695 emitpcode(POC_ANDLW, popGetLit(0x0f));
6696 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6697 emitpcode(POC_IORLW, popGetLit(0xf0));
6698 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6702 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6704 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6705 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6707 emitpcode(POC_RRFW, popGet(AOP(result),offr));
6708 emitpcode(POC_ANDLW, popGetLit(0x07));
6709 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6710 emitpcode(POC_IORLW, popGetLit(0xf8));
6711 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6716 emitpcode(POC_MOVLW, popGetLit(0x00));
6717 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6718 emitpcode(POC_MOVLW, popGetLit(0xfe));
6719 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6720 emitpcode(POC_IORLW, popGetLit(0x01));
6721 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6723 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6724 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6725 emitpcode(POC_DECF, popGet(AOP(result),offr));
6726 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6727 emitpcode(POC_BCF, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6733 emitpcode(POC_MOVLW, popGetLit(0x00));
6734 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6735 emitpcode(POC_MOVLW, popGetLit(0xff));
6736 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6738 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6739 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6740 emitpcode(POC_DECF, popGet(AOP(result),offr));
6748 /*-----------------------------------------------------------------*/
6749 /* shiftR1Left2Result - shift right one byte from left to result */
6750 /*-----------------------------------------------------------------*/
6751 static void shiftR1Left2Result (operand *left, int offl,
6752 operand *result, int offr,
6753 int shCount, int sign)
6758 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6760 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6762 /* Copy the msb into the carry if signed. */
6764 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6774 emitpcode(POC_RRF, popGet(AOP(result),offr));
6776 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6777 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6783 emitpcode(POC_RRF, popGet(AOP(result),offr));
6785 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6786 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6789 emitpcode(POC_RRF, popGet(AOP(result),offr));
6794 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6796 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6797 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6800 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6801 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6802 emitpcode(POC_ANDLW, popGetLit(0x1f));
6803 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6807 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6808 emitpcode(POC_ANDLW, popGetLit(0x0f));
6809 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6813 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6814 emitpcode(POC_ANDLW, popGetLit(0x0f));
6815 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6817 emitpcode(POC_RRF, popGet(AOP(result),offr));
6822 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6823 emitpcode(POC_ANDLW, popGetLit(0x80));
6824 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6825 emitpcode(POC_RLF, popGet(AOP(result),offr));
6826 emitpcode(POC_RLF, popGet(AOP(result),offr));
6831 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6832 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6833 emitpcode(POC_RLF, popGet(AOP(result),offr));
6842 /*-----------------------------------------------------------------*/
6843 /* shiftL1Left2Result - shift left one byte from left to result */
6844 /*-----------------------------------------------------------------*/
6845 static void shiftL1Left2Result (operand *left, int offl,
6846 operand *result, int offr, int shCount)
6852 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6854 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6855 DEBUGpic14_emitcode ("; ***","same = %d",same);
6856 // l = aopGet(AOP(left),offl,FALSE,FALSE);
6858 /* shift left accumulator */
6859 //AccLsh(shCount); // don't comment out just yet...
6860 // aopPut(AOP(result),"a",offr);
6864 /* Shift left 1 bit position */
6865 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6867 emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6869 emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6870 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6874 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6875 emitpcode(POC_ANDLW,popGetLit(0x7e));
6876 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6877 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6880 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6881 emitpcode(POC_ANDLW,popGetLit(0x3e));
6882 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6883 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6884 emitpcode(POC_RLF, popGet(AOP(result),offr));
6887 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6888 emitpcode(POC_ANDLW, popGetLit(0xf0));
6889 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6892 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6893 emitpcode(POC_ANDLW, popGetLit(0xf0));
6894 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6895 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6898 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6899 emitpcode(POC_ANDLW, popGetLit(0x30));
6900 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6901 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6902 emitpcode(POC_RLF, popGet(AOP(result),offr));
6905 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6906 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6907 emitpcode(POC_RRF, popGet(AOP(result),offr));
6911 DEBUGpic14_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6917 /*-----------------------------------------------------------------*/
6918 /* movLeft2Result - move byte from left to result */
6919 /*-----------------------------------------------------------------*/
6920 static void movLeft2Result (operand *left, int offl,
6921 operand *result, int offr)
6925 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6926 if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6927 l = aopGet(AOP(left),offl,FALSE,FALSE);
6929 if (*l == '@' && (IS_AOP_PREG(result))) {
6930 pic14_emitcode("mov","a,%s",l);
6931 aopPut(AOP(result),"a",offr);
6933 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6934 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6939 /*-----------------------------------------------------------------*/
6940 /* shiftLeft_Left2ResultLit - shift left by known count */
6941 /*-----------------------------------------------------------------*/
6943 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6945 int size, same, offr, i;
6947 size = AOP_SIZE(left);
6948 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6950 same = pic14_sameRegs (AOP(left), AOP(result));
6953 shCount = shCount & 0x07;
6959 case 0: /* takes 0 or 2N cycles (for offr==0) */
6960 if (!same || offr) {
6961 for (i=size-1; i >= 0; i--)
6962 movLeft2Result (left, i, result, offr + i);
6966 case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6968 shiftLeft_Left2ResultLit (left, result, 8 * offr);
6969 shiftLeft_Left2ResultLit (result, result, shCount);
6970 return; /* prevent clearing result again */
6973 for (i=0; i < size; i++) {
6974 if (same && !offr) {
6975 emitpcode (POC_RLF, popGet (AOP(left), i));
6977 emitpcode (POC_RLFW, popGet (AOP(left), i));
6978 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6984 case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
6985 /* works in-place/with offr as well */
6986 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
6987 emitpcode (POC_ANDLW, popGetLit (0xF0));
6988 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
6990 for (i = size - 2; i >= 0; i--)
6992 emitpcode (POC_SWAPFW, popGet (AOP(left), i));
6993 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6994 emitpcode (POC_ANDLW, popGetLit (0x0F));
6995 emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
6996 emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
7000 case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
7001 /* works in-place/with offr as well */
7002 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
7003 for (i = size-2; i >= 0; i--) {
7004 emitpcode (POC_RRFW, popGet (AOP(left), i));
7005 emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
7007 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7008 emitpcode (POC_RRF, popGet (AOP(result), offr));
7012 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
7013 shiftLeft_Left2ResultLit (result, result, 1);
7014 return; /* prevent clearing result again */
7020 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7024 /*-----------------------------------------------------------------*/
7025 /* shiftRight_Left2ResultLit - shift right by known count */
7026 /*-----------------------------------------------------------------*/
7028 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
7030 int size, same, offr, i;
7032 size = AOP_SIZE(left);
7033 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7035 same = pic14_sameRegs (AOP(left), AOP(result));
7038 shCount = shCount & 0x07;
7046 case 0: /* takes 0 or 2N cycles (for offr==0) */
7047 if (!same || offr) {
7048 for (i=0; i < size; i++)
7049 movLeft2Result (left, i + offr, result, i);
7053 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7054 emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7056 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7057 shiftRight_Left2ResultLit (result, result, shCount, sign);
7058 return; /* prevent sign-extending result again */
7062 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7065 for (i = size-1; i >= 0; i--) {
7066 if (same && !offr) {
7067 emitpcode (POC_RRF, popGet (AOP(left), i));
7069 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7070 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7076 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7077 /* works in-place/with offr as well */
7078 emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7079 emitpcode (POC_ANDLW, popGetLit (0x0F));
7080 emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7082 for (i = 1; i < size; i++)
7084 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7085 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7086 emitpcode (POC_ANDLW, popGetLit (0xF0));
7087 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7088 emitpcode (POC_XORWF, popGet (AOP(result), i));
7093 emitpcode (POC_MOVLW, popGetLit (0xF0));
7094 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7095 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7099 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7100 /* works in-place/with offr as well */
7101 emitpcode (POC_RLFW, popGet (AOP(left), offr));
7102 for (i = 0; i < size-1; i++) {
7103 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7104 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7106 emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7108 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7111 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7116 shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7117 shiftRight_Left2ResultLit (result, result, 1, sign);
7118 return; /* prevent sign extending result again */
7123 addSign (result, size, sign);
7127 /*-----------------------------------------------------------------*/
7128 /* shiftL2Left2Result - shift left two bytes from left to result */
7129 /*-----------------------------------------------------------------*/
7130 static void shiftL2Left2Result (operand *left, int offl,
7131 operand *result, int offr, int shCount)
7135 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7137 if(pic14_sameRegs(AOP(result), AOP(left))) {
7145 emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7146 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7147 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7151 emitpcode(POC_RLF, popGet(AOP(result),offr));
7152 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7158 emitpcode(POC_MOVLW, popGetLit(0x0f));
7159 emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7160 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7161 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7162 emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7163 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7164 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7166 emitpcode(POC_RLF, popGet(AOP(result),offr));
7167 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7171 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7172 emitpcode(POC_RRF, popGet(AOP(result),offr));
7173 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7174 emitpcode(POC_RRF, popGet(AOP(result),offr));
7175 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7176 emitpcode(POC_ANDLW,popGetLit(0xc0));
7177 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7178 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7179 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7180 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7183 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7184 emitpcode(POC_RRFW, popGet(AOP(result),offr));
7185 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7186 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7187 emitpcode(POC_RRF, popGet(AOP(result),offr));
7197 /* note, use a mov/add for the shift since the mov has a
7198 chance of getting optimized out */
7199 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7200 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7201 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7202 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7203 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7207 emitpcode(POC_RLF, popGet(AOP(result),offr));
7208 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7214 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7215 emitpcode(POC_ANDLW, popGetLit(0xF0));
7216 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7217 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7218 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7219 emitpcode(POC_ANDLW, popGetLit(0xF0));
7220 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7221 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7225 emitpcode(POC_RLF, popGet(AOP(result),offr));
7226 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7230 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7231 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7232 emitpcode(POC_RRFW, popGet(AOP(result),offl));
7233 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7235 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7236 emitpcode(POC_RRF, popGet(AOP(result),offr));
7237 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7238 emitpcode(POC_ANDLW,popGetLit(0xc0));
7239 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7240 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7241 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7242 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7245 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7246 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7247 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7248 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7249 emitpcode(POC_RRF, popGet(AOP(result),offr));
7255 /*-----------------------------------------------------------------*/
7256 /* shiftR2Left2Result - shift right two bytes from left to result */
7257 /*-----------------------------------------------------------------*/
7258 static void shiftR2Left2Result (operand *left, int offl,
7259 operand *result, int offr,
7260 int shCount, int sign)
7265 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7266 same = pic14_sameRegs(AOP(result), AOP(left));
7268 if(same && ((offl + MSB16) == offr)){
7270 /* don't crash result[offr] */
7271 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7272 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7275 movLeft2Result(left,offl, result, offr);
7276 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7279 /* a:x >> shCount (x = lsb(result))*/
7282 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7284 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7293 emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7298 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7299 emitpcode(POC_RRF,popGet(AOP(result),offr));
7301 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7302 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7303 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7304 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7309 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7312 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7313 emitpcode(POC_RRF,popGet(AOP(result),offr));
7320 emitpcode(POC_MOVLW, popGetLit(0xf0));
7321 emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7322 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7324 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7325 emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7326 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7327 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7329 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7330 emitpcode(POC_ANDLW, popGetLit(0x0f));
7331 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7333 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7334 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7335 emitpcode(POC_ANDLW, popGetLit(0xf0));
7336 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7337 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7341 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7342 emitpcode(POC_RRF, popGet(AOP(result),offr));
7346 emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7347 emitpcode(POC_BTFSC,
7348 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7349 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7357 emitpcode(POC_RLF, popGet(AOP(result),offr));
7358 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7360 emitpcode(POC_RLF, popGet(AOP(result),offr));
7361 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7362 emitpcode(POC_RLFW, popGet(AOP(result),offr));
7363 emitpcode(POC_ANDLW,popGetLit(0x03));
7365 emitpcode(POC_BTFSC,
7366 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7367 emitpcode(POC_IORLW,popGetLit(0xfc));
7369 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7370 emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7371 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7372 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7374 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7375 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7376 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7377 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7378 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7379 emitpcode(POC_RLF, popGet(AOP(result),offr));
7380 emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7381 emitpcode(POC_ANDLW,popGetLit(0x03));
7383 emitpcode(POC_BTFSC,
7384 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7385 emitpcode(POC_IORLW,popGetLit(0xfc));
7387 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7388 //emitpcode(POC_RLF, popGet(AOP(result),offr));
7395 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7396 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7397 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7398 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7401 emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7403 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7407 /*-----------------------------------------------------------------*/
7408 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7409 /*-----------------------------------------------------------------*/
7410 static void shiftLLeftOrResult (operand *left, int offl,
7411 operand *result, int offr, int shCount)
7414 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7416 /* shift left accumulator */
7417 AccLsh(left,offl,shCount);
7418 /* or with result */
7419 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7420 assert ( !"broken (modifies left, fails for left==result))" );
7423 /*-----------------------------------------------------------------*/
7424 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7425 /*-----------------------------------------------------------------*/
7426 static void shiftRLeftOrResult (operand *left, int offl,
7427 operand *result, int offr, int shCount)
7430 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7432 /* shift right accumulator */
7433 AccRsh(left,offl,shCount);
7434 /* or with result */
7435 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7436 assert ( !"broken (modifies left, fails for left==result))" );
7439 /*-----------------------------------------------------------------*/
7440 /* genlshOne - left shift a one byte quantity by known count */
7441 /*-----------------------------------------------------------------*/
7442 static void genlshOne (operand *result, operand *left, int shCount)
7445 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7446 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7449 /*-----------------------------------------------------------------*/
7450 /* genlshTwo - left shift two bytes by known amount != 0 */
7451 /*-----------------------------------------------------------------*/
7452 static void genlshTwo (operand *result,operand *left, int shCount)
7457 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7458 size = pic14_getDataSize(result);
7460 /* if shCount >= 8 */
7466 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7468 movLeft2Result(left, LSB, result, MSB16);
7470 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7473 /* 1 <= shCount <= 7 */
7476 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7478 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7482 /*-----------------------------------------------------------------*/
7483 /* shiftLLong - shift left one long from left to result */
7484 /* offl = LSB or MSB16 */
7485 /*-----------------------------------------------------------------*/
7486 static void shiftLLong (operand *left, operand *result, int offr )
7489 int size = AOP_SIZE(result);
7492 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7493 if(size >= LSB+offr){
7494 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7496 pic14_emitcode("add","a,acc");
7497 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7498 size >= MSB16+offr && offr != LSB )
7499 pic14_emitcode("xch","a,%s",
7500 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7502 aopPut(AOP(result),"a",LSB+offr);
7505 if(size >= MSB16+offr){
7506 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7507 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7510 pic14_emitcode("rlc","a");
7511 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7512 size >= MSB24+offr && offr != LSB)
7513 pic14_emitcode("xch","a,%s",
7514 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7516 aopPut(AOP(result),"a",MSB16+offr);
7519 if(size >= MSB24+offr){
7520 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7521 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7524 pic14_emitcode("rlc","a");
7525 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7526 size >= MSB32+offr && offr != LSB )
7527 pic14_emitcode("xch","a,%s",
7528 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7530 aopPut(AOP(result),"a",MSB24+offr);
7533 if(size > MSB32+offr){
7534 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7535 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7538 pic14_emitcode("rlc","a");
7539 aopPut(AOP(result),"a",MSB32+offr);
7542 aopPut(AOP(result),zero,LSB);
7545 /*-----------------------------------------------------------------*/
7546 /* genlshFour - shift four byte by a known amount != 0 */
7547 /*-----------------------------------------------------------------*/
7548 static void genlshFour (operand *result, operand *left, int shCount)
7553 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7554 size = AOP_SIZE(result);
7556 /* if shifting more that 3 bytes */
7557 if (shCount >= 24 ) {
7560 /* lowest order of left goes to the highest
7561 order of the destination */
7562 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7564 movLeft2Result(left, LSB, result, MSB32);
7565 aopPut(AOP(result),zero,LSB);
7566 aopPut(AOP(result),zero,MSB16);
7567 aopPut(AOP(result),zero,MSB32);
7571 /* more than two bytes */
7572 else if ( shCount >= 16 ) {
7573 /* lower order two bytes goes to higher order two bytes */
7575 /* if some more remaining */
7577 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7579 movLeft2Result(left, MSB16, result, MSB32);
7580 movLeft2Result(left, LSB, result, MSB24);
7582 aopPut(AOP(result),zero,MSB16);
7583 aopPut(AOP(result),zero,LSB);
7587 /* if more than 1 byte */
7588 else if ( shCount >= 8 ) {
7589 /* lower order three bytes goes to higher order three bytes */
7593 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7595 movLeft2Result(left, LSB, result, MSB16);
7597 else{ /* size = 4 */
7599 movLeft2Result(left, MSB24, result, MSB32);
7600 movLeft2Result(left, MSB16, result, MSB24);
7601 movLeft2Result(left, LSB, result, MSB16);
7602 aopPut(AOP(result),zero,LSB);
7604 else if(shCount == 1)
7605 shiftLLong(left, result, MSB16);
7607 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7608 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7609 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7610 aopPut(AOP(result),zero,LSB);
7615 /* 1 <= shCount <= 7 */
7616 else if(shCount <= 2){
7617 shiftLLong(left, result, LSB);
7619 shiftLLong(result, result, LSB);
7621 /* 3 <= shCount <= 7, optimize */
7623 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7624 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7625 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7631 /*-----------------------------------------------------------------*/
7632 /* genLeftShiftLiteral - left shifting by known count */
7633 /*-----------------------------------------------------------------*/
7634 static void genLeftShiftLiteral (operand *left,
7639 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7643 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7644 freeAsmop(right,NULL,ic,TRUE);
7646 aopOp(left,ic,FALSE);
7647 aopOp(result,ic,FALSE);
7649 size = getSize(operandType(result));
7652 pic14_emitcode("; shift left ","result %d, left %d",size,
7656 /* I suppose that the left size >= result size */
7659 movLeft2Result(left, size, result, size);
7663 else if(shCount >= (size * 8))
7665 aopPut(AOP(result),zero,size);
7669 genlshOne (result,left,shCount);
7674 genlshTwo (result,left,shCount);
7678 genlshFour (result,left,shCount);
7682 freeAsmop(left,NULL,ic,TRUE);
7683 freeAsmop(result,NULL,ic,TRUE);
7687 /*-----------------------------------------------------------------*
7688 * genMultiAsm - repeat assembly instruction for size of register.
7689 * if endian == 1, then the high byte (i.e base address + size of
7690 * register) is used first else the low byte is used first;
7691 *-----------------------------------------------------------------*/
7692 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7698 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7711 emitpcode(poc, popGet(AOP(reg),offset));
7718 /*-----------------------------------------------------------------*/
7719 /* genLeftShift - generates code for left shifting */
7720 /*-----------------------------------------------------------------*/
7721 static void genLeftShift (iCode *ic)
7723 operand *left,*right, *result;
7725 unsigned long lit = 0L;
7727 symbol *tlbl , *tlbl1;
7731 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7733 right = IC_RIGHT(ic);
7735 result = IC_RESULT(ic);
7737 aopOp(right,ic,FALSE);
7738 aopOp(left,ic,FALSE);
7739 aopOp(result,ic,FALSE);
7742 /* if the shift count is known then do it
7743 as efficiently as possible */
7744 if (AOP_TYPE(right) == AOP_LIT) {
7745 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7749 /* shift count is unknown then we have to form
7750 a loop get the loop count in B : Note: we take
7751 only the lower order byte since shifting
7752 more that 32 bits make no sense anyway, ( the
7753 largest size of an object can be only 32 bits ) */
7755 /* this code fails for RIGHT == RESULT */
7756 assert (!pic14_sameRegs (AOP(right), AOP(result)));
7758 /* now move the left to the result if they are not the
7760 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
7761 AOP_SIZE(result) > 1) {
7763 size = AOP_SIZE(result);
7766 l = aopGet(AOP(left),offset,FALSE,TRUE);
7767 if (*l == '@' && (IS_AOP_PREG(result))) {
7769 pic14_emitcode("mov","a,%s",l);
7770 aopPut(AOP(result),"a",offset);
7772 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
7773 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7774 //aopPut(AOP(result),l,offset);
7780 if(AOP_TYPE(left) == AOP_LIT)
7781 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7783 size = AOP_SIZE(result);
7785 /* if it is only one byte then */
7787 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7788 emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7789 emitpcode(POC_ANDLW, popGetLit(0xf0));
7790 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7791 emitpcode(POC_MOVFW, popGet(AOP(left),0));
7792 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7793 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7794 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7795 emitpcode(POC_RLFW, popGet(AOP(result),0));
7796 emitpcode(POC_ANDLW, popGetLit(0xfe));
7797 emitpcode(POC_ADDFW, popGet(AOP(result),0));
7798 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7799 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7802 tlbl = newiTempLabel(NULL);
7803 if (!pic14_sameRegs(AOP(left),AOP(result))) {
7804 mov2w (AOP(left), 0);
7805 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7808 emitpcode(POC_COMFW, popGet(AOP(right),0));
7809 emitpcode(POC_RRF, popGet(AOP(result),0));
7810 emitpLabel(tlbl->key);
7811 emitpcode(POC_RLF, popGet(AOP(result),0));
7812 emitpcode(POC_ADDLW, popGetLit(1));
7814 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7819 if (pic14_sameRegs(AOP(left),AOP(result))) {
7821 tlbl = newiTempLabel(NULL);
7822 emitpcode(POC_COMFW, popGet(AOP(right),0));
7823 genMultiAsm(POC_RRF, result, size,1);
7824 emitpLabel(tlbl->key);
7825 genMultiAsm(POC_RLF, result, size,0);
7826 emitpcode(POC_ADDLW, popGetLit(1));
7828 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7832 //tlbl = newiTempLabel(NULL);
7834 //tlbl1 = newiTempLabel(NULL);
7836 //reAdjustPreg(AOP(result));
7838 //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7839 //pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7840 //l = aopGet(AOP(result),offset,FALSE,FALSE);
7842 //pic14_emitcode("add","a,acc");
7843 //aopPut(AOP(result),"a",offset++);
7845 // l = aopGet(AOP(result),offset,FALSE,FALSE);
7847 // pic14_emitcode("rlc","a");
7848 // aopPut(AOP(result),"a",offset++);
7850 //reAdjustPreg(AOP(result));
7852 //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7853 //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7856 tlbl = newiTempLabel(NULL);
7857 tlbl1= newiTempLabel(NULL);
7859 size = AOP_SIZE(result);
7862 pctemp = popGetTempReg(); /* grab a temporary working register. */
7864 emitpcode(POC_MOVFW, popGet(AOP(right),0));
7866 /* offset should be 0, 1 or 3 */
7867 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7869 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
7871 emitpcode(POC_MOVWF, pctemp);
7874 emitpLabel(tlbl->key);
7877 emitpcode(POC_RLF, popGet(AOP(result),0));
7879 emitpcode(POC_RLF, popGet(AOP(result),offset++));
7881 emitpcode(POC_DECFSZ, pctemp);
7882 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7883 emitpLabel(tlbl1->key);
7885 popReleaseTempReg(pctemp);
7889 freeAsmop (right,NULL,ic,TRUE);
7890 freeAsmop(left,NULL,ic,TRUE);
7891 freeAsmop(result,NULL,ic,TRUE);
7896 /*-----------------------------------------------------------------*/
7897 /* genrshOne - right shift a one byte quantity by known count */
7898 /*-----------------------------------------------------------------*/
7899 static void genrshOne (operand *result, operand *left,
7900 int shCount, int sign)
7903 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7904 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7907 /*-----------------------------------------------------------------*/
7908 /* genrshTwo - right shift two bytes by known amount != 0 */
7909 /*-----------------------------------------------------------------*/
7910 static void genrshTwo (operand *result,operand *left,
7911 int shCount, int sign)
7914 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7915 /* if shCount >= 8 */
7919 shiftR1Left2Result(left, MSB16, result, LSB,
7922 movLeft2Result(left, MSB16, result, LSB);
7924 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7927 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7928 emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7932 /* 1 <= shCount <= 7 */
7934 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
7937 /*-----------------------------------------------------------------*/
7938 /* shiftRLong - shift right one long from left to result */
7939 /* offl = LSB or MSB16 */
7940 /*-----------------------------------------------------------------*/
7941 static void shiftRLong (operand *left, int offl,
7942 operand *result, int sign)
7947 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7949 size = AOP_SIZE(left);
7950 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7953 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7957 assert (offl >= 0 && offl < size);
7959 same = pic14_sameRegs (AOP(left), AOP(result));
7961 /* perform the shift */
7964 if (same && !offl) {
7965 emitpcode (POC_RRF, popGet (AOP(result), size));
7967 emitpcode (POC_RRFW, popGet (AOP(left), size));
7968 emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7972 addSign (result, AOP_SIZE(left) - offl, sign);
7975 /*-----------------------------------------------------------------*/
7976 /* genrshFour - shift four byte by a known amount != 0 */
7977 /*-----------------------------------------------------------------*/
7978 static void genrshFour (operand *result, operand *left,
7979 int shCount, int sign)
7982 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7983 /* if shifting more that 3 bytes */
7984 if(shCount >= 24 ) {
7987 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7989 movLeft2Result(left, MSB32, result, LSB);
7991 addSign(result, MSB16, sign);
7993 else if(shCount >= 16){
7996 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7998 movLeft2Result(left, MSB24, result, LSB);
7999 movLeft2Result(left, MSB32, result, MSB16);
8001 addSign(result, MSB24, sign);
8003 else if(shCount >= 8){
8006 shiftRLong(left, MSB16, result, sign);
8007 else if(shCount == 0){
8008 movLeft2Result(left, MSB16, result, LSB);
8009 movLeft2Result(left, MSB24, result, MSB16);
8010 movLeft2Result(left, MSB32, result, MSB24);
8011 addSign(result, MSB32, sign);
8014 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8015 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8016 /* the last shift is signed */
8017 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8018 addSign(result, MSB32, sign);
8021 else{ /* 1 <= shCount <= 7 */
8023 shiftRLong(left, LSB, result, sign);
8025 shiftRLong(result, LSB, result, sign);
8028 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8029 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8030 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8035 /*-----------------------------------------------------------------*/
8036 /* genRightShiftLiteral - right shifting by known count */
8037 /*-----------------------------------------------------------------*/
8038 static void genRightShiftLiteral (operand *left,
8044 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8048 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8049 freeAsmop(right,NULL,ic,TRUE);
8051 aopOp(left,ic,FALSE);
8052 aopOp(result,ic,FALSE);
8055 pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8059 lsize = pic14_getDataSize(left);
8060 res_size = pic14_getDataSize(result);
8061 /* test the LEFT size !!! */
8063 /* I suppose that the left size >= result size */
8066 movLeft2Result(left, res_size, result, res_size);
8069 else if(shCount >= (lsize * 8)){
8072 emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8074 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8075 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8080 emitpcode(POC_MOVLW, popGetLit(0));
8081 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8082 emitpcode(POC_MOVLW, popGetLit(0xff));
8084 emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8089 emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8096 genrshOne (result,left,shCount,sign);
8100 genrshTwo (result,left,shCount,sign);
8104 genrshFour (result,left,shCount,sign);
8112 freeAsmop(left,NULL,ic,TRUE);
8113 freeAsmop(result,NULL,ic,TRUE);
8118 /*-----------------------------------------------------------------*/
8119 /* genSignedRightShift - right shift of signed number */
8120 /*-----------------------------------------------------------------*/
8121 static void genSignedRightShift (iCode *ic)
8123 operand *right, *left, *result;
8126 symbol *tlbl, *tlbl1 ;
8129 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8131 /* we do it the hard way put the shift count in b
8132 and loop thru preserving the sign */
8134 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8136 right = IC_RIGHT(ic);
8138 result = IC_RESULT(ic);
8140 aopOp(right,ic,FALSE);
8141 aopOp(left,ic,FALSE);
8142 aopOp(result,ic,FALSE);
8145 if ( AOP_TYPE(right) == AOP_LIT) {
8146 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8147 //genRightShiftLiteral (left,right,result,ic,1);
8150 /* shift count is unknown then we have to form
8151 a loop get the loop count in B : Note: we take
8152 only the lower order byte since shifting
8153 more that 32 bits make no sense anyway, ( the
8154 largest size of an object can be only 32 bits ) */
8156 //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8157 //pic14_emitcode("inc","b");
8158 //freeAsmop (right,NULL,ic,TRUE);
8159 //aopOp(left,ic,FALSE);
8160 //aopOp(result,ic,FALSE);
8162 /* now move the left to the result if they are not the
8164 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
8165 AOP_SIZE(result) > 1) {
8167 size = AOP_SIZE(result);
8171 l = aopGet(AOP(left),offset,FALSE,TRUE);
8172 if (*l == '@' && IS_AOP_PREG(result)) {
8173 pic14_emitcode("mov","a,%s",l);
8174 aopPut(AOP(result),"a",offset);
8176 aopPut(AOP(result),l,offset);
8178 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8179 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8185 /* mov the highest order bit to OVR */
8186 tlbl = newiTempLabel(NULL);
8187 tlbl1= newiTempLabel(NULL);
8189 size = AOP_SIZE(result);
8192 pctemp = popGetTempReg(); /* grab a temporary working register. */
8194 emitpcode(POC_MOVFW, popGet(AOP(right),0));
8196 /* offset should be 0, 1 or 3 */
8197 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8199 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8201 emitpcode(POC_MOVWF, pctemp);
8204 emitpLabel(tlbl->key);
8206 emitpcode(POC_RLFW, popGet(AOP(result),offset));
8207 emitpcode(POC_RRF, popGet(AOP(result),offset));
8210 emitpcode(POC_RRF, popGet(AOP(result),--offset));
8213 emitpcode(POC_DECFSZ, pctemp);
8214 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8215 emitpLabel(tlbl1->key);
8217 popReleaseTempReg(pctemp);
8219 size = AOP_SIZE(result);
8221 pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8222 pic14_emitcode("rlc","a");
8223 pic14_emitcode("mov","ov,c");
8224 /* if it is only one byte then */
8226 l = aopGet(AOP(left),0,FALSE,FALSE);
8228 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8229 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8230 pic14_emitcode("mov","c,ov");
8231 pic14_emitcode("rrc","a");
8232 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8233 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8234 aopPut(AOP(result),"a",0);
8238 reAdjustPreg(AOP(result));
8239 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8240 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8241 pic14_emitcode("mov","c,ov");
8243 l = aopGet(AOP(result),offset,FALSE,FALSE);
8245 pic14_emitcode("rrc","a");
8246 aopPut(AOP(result),"a",offset--);
8248 reAdjustPreg(AOP(result));
8249 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8250 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8255 freeAsmop(left,NULL,ic,TRUE);
8256 freeAsmop(result,NULL,ic,TRUE);
8257 freeAsmop(right,NULL,ic,TRUE);
8261 /*-----------------------------------------------------------------*/
8262 /* loadSignToC - load the operand's sign bit into CARRY */
8263 /*-----------------------------------------------------------------*/
8265 static void loadSignToC (operand *op)
8268 assert (op && AOP(op) && AOP_SIZE(op));
8271 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8275 /*-----------------------------------------------------------------*/
8276 /* genRightShift - generate code for right shifting */
8277 /*-----------------------------------------------------------------*/
8278 static void genGenericShift (iCode *ic, int shiftRight)
8280 operand *right, *left, *result;
8283 symbol *tlbl, *tlbl1, *inverselbl;
8286 /* if signed then we do it the hard way preserve the
8287 sign bit moving it inwards */
8288 retype = getSpec(operandType(IC_RESULT(ic)));
8289 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8291 /* signed & unsigned types are treated the same : i.e. the
8292 signed is NOT propagated inwards : quoting from the
8293 ANSI - standard : "for E1 >> E2, is equivalent to division
8294 by 2**E2 if unsigned or if it has a non-negative value,
8295 otherwise the result is implementation defined ", MY definition
8296 is that the sign does not get propagated */
8298 right = IC_RIGHT(ic);
8300 result = IC_RESULT(ic);
8302 aopOp(right,ic,FALSE);
8303 aopOp(left,ic,FALSE);
8304 aopOp(result,ic,FALSE);
8306 /* if the shift count is known then do it
8307 as efficiently as possible */
8308 if (AOP_TYPE(right) == AOP_LIT) {
8309 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8313 shiftRight = !shiftRight;
8317 shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8319 shiftLeft_Left2ResultLit (left, result, lit);
8320 //genRightShiftLiteral (left,right,result,ic, 0);
8324 /* shift count is unknown then we have to form
8325 a loop get the loop count in B : Note: we take
8326 only the lower order byte since shifting
8327 more that 32 bits make no sense anyway, ( the
8328 largest size of an object can be only 32 bits ) */
8330 /* we must not overwrite the shift counter */
8331 assert (!pic14_sameRegs(AOP(right),AOP(result)));
8333 /* now move the left to the result if they are not the
8335 if (!pic14_sameRegs(AOP(left),AOP(result)))
8337 size = min(AOP_SIZE(result), AOP_SIZE(left));
8339 mov2w(AOP(left), size);
8340 movwf(AOP(result), size);
8342 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8345 tlbl = newiTempLabel(NULL);
8346 tlbl1= newiTempLabel(NULL);
8348 size = AOP_SIZE(result);
8350 mov2w(AOP(right),0);
8351 if (!SPEC_USIGN(operandType(right)))
8353 inverselbl = newiTempLabel(NULL);
8354 /* signed shift count -- invert shift direction for c<0 */
8355 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8356 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8358 emitpcode(POC_SUBLW, popGetLit(0)); /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8359 /* check for `a = b >> c' with `-c == 0' */
8361 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8362 emitpLabel(tlbl->key);
8363 /* propagate the sign bit inwards for SIGNED result */
8364 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8365 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8366 emitpcode(POC_ADDLW, popGetLit(1)); /* clears CARRY (unless W==0 afterwards) */
8368 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8370 if (!SPEC_USIGN(operandType(right)))
8372 symbol *inv_loop = newiTempLabel(NULL);
8374 shiftRight = !shiftRight; /* invert shift direction */
8376 /* we came here from the code above -- we are done */
8377 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8379 /* emit code for shifting N<0 steps, count is already in W */
8380 emitpLabel(inverselbl->key);
8381 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8382 emitpLabel(inv_loop->key);
8383 /* propagate the sign bit inwards for SIGNED result */
8384 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8385 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8386 emitpcode(POC_ADDLW, popGetLit(1));
8388 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8391 emitpLabel(tlbl1->key);
8393 freeAsmop(left,NULL,ic,TRUE);
8394 freeAsmop (right,NULL,ic,TRUE);
8395 freeAsmop(result,NULL,ic,TRUE);
8398 static void genRightShift (iCode *ic)
8400 genGenericShift(ic, 1);
8403 static void genLeftShift (iCode *ic)
8405 genGenericShift(ic, 0);
8408 /*-----------------------------------------------------------------*/
8409 /* SetIrp - Set IRP bit */
8410 /*-----------------------------------------------------------------*/
8411 void SetIrp(operand *result) {
8413 if (AOP_TYPE(result) == AOP_LIT) {
8414 unsigned lit = (unsigned)operandLitValue(result);
8420 if (PCOP(AOP(result))->type == PO_LITERAL) {
8421 int addrs = PCOL(AOP(result))->lit;
8427 emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8428 if(AOP_SIZE(result) > 1) {
8429 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8437 setup_fsr (operand *ptr)
8440 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8442 /* also setup-up IRP */
8446 /*-----------------------------------------------------------------*/
8447 /* emitPtrByteGet - emits code to get a byte into WREG from an */
8448 /* arbitrary pointer (__code, __data, generic) */
8449 /*-----------------------------------------------------------------*/
8451 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8458 if (!alreadyAddressed) setup_fsr (src);
8459 emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8463 assert( AOP_SIZE(src) == 2 );
8465 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8467 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8468 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
8469 call_libraryfunc ("__gptrget1");
8473 assert( AOP_SIZE(src) == 3 );
8475 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8477 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8479 call_libraryfunc ("__gptrget1");
8483 assert( !"unhandled pointer type" );
8488 /*-----------------------------------------------------------------*/
8489 /* emitPtrByteSet - emits code to set a byte from src through a */
8490 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR). */
8491 /*-----------------------------------------------------------------*/
8493 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8500 if (!alreadyAddressed) setup_fsr (dst);
8501 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8505 assert( !"trying to assign to __code pointer" );
8509 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8511 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8513 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8515 call_libraryfunc ("__gptrput1");
8519 assert( !"unhandled pointer type" );
8524 /*-----------------------------------------------------------------*/
8525 /* genUnpackBits - generates code for unpacking bits */
8526 /*-----------------------------------------------------------------*/
8527 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8529 int rsize; /* result size */
8530 sym_link *etype; /* bitfield type information */
8531 int blen; /* bitfield length */
8532 int bstr; /* bitfield starting bit within byte */
8535 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8536 etype = getSpec(operandType(result));
8537 rsize = getSize (operandType (result));
8538 blen = SPEC_BLEN (etype);
8539 bstr = SPEC_BSTR (etype);
8541 /* single bit field case */
8543 if (ifx) { /* that is for an if statement */
8546 resolveIfx(&rIfx,ifx);
8547 if (ptype == -1) /* direct */
8548 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8550 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8551 emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8552 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8556 assert (!pic14_sameRegs (AOP(result), AOP(left)));
8557 for (i=0; i < AOP_SIZE(result); i++)
8558 emitpcode (POC_CLRF, popGet (AOP(result), i));
8563 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8564 /* adjust result below */
8571 emitPtrByteGet (left, ptype, FALSE);
8572 emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8574 /* adjust result below */
8578 assert( !"unhandled pointer type" );
8581 /* move sign-/zero extended bit to result */
8582 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8583 emitpcode (POC_INCF, popGet (AOP(result), 0));
8585 emitpcode (POC_DECF, popGet (AOP(result), 0));
8587 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8591 else if (blen <= 8 && ((blen + bstr) <= 8))
8596 for (i=0; i < AOP_SIZE(result); i++)
8597 emitpcode (POC_CLRF, popGet (AOP(result), i));
8602 mov2w(AOP(left), 0);
8609 emitPtrByteGet (left, ptype, FALSE);
8613 assert( !"unhandled pointer type" );
8617 emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8618 movwf(AOP(result), 0);
8619 AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8621 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8623 /* signed bitfield */
8624 assert (bstr + blen > 0);
8625 emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8626 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8627 emitpcode(POC_IORWF, popGet(AOP(result),0));
8629 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8633 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8637 /*-----------------------------------------------------------------*/
8638 /* genDataPointerGet - generates code when ptr offset is known */
8639 /*-----------------------------------------------------------------*/
8640 static void genDataPointerGet (operand *left,
8644 int size , offset = 0;
8647 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8650 /* optimization - most of the time, left and result are the same
8651 * address, but different types. for the pic code, we could omit
8654 aopOp(result,ic,TRUE);
8656 if (pic14_sameRegs (AOP(left), AOP(result)))
8659 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8661 //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8663 size = AOP_SIZE(result);
8664 if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8668 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8669 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8673 freeAsmop(left,NULL,ic,TRUE);
8674 freeAsmop(result,NULL,ic,TRUE);
8678 /*-----------------------------------------------------------------*/
8679 /* genNearPointerGet - pic14_emitcode for near pointer fetch */
8680 /*-----------------------------------------------------------------*/
8681 static void genNearPointerGet (operand *left,
8686 sym_link *ltype = operandType(left);
8687 sym_link *rtype = operandType(result);
8688 sym_link *retype= getSpec(rtype); /* bitfield type information */
8692 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8695 aopOp(left,ic,FALSE);
8697 /* if left is rematerialisable and
8698 result is not bit variable type and
8699 the left is pointer to data space i.e
8700 lower 128 bytes of space */
8701 if (AOP_TYPE(left) == AOP_PCODE && //AOP_TYPE(left) == AOP_IMMD &&
8702 !IS_BITVAR(retype) &&
8703 PIC_IS_DATA_PTR(ltype)) {
8704 genDataPointerGet (left,result,ic);
8708 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8709 aopOp (result,ic,FALSE);
8711 /* Check if can access directly instead of via a pointer */
8712 if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8713 && AOP_SIZE(result) == 1)
8718 if (IS_BITFIELD(getSpec(operandType(result))))
8720 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8724 /* If the pointer value is not in a the FSR then need to put it in */
8725 /* Must set/reset IRP bit for use with FSR. */
8730 /* if bitfield then unpack the bits */
8732 /* we have can just get the values */
8733 int size = AOP_SIZE(result);
8736 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8740 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8742 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8743 if (AOP_TYPE(result) == AOP_LIT) {
8744 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8746 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8748 if (size && !direct)
8749 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8754 /* now some housekeeping stuff */
8756 /* we had to allocate for this iCode */
8757 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8758 freeAsmop(NULL,aop,ic,TRUE);
8760 /* we did not allocate which means left
8761 already in a pointer register, then
8762 if size > 0 && this could be used again
8763 we have to point it back to where it
8765 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8766 if (AOP_SIZE(result) > 1 &&
8767 !OP_SYMBOL(left)->remat &&
8768 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8770 int size = AOP_SIZE(result) - 1;
8772 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8778 freeAsmop(left,NULL,ic,TRUE);
8779 freeAsmop(result,NULL,ic,TRUE);
8784 /*-----------------------------------------------------------------*/
8785 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch */
8786 /*-----------------------------------------------------------------*/
8787 static void genPagedPointerGet (operand *left,
8794 sym_link *rtype, *retype;
8797 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8799 rtype = operandType(result);
8800 retype= getSpec(rtype);
8802 aopOp(left,ic,FALSE);
8804 /* if the value is already in a pointer register
8805 then don't need anything more */
8806 if (!AOP_INPREG(AOP(left))) {
8807 /* otherwise get a free pointer register */
8809 preg = getFreePtr(ic,&aop,FALSE);
8810 pic14_emitcode("mov","%s,%s",
8812 aopGet(AOP(left),0,FALSE,TRUE));
8813 rname = preg->name ;
8815 rname = aopGet(AOP(left),0,FALSE,FALSE);
8817 freeAsmop(left,NULL,ic,TRUE);
8818 aopOp (result,ic,FALSE);
8820 /* if bitfield then unpack the bits */
8821 if (IS_BITFIELD(retype))
8822 genUnpackBits (result,left,rname,PPOINTER,0);
8824 /* we have can just get the values */
8825 int size = AOP_SIZE(result);
8830 pic14_emitcode("movx","a,@%s",rname);
8831 aopPut(AOP(result),"a",offset);
8836 pic14_emitcode("inc","%s",rname);
8840 /* now some housekeeping stuff */
8842 /* we had to allocate for this iCode */
8843 freeAsmop(NULL,aop,ic,TRUE);
8845 /* we did not allocate which means left
8846 already in a pointer register, then
8847 if size > 0 && this could be used again
8848 we have to point it back to where it
8850 if (AOP_SIZE(result) > 1 &&
8851 !OP_SYMBOL(left)->remat &&
8852 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8854 int size = AOP_SIZE(result) - 1;
8856 pic14_emitcode("dec","%s",rname);
8861 freeAsmop(result,NULL,ic,TRUE);
8866 /*-----------------------------------------------------------------*/
8867 /* genFarPointerGet - gget value from far space */
8868 /*-----------------------------------------------------------------*/
8869 static void genFarPointerGet (operand *left,
8870 operand *result, iCode *ic)
8873 sym_link *retype = getSpec(operandType(result));
8876 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8878 aopOp(left,ic,FALSE);
8880 /* if the operand is already in dptr
8881 then we do nothing else we move the value to dptr */
8882 if (AOP_TYPE(left) != AOP_STR) {
8883 /* if this is remateriazable */
8884 if (AOP_TYPE(left) == AOP_IMMD)
8885 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8886 else { /* we need to get it byte by byte */
8887 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8888 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8889 if (options.model == MODEL_FLAT24)
8891 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8895 /* so dptr know contains the address */
8896 freeAsmop(left,NULL,ic,TRUE);
8897 aopOp(result,ic,FALSE);
8899 /* if bit then unpack */
8900 if (IS_BITFIELD(retype))
8901 genUnpackBits(result,left,"dptr",FPOINTER,0);
8903 size = AOP_SIZE(result);
8907 pic14_emitcode("movx","a,@dptr");
8908 aopPut(AOP(result),"a",offset++);
8910 pic14_emitcode("inc","dptr");
8914 freeAsmop(result,NULL,ic,TRUE);
8919 /*-----------------------------------------------------------------*/
8920 /* genCodePointerGet - get value from code space */
8921 /*-----------------------------------------------------------------*/
8922 static void genCodePointerGet (operand *left,
8923 operand *result, iCode *ic)
8926 sym_link *retype = getSpec(operandType(result));
8928 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8930 aopOp(left,ic,FALSE);
8932 /* if the operand is already in dptr
8933 then we do nothing else we move the value to dptr */
8934 if (AOP_TYPE(left) != AOP_STR) {
8935 /* if this is remateriazable */
8936 if (AOP_TYPE(left) == AOP_IMMD)
8937 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8938 else { /* we need to get it byte by byte */
8939 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8940 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8941 if (options.model == MODEL_FLAT24)
8943 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8947 /* so dptr know contains the address */
8948 freeAsmop(left,NULL,ic,TRUE);
8949 aopOp(result,ic,FALSE);
8951 /* if bit then unpack */
8952 if (IS_BITFIELD(retype))
8953 genUnpackBits(result,left,"dptr",CPOINTER,0);
8955 size = AOP_SIZE(result);
8959 pic14_emitcode("clr","a");
8960 pic14_emitcode("movc","a,@a+dptr");
8961 aopPut(AOP(result),"a",offset++);
8963 pic14_emitcode("inc","dptr");
8967 freeAsmop(result,NULL,ic,TRUE);
8970 /*-----------------------------------------------------------------*/
8971 /* genGenPointerGet - gget value from generic pointer space */
8972 /*-----------------------------------------------------------------*/
8973 static void genGenPointerGet (operand *left,
8974 operand *result, iCode *ic)
8977 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8978 aopOp(left,ic,FALSE);
8979 aopOp(result,ic,FALSE);
8982 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8984 if (IS_BITFIELD(getSpec(operandType(result))))
8986 genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
8991 /* emit call to __gptrget */
8992 char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
8993 int size = AOP_SIZE(result);
8996 assert (size > 0 && size <= 4);
8998 /* pass arguments */
8999 assert (AOP_SIZE(left) == 3);
9000 mov2w(AOP(left), 0);
9001 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9002 mov2w(AOP(left), 1);
9003 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9004 mov2w(AOP(left), 2);
9005 call_libraryfunc (func[size]);
9008 movwf (AOP(result), --size);
9010 emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
9011 movwf (AOP(result), size);
9015 freeAsmop(left,NULL,ic,TRUE);
9016 freeAsmop(result,NULL,ic,TRUE);
9020 /*-----------------------------------------------------------------*/
9021 /* genConstPointerGet - get value from const generic pointer space */
9022 /*-----------------------------------------------------------------*/
9023 static void genConstPointerGet (operand *left,
9024 operand *result, iCode *ic)
9026 //sym_link *retype = getSpec(operandType(result));
9028 symbol *albl, *blbl;//, *clbl;
9035 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9036 aopOp(left,ic,FALSE);
9037 aopOp(result,ic,FALSE);
9039 size = AOP_SIZE(result);
9041 DEBUGpic14_AopType(__LINE__,left,NULL,result);
9043 DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
9045 lit = op_isLitLike (left);
9046 poc = lit ? POC_MOVLW : POC_MOVFW;
9048 if (IS_BITFIELD(getSpec(operandType(result))))
9050 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
9055 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
9056 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
9057 assert (size > 0 && size <= 4);
9060 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9062 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9063 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
9064 call_libraryfunc (func[size]);
9066 movwf(AOP(result),size-1);
9067 for (i = 1; i < size; i++)
9069 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
9070 movwf(AOP(result),size - 1 - i);
9075 freeAsmop(left,NULL,ic,TRUE);
9076 freeAsmop(result,NULL,ic,TRUE);
9079 /*-----------------------------------------------------------------*/
9080 /* genPointerGet - generate code for pointer get */
9081 /*-----------------------------------------------------------------*/
9082 static void genPointerGet (iCode *ic)
9084 operand *left, *result ;
9085 sym_link *type, *etype;
9089 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9092 result = IC_RESULT(ic) ;
9094 /* depending on the type of pointer we need to
9095 move it to the correct pointer register */
9096 type = operandType(left);
9097 etype = getSpec(type);
9099 if (IS_PTR_CONST(type))
9100 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9102 /* if left is of type of pointer then it is simple */
9103 if (IS_PTR(type) && !IS_FUNC(type->next))
9104 p_type = DCL_TYPE(type);
9106 /* we have to go by the storage class */
9107 p_type = PTR_TYPE(SPEC_OCLS(etype));
9109 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9111 if (SPEC_OCLS(etype)->codesp ) {
9112 DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9113 //p_type = CPOINTER ;
9116 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9117 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9118 /*p_type = FPOINTER ;*/
9120 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9121 DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9122 /* p_type = PPOINTER; */
9124 if (SPEC_OCLS(etype) == idata )
9125 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9126 /* p_type = IPOINTER; */
9128 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9129 /* p_type = POINTER ; */
9132 /* now that we have the pointer type we assign
9133 the pointer values */
9139 genNearPointerGet (left,result,ic);
9143 genPagedPointerGet(left,result,ic);
9147 genFarPointerGet (left,result,ic);
9151 genConstPointerGet (left,result,ic);
9155 genGenPointerGet (left,result,ic);
9158 assert ( !"unhandled pointer type" );
9164 /*-----------------------------------------------------------------*/
9165 /* genPackBits - generates code for packed bit storage */
9166 /*-----------------------------------------------------------------*/
9167 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9169 int blen; /* bitfield length */
9170 int bstr; /* bitfield starting bit within byte */
9171 int litval; /* source literal value (if AOP_LIT) */
9172 unsigned char mask; /* bitmask within current byte */
9175 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9177 blen = SPEC_BLEN (etype);
9178 bstr = SPEC_BSTR (etype);
9180 /* If the bitfield length is less than a byte and does not cross byte boundaries */
9181 if ((blen <= 8) && ((bstr + blen) <= 8))
9183 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9184 (unsigned char) (0xFF >> (8 - bstr)));
9186 if (AOP_TYPE (right) == AOP_LIT)
9188 /* Case with a bitfield length <8 and literal source */
9189 int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9196 if (AOP(result)->type == AOP_PCODE)
9197 pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9199 pcop = popGet(AOP(result),0);
9200 emitpcode(lit?POC_BSF:POC_BCF,pcop);
9206 emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9210 assert( !"trying to assign to bitfield via pointer to __code space" );
9214 emitPtrByteGet(result, p_type, FALSE);
9216 emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9218 emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9220 emitPtrByteSet(result, p_type, TRUE);
9224 assert( !"unhandled pointer type" );
9226 } // switch (p_type)
9229 litval = lit << bstr;
9230 litval &= (~mask) & 0x00ff;
9235 mov2w (AOP(result), 0);
9236 if ((litval|mask) != 0x00ff)
9237 emitpcode(POC_ANDLW, popGetLit (mask));
9239 emitpcode(POC_IORLW, popGetLit (litval));
9240 movwf (AOP(result), 0);
9246 emitPtrByteGet(result, p_type, FALSE);
9247 if ((litval|mask) != 0x00ff)
9248 emitpcode(POC_ANDLW, popGetLit (mask));
9250 emitpcode(POC_IORLW, popGetLit (litval));
9251 emitPtrByteSet(result, p_type, TRUE);
9255 assert( !"trying to assign to bitfield via pointer to __code space" );
9259 assert( !"unhandled pointer type" );
9266 /* right is no literal */
9271 /* Note more efficient code, of pre clearing bit then only setting it if required,
9272 * can only be done if it is known that the result is not a SFR */
9273 emitpcode(POC_RRFW,popGet(AOP(right),0));
9275 emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9277 emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9283 emitPtrByteGet (result, p_type, FALSE);
9284 emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9285 emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9286 emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9287 emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9288 emitPtrByteSet (result, p_type, TRUE);
9292 assert( !"trying to assign to bitfield via pointer to __code space" );
9296 assert( !"unhandled pointer type" );
9301 /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9302 pCodeOp *temp = popGetTempReg ();
9304 mov2w (AOP(right), 0);
9306 emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9308 emitpcode(POC_MOVWF, temp);
9310 AccLsh (temp, bstr);
9316 mov2w (AOP(result), 0);
9317 emitpcode(POC_ANDLW, popGetLit (mask));
9318 emitpcode(POC_IORFW, temp);
9319 movwf (AOP(result), 0);
9325 emitPtrByteGet (result, p_type, FALSE);
9326 emitpcode(POC_ANDLW, popGetLit (mask));
9327 emitpcode(POC_IORFW, temp);
9328 emitPtrByteSet (result, p_type, TRUE);
9332 assert( !"trying to assign to bitfield via pointer to __code space" );
9336 assert( !"unhandled pointer type" );
9340 popReleaseTempReg (temp);
9342 } // if (AOP(right)->type != AOP_LIT)
9344 } // if (blen <= 8 && ((blen + bstr) <= 8))
9346 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9350 bitpatternFromVal (value *val)
9357 assert (sizeof (float) == sizeof (long));
9359 //fprintf (stderr, "%s:%u(%s): val=%lf, type: %d, etype: %d\n", __FILE__, __LINE__, __FUNCTION__, floatFromVal(val), SPEC_NOUN(val->type), SPEC_NOUN(val->etype));
9361 switch (SPEC_NOUN(val->type))
9365 return (unsigned long)floatFromVal (val);
9369 float_long.d = floatFromVal (val);
9370 return float_long.l;
9373 assert( !"unhandled value type" );
9377 float_long.d = floatFromVal (val);
9378 return float_long.l;
9381 /*-----------------------------------------------------------------*/
9382 /* genDataPointerSet - remat pointer to data space */
9383 /*-----------------------------------------------------------------*/
9384 static void genDataPointerSet(operand *right,
9388 int size, offset = 0 ;
9392 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9393 aopOp(right,ic,FALSE);
9394 aopOp(result,ic,FALSE);
9396 assert (IS_SYMOP(result));
9397 assert (IS_PTR(OP_SYM_TYPE(result)));
9399 size = AOP_SIZE(right);
9400 ressize = getSize(OP_SYM_ETYPE(result));
9401 if (size > ressize) size = ressize;
9402 //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9404 //assert( !"what's going on here?" );
9407 if ( AOP_TYPE(result) == AOP_PCODE) {
9408 fprintf(stderr,"genDataPointerSet %s, %d\n",
9409 AOP(result)->aopu.pcop->name,
9410 PCOI(AOP(result)->aopu.pcop)->offset);
9414 // tsd, was l+1 - the underline `_' prefix was being stripped
9416 emitpComment ("%s:%u: size=%d/%d, offset=%i", __FILE__,__LINE__, size, ressize, offset);
9418 if (AOP_TYPE(right) == AOP_LIT) {
9419 /* XXX: might be float... */
9420 unsigned int lit = bitpatternFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9421 lit = lit >> (8*offset);
9422 //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9424 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9425 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9427 emitpcode(POC_CLRF, popGet(AOP(result),offset));
9430 //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9431 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9432 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9438 freeAsmop(right,NULL,ic,TRUE);
9439 freeAsmop(result,NULL,ic,TRUE);
9442 /*-----------------------------------------------------------------*/
9443 /* genNearPointerSet - pic14_emitcode for near pointer put */
9444 /*-----------------------------------------------------------------*/
9445 static void genNearPointerSet (operand *right,
9450 sym_link *ptype = operandType(result);
9451 sym_link *retype = getSpec(operandType(right));
9452 sym_link *letype = getSpec(ptype);
9457 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9458 aopOp(result,ic,FALSE);
9461 /* if the result is rematerializable &
9462 in data space & not a bit variable */
9463 //if (AOP_TYPE(result) == AOP_IMMD &&
9464 if (AOP_TYPE(result) == AOP_PCODE &&
9465 PIC_IS_DATA_PTR(ptype) &&
9466 !IS_BITVAR (retype) &&
9467 !IS_BITVAR (letype)) {
9468 genDataPointerSet (right,result,ic);
9469 freeAsmop(result,NULL,ic,TRUE);
9474 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9475 aopOp(right,ic,FALSE);
9476 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9478 /* Check if can access directly instead of via a pointer */
9479 if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9483 if (IS_BITFIELD (letype))
9485 genPackBits (letype, result, right, direct?-1:POINTER);
9489 /* If the pointer value is not in a the FSR then need to put it in */
9490 /* Must set/reset IRP bit for use with FSR. */
9491 /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9496 /* we have can just get the values */
9497 int size = AOP_SIZE(right);
9500 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9502 char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9504 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9506 if (AOP_TYPE(right) == AOP_LIT) {
9507 emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9509 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9512 emitpcode(POC_MOVWF,popGet(AOP(result),0));
9514 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9516 if (size && !direct)
9517 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9522 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9523 /* now some housekeeping stuff */
9525 /* we had to allocate for this iCode */
9526 freeAsmop(NULL,aop,ic,TRUE);
9528 /* we did not allocate which means left
9529 already in a pointer register, then
9530 if size > 0 && this could be used again
9531 we have to point it back to where it
9533 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9534 if (AOP_SIZE(right) > 1 &&
9535 !OP_SYMBOL(result)->remat &&
9536 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9538 int size = AOP_SIZE(right) - 1;
9540 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9544 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9547 freeAsmop(right,NULL,ic,TRUE);
9548 freeAsmop(result,NULL,ic,TRUE);
9552 /*-----------------------------------------------------------------*/
9553 /* genPagedPointerSet - pic14_emitcode for Paged pointer put */
9554 /*-----------------------------------------------------------------*/
9555 static void genPagedPointerSet (operand *right,
9565 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9567 retype= getSpec(operandType(right));
9569 aopOp(result,ic,FALSE);
9571 /* if the value is already in a pointer register
9572 then don't need anything more */
9573 if (!AOP_INPREG(AOP(result))) {
9574 /* otherwise get a free pointer register */
9576 preg = getFreePtr(ic,&aop,FALSE);
9577 pic14_emitcode("mov","%s,%s",
9579 aopGet(AOP(result),0,FALSE,TRUE));
9580 rname = preg->name ;
9582 rname = aopGet(AOP(result),0,FALSE,FALSE);
9584 freeAsmop(result,NULL,ic,TRUE);
9585 aopOp (right,ic,FALSE);
9587 /* if bitfield then unpack the bits */
9588 if (IS_BITFIELD(retype))
9589 genPackBits (retype,result,right,rname,PPOINTER);
9591 /* we have can just get the values */
9592 int size = AOP_SIZE(right);
9596 l = aopGet(AOP(right),offset,FALSE,TRUE);
9599 pic14_emitcode("movx","@%s,a",rname);
9602 pic14_emitcode("inc","%s",rname);
9608 /* now some housekeeping stuff */
9610 /* we had to allocate for this iCode */
9611 freeAsmop(NULL,aop,ic,TRUE);
9613 /* we did not allocate which means left
9614 already in a pointer register, then
9615 if size > 0 && this could be used again
9616 we have to point it back to where it
9618 if (AOP_SIZE(right) > 1 &&
9619 !OP_SYMBOL(result)->remat &&
9620 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9622 int size = AOP_SIZE(right) - 1;
9624 pic14_emitcode("dec","%s",rname);
9629 freeAsmop(right,NULL,ic,TRUE);
9634 /*-----------------------------------------------------------------*/
9635 /* genFarPointerSet - set value from far space */
9636 /*-----------------------------------------------------------------*/
9637 static void genFarPointerSet (operand *right,
9638 operand *result, iCode *ic)
9641 sym_link *retype = getSpec(operandType(right));
9644 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9645 aopOp(result,ic,FALSE);
9647 /* if the operand is already in dptr
9648 then we do nothing else we move the value to dptr */
9649 if (AOP_TYPE(result) != AOP_STR) {
9650 /* if this is remateriazable */
9651 if (AOP_TYPE(result) == AOP_IMMD)
9652 pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9653 else { /* we need to get it byte by byte */
9654 pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9655 pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9656 if (options.model == MODEL_FLAT24)
9658 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9662 /* so dptr know contains the address */
9663 freeAsmop(result,NULL,ic,TRUE);
9664 aopOp(right,ic,FALSE);
9666 /* if bit then unpack */
9667 if (IS_BITFIELD(retype))
9668 genPackBits(retype,result,right,"dptr",FPOINTER);
9670 size = AOP_SIZE(right);
9674 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9676 pic14_emitcode("movx","@dptr,a");
9678 pic14_emitcode("inc","dptr");
9682 freeAsmop(right,NULL,ic,TRUE);
9686 /*-----------------------------------------------------------------*/
9687 /* genGenPointerSet - set value from generic pointer space */
9688 /*-----------------------------------------------------------------*/
9689 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9691 sym_link *retype = getSpec(operandType(result));
9694 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9695 aopOp(right,ic,FALSE);
9696 aopOp(result,ic,FALSE);
9699 DEBUGpic14_AopType(__LINE__,right,NULL,result);
9701 if (IS_BITFIELD(retype))
9703 genPackBits (retype, result, right, GPOINTER);
9708 /* emit call to __gptrput */
9709 char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9710 int size = AOP_SIZE(right);
9713 assert (size == getSize(OP_SYM_ETYPE(result)));
9714 assert (size > 0 && size <= 4);
9716 /* pass arguments */
9717 /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9723 mov2w_op (right, off);
9724 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9729 assert (AOP_SIZE(result) == 3);
9730 mov2w(AOP(result), 0);
9731 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9732 mov2w(AOP(result), 1);
9733 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9734 mov2w(AOP(result), 2);
9735 call_libraryfunc (func[size]);
9738 freeAsmop(right,NULL,ic,TRUE);
9739 freeAsmop(result,NULL,ic,TRUE);
9742 /*-----------------------------------------------------------------*/
9743 /* genPointerSet - stores the value into a pointer location */
9744 /*-----------------------------------------------------------------*/
9745 static void genPointerSet (iCode *ic)
9747 operand *right, *result ;
9748 sym_link *type, *etype;
9752 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9754 right = IC_RIGHT(ic);
9755 result = IC_RESULT(ic) ;
9757 /* depending on the type of pointer we need to
9758 move it to the correct pointer register */
9759 type = operandType(result);
9760 etype = getSpec(type);
9761 /* if left is of type of pointer then it is simple */
9762 if (IS_PTR(type) && !IS_FUNC(type->next)) {
9763 p_type = DCL_TYPE(type);
9766 /* we have to go by the storage class */
9767 p_type = PTR_TYPE(SPEC_OCLS(etype));
9769 /* if (SPEC_OCLS(etype)->codesp ) { */
9770 /* p_type = CPOINTER ; */
9773 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9774 /* p_type = FPOINTER ; */
9776 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9777 /* p_type = PPOINTER ; */
9779 /* if (SPEC_OCLS(etype) == idata ) */
9780 /* p_type = IPOINTER ; */
9782 /* p_type = POINTER ; */
9785 /* now that we have the pointer type we assign
9786 the pointer values */
9792 genNearPointerSet (right,result,ic);
9796 genPagedPointerSet (right,result,ic);
9800 genFarPointerSet (right,result,ic);
9804 genGenPointerSet (right,result,ic);
9808 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9809 "genPointerSet: illegal pointer type");
9813 /*-----------------------------------------------------------------*/
9814 /* genIfx - generate code for Ifx statement */
9815 /*-----------------------------------------------------------------*/
9816 static void genIfx (iCode *ic, iCode *popIc)
9818 operand *cond = IC_COND(ic);
9822 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9824 aopOp(cond,ic,FALSE);
9826 /* get the value into acc */
9827 if (AOP_TYPE(cond) != AOP_CRY)
9828 pic14_toBoolean(cond);
9832 /* if there was something to be popped then do it */
9838 /* This assumes that CARRY is set iff cond is true */
9841 assert (!IC_FALSE(ic));
9842 emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
9844 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9846 assert (IC_FALSE(ic));
9847 emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
9849 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9853 static int hasWarned = 0;
9856 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
9863 /* now Z is set iff !cond */
9866 assert (!IC_FALSE(ic));
9868 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9871 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9877 /* the result is now in the accumulator */
9878 freeAsmop(cond,NULL,ic,TRUE);
9881 /*-----------------------------------------------------------------*/
9882 /* genAddrOf - generates code for address of */
9883 /*-----------------------------------------------------------------*/
9884 static void genAddrOf (iCode *ic)
9886 operand *right, *result, *left;
9890 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9893 //aopOp(IC_RESULT(ic),ic,FALSE);
9895 aopOp((left=IC_LEFT(ic)),ic,FALSE);
9896 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9897 aopOp((result=IC_RESULT(ic)),ic,TRUE);
9899 DEBUGpic14_AopType(__LINE__,left,right,result);
9900 assert (IS_SYMOP (left));
9902 /* sanity check: generic pointers to code space are not yet supported,
9903 * pionters to codespace must not be assigned addresses of __data values. */
9905 fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9906 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)));
9907 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)));
9908 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)));
9909 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)));
9912 if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9913 fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9914 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9915 OP_SYMBOL(left)->name);
9916 } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9917 fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9918 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9919 OP_SYMBOL(left)->name);
9922 size = AOP_SIZE(IC_RESULT(ic));
9923 if (IS_GENPTR(OP_SYM_TYPE(result))) {
9925 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9930 /* fixing bug #863624, reported from (errolv) */
9931 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9932 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9935 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9936 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9941 if (IS_GENPTR(OP_SYM_TYPE(result)))
9943 /* provide correct tag */
9944 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9945 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9946 movwf (AOP(result), 2);
9949 freeAsmop(left,NULL,ic,FALSE);
9950 freeAsmop(result,NULL,ic,TRUE);
9955 /*-----------------------------------------------------------------*/
9956 /* genFarFarAssign - assignment when both are in far space */
9957 /*-----------------------------------------------------------------*/
9958 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9960 int size = AOP_SIZE(right);
9963 /* first push the right side on to the stack */
9965 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9967 pic14_emitcode ("push","acc");
9970 freeAsmop(right,NULL,ic,FALSE);
9971 /* now assign DPTR to result */
9972 aopOp(result,ic,FALSE);
9973 size = AOP_SIZE(result);
9975 pic14_emitcode ("pop","acc");
9976 aopPut(AOP(result),"a",--offset);
9978 freeAsmop(result,NULL,ic,FALSE);
9983 /*-----------------------------------------------------------------*/
9984 /* genAssign - generate code for assignment */
9985 /*-----------------------------------------------------------------*/
9986 static void genAssign (iCode *ic)
9988 operand *result, *right;
9989 int size, offset,know_W;
9990 unsigned long lit = 0L;
9992 result = IC_RESULT(ic);
9993 right = IC_RIGHT(ic) ;
9996 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9998 /* if they are the same */
9999 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10002 aopOp(right,ic,FALSE);
10003 aopOp(result,ic,TRUE);
10005 DEBUGpic14_AopType(__LINE__,NULL,right,result);
10007 /* if they are the same registers */
10008 if (pic14_sameRegs(AOP(right),AOP(result)))
10011 /* special case: assign from __code */
10012 if (!IS_ITEMP(right) /* --> iTemps never reside in __code */
10013 && IS_SYMOP (right) /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
10014 && !IS_FUNC(OP_SYM_TYPE(right)) /* --> we would want its address instead of the first instruction */
10015 && !IS_CODEPTR(OP_SYM_TYPE(right)) /* --> get symbols address instread */
10016 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
10018 emitpComment ("genAssign from CODESPACE");
10019 genConstPointerGet (right, result, ic);
10023 /* just for symmetry reasons... */
10024 if (!IS_ITEMP(result)
10025 && IS_SYMOP (result)
10026 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
10028 assert ( !"cannot write to CODESPACE" );
10031 /* if the result is a bit */
10032 if (AOP_TYPE(result) == AOP_CRY) {
10034 /* if the right size is a literal then
10035 we know what the value is */
10036 if (AOP_TYPE(right) == AOP_LIT) {
10038 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10039 popGet(AOP(result),0));
10041 if (((int) operandLitValue(right)))
10042 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10043 AOP(result)->aopu.aop_dir,
10044 AOP(result)->aopu.aop_dir);
10046 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10047 AOP(result)->aopu.aop_dir,
10048 AOP(result)->aopu.aop_dir);
10052 /* the right is also a bit variable */
10053 if (AOP_TYPE(right) == AOP_CRY) {
10054 emitpcode(POC_BCF, popGet(AOP(result),0));
10055 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10056 emitpcode(POC_BSF, popGet(AOP(result),0));
10058 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10059 AOP(result)->aopu.aop_dir,
10060 AOP(result)->aopu.aop_dir);
10061 pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
10062 AOP(right)->aopu.aop_dir,
10063 AOP(right)->aopu.aop_dir);
10064 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10065 AOP(result)->aopu.aop_dir,
10066 AOP(result)->aopu.aop_dir);
10070 /* we need to or */
10071 emitpcode(POC_BCF, popGet(AOP(result),0));
10072 pic14_toBoolean(right);
10074 emitpcode(POC_BSF, popGet(AOP(result),0));
10075 //aopPut(AOP(result),"a",0);
10079 /* bit variables done */
10081 size = AOP_SIZE(result);
10083 if(AOP_TYPE(right) == AOP_LIT)
10084 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10086 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
10087 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10088 if(aopIdx(AOP(result),0) == 4) {
10089 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10090 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10091 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10094 DEBUGpic14_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
10099 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10100 if(AOP_TYPE(right) == AOP_LIT) {
10102 if(know_W != (int)(lit&0xff))
10103 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10105 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10107 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10111 } else if (AOP_TYPE(right) == AOP_CRY) {
10112 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10114 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10115 emitpcode(POC_INCF, popGet(AOP(result),0));
10118 mov2w_op (right, offset);
10119 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10127 freeAsmop (right,NULL,ic,FALSE);
10128 freeAsmop (result,NULL,ic,TRUE);
10131 /*-----------------------------------------------------------------*/
10132 /* genJumpTab - genrates code for jump table */
10133 /*-----------------------------------------------------------------*/
10134 static void genJumpTab (iCode *ic)
10140 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10142 aopOp(IC_JTCOND(ic),ic,FALSE);
10143 /* get the condition into accumulator */
10144 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10146 /* multiply by three */
10147 pic14_emitcode("add","a,acc");
10148 pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10150 jtab = newiTempLabel(NULL);
10151 pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10152 pic14_emitcode("jmp","@a+dptr");
10153 pic14_emitcode("","%05d_DS_:",jtab->key+100);
10155 emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10156 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10157 emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10158 emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10160 emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10161 emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10162 emitpLabel(jtab->key);
10164 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10166 /* now generate the jump labels */
10167 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10168 jtab = setNextItem(IC_JTLABELS(ic))) {
10169 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10170 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10176 /*-----------------------------------------------------------------*/
10177 /* genMixedOperation - gen code for operators between mixed types */
10178 /*-----------------------------------------------------------------*/
10180 TSD - Written for the PIC port - but this unfortunately is buggy.
10181 This routine is good in that it is able to efficiently promote
10182 types to different (larger) sizes. Unfortunately, the temporary
10183 variables that are optimized out by this routine are sometimes
10184 used in other places. So until I know how to really parse the
10185 iCode tree, I'm going to not be using this routine :(.
10187 static int genMixedOperation (iCode *ic)
10191 operand *result = IC_RESULT(ic);
10192 sym_link *ctype = operandType(IC_LEFT(ic));
10193 operand *right = IC_RIGHT(ic);
10199 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10201 pic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10207 nextright = IC_RIGHT(nextic);
10208 nextleft = IC_LEFT(nextic);
10209 nextresult = IC_RESULT(nextic);
10211 aopOp(right,ic,FALSE);
10212 aopOp(result,ic,FALSE);
10213 aopOp(nextright, nextic, FALSE);
10214 aopOp(nextleft, nextic, FALSE);
10215 aopOp(nextresult, nextic, FALSE);
10217 if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10219 operand *t = right;
10223 pic14_emitcode(";remove right +","");
10225 } else if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10227 operand *t = right;
10231 pic14_emitcode(";remove left +","");
10235 big = AOP_SIZE(nextleft);
10236 small = AOP_SIZE(nextright);
10238 switch(nextic->op) {
10241 pic14_emitcode(";optimize a +","");
10242 /* if unsigned or not an integral type */
10243 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10244 pic14_emitcode(";add a bit to something","");
10247 pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10249 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10250 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10251 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10253 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10261 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10262 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10263 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10266 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10268 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10269 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10270 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10271 pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10272 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10275 pic14_emitcode("rlf","known_zero,w");
10282 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10283 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10284 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10286 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10296 freeAsmop(right,NULL,ic,TRUE);
10297 freeAsmop(result,NULL,ic,TRUE);
10298 freeAsmop(nextright,NULL,ic,TRUE);
10299 freeAsmop(nextleft,NULL,ic,TRUE);
10301 nextic->generated = 1;
10308 /*-----------------------------------------------------------------*/
10309 /* genCast - gen code for casting */
10310 /*-----------------------------------------------------------------*/
10311 static void genCast (iCode *ic)
10313 operand *result = IC_RESULT(ic);
10314 sym_link *restype = operandType(result);
10315 sym_link *rtype = operandType(IC_RIGHT(ic));
10316 operand *right = IC_RIGHT(ic);
10320 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10321 /* if they are equivalent then do nothing */
10322 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10325 aopOp(right,ic,FALSE) ;
10326 aopOp(result,ic,FALSE);
10328 DEBUGpic14_AopType(__LINE__,NULL,right,result);
10330 /* if the result is a bit */
10331 if (AOP_TYPE(result) == AOP_CRY) {
10332 assert(!"assigning to bit variables is not supported");
10335 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10337 size = AOP_SIZE(result);
10339 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10341 emitpcode(POC_CLRF, popGet(AOP(result),0));
10342 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10343 emitpcode(POC_INCF, popGet(AOP(result),0));
10346 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
10351 if (IS_PTR(restype))
10353 operand *result = IC_RESULT(ic);
10354 //operand *left = IC_LEFT(ic);
10355 operand *right = IC_RIGHT(ic);
10358 /* copy common part */
10359 int max, size = AOP_SIZE(result);
10360 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10361 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10363 /* warn if we discard generic opinter tag */
10364 if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10366 //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10372 mov2w_op (right, size);
10373 movwf (AOP(result), size);
10376 /* upcast into generic pointer type? */
10377 if (IS_GENPTR(restype)
10378 && (size < AOP_SIZE(result))
10379 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10381 //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10384 switch (DCL_TYPE(rtype))
10386 case POINTER: /* __data */
10387 case FPOINTER: /* __data */
10388 assert (AOP_SIZE(right) == 2);
10389 tag = GPTRTAG_DATA;
10392 case CPOINTER: /* __code */
10393 assert (AOP_SIZE(right) == 2);
10394 tag = GPTRTAG_CODE;
10397 case GPOINTER: /* unknown destination, __data or __code */
10398 /* assume __data space (address of immediate) */
10399 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10400 if (AOP(right)->code)
10401 tag = GPTRTAG_CODE;
10403 tag = GPTRTAG_DATA;
10407 assert (!"unhandled pointer type");
10410 /* convert other values into pointers to __data space */
10411 tag = GPTRTAG_DATA;
10414 assert (AOP_SIZE(result) == 3);
10416 emitpcode(POC_CLRF, popGet(AOP(result), 2));
10418 emitpcode(POC_MOVLW, popGetLit(tag));
10419 movwf(AOP(result), 2);
10422 addSign(result, max, 0);
10427 /* if they are the same size : or less */
10428 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10430 /* if they are in the same place */
10431 if (pic14_sameRegs(AOP(right),AOP(result)))
10434 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10435 if (IS_PTR_CONST(rtype))
10436 DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10437 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10438 DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10440 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10441 emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10442 emitpcode(POC_MOVWF, popGet(AOP(result),0));
10443 emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10444 emitpcode(POC_MOVWF, popGet(AOP(result),1));
10445 if(AOP_SIZE(result) <2)
10446 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10450 /* if they in different places then copy */
10451 size = AOP_SIZE(result);
10454 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10455 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10457 //aopPut(AOP(result),
10458 // aopGet(AOP(right),offset,FALSE,FALSE),
10467 /* so we now know that the size of destination is greater
10468 than the size of the source.
10469 Now, if the next iCode is an operator then we might be
10470 able to optimize the operation without performing a cast.
10472 if(0 && genMixedOperation(ic)) {
10473 /* XXX: cannot optimize: must copy regs! */
10477 /* we move to result for the size of source */
10478 size = AOP_SIZE(right);
10481 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10482 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10486 addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10489 freeAsmop(right,NULL,ic,TRUE);
10490 freeAsmop(result,NULL,ic,TRUE);
10494 /*-----------------------------------------------------------------*/
10495 /* genDjnz - generate decrement & jump if not zero instrucion */
10496 /*-----------------------------------------------------------------*/
10497 static int genDjnz (iCode *ic, iCode *ifx)
10499 symbol *lbl, *lbl1;
10501 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10506 /* if the if condition has a false label
10507 then we cannot save */
10511 /* if the minus is not of the form
10513 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10514 !IS_OP_LITERAL(IC_RIGHT(ic)))
10517 if (operandLitValue(IC_RIGHT(ic)) != 1)
10520 /* if the size of this greater than one then no
10522 if (getSize(operandType(IC_RESULT(ic))) > 1)
10525 /* otherwise we can save BIG */
10526 lbl = newiTempLabel(NULL);
10527 lbl1= newiTempLabel(NULL);
10529 aopOp(IC_RESULT(ic),ic,FALSE);
10531 if (IS_AOP_PREG(IC_RESULT(ic))) {
10532 pic14_emitcode("dec","%s",
10533 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10534 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10535 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10539 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10540 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10542 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10543 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10546 /* pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10547 /* pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10548 /* pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10549 /* pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10552 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10553 ifx->generated = 1;
10557 /*-----------------------------------------------------------------*/
10558 /* genReceive - generate code for a receive iCode */
10559 /*-----------------------------------------------------------------*/
10560 static void genReceive (iCode *ic)
10563 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10565 if (isOperandInFarSpace(IC_RESULT(ic)) &&
10566 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10567 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10569 int size = getSize(operandType(IC_RESULT(ic)));
10570 int offset = fReturnSizePic - size;
10572 pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10573 fReturn[fReturnSizePic - offset - 1] : "acc"));
10576 aopOp(IC_RESULT(ic),ic,FALSE);
10577 size = AOP_SIZE(IC_RESULT(ic));
10580 pic14_emitcode ("pop","acc");
10581 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10586 aopOp(IC_RESULT(ic),ic,FALSE);
10588 assignResultValue(IC_RESULT(ic));
10591 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10594 /*-----------------------------------------------------------------*/
10595 /* genDummyRead - generate code for dummy read of volatiles */
10596 /*-----------------------------------------------------------------*/
10598 genDummyRead (iCode * ic)
10601 pic14_emitcode ("; genDummyRead","");
10602 pic14_emitcode ("; not implemented","");
10607 /*-----------------------------------------------------------------*/
10608 /* genpic14Code - generate code for pic14 based controllers */
10609 /*-----------------------------------------------------------------*/
10611 * At this point, ralloc.c has gone through the iCode and attempted
10612 * to optimize in a way suitable for a PIC. Now we've got to generate
10613 * PIC instructions that correspond to the iCode.
10615 * Once the instructions are generated, we'll pass through both the
10616 * peep hole optimizer and the pCode optimizer.
10617 *-----------------------------------------------------------------*/
10619 void genpic14Code (iCode *lic)
10626 lineHead = lineCurr = NULL;
10628 pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10631 /* if debug information required */
10632 if (options.debug && currFunc) {
10634 debugFile->writeFunction (currFunc, lic);
10639 for (ic = lic ; ic ; ic = ic->next ) {
10641 //DEBUGpic14_emitcode(";ic","");
10642 //fprintf (stderr, "in ic loop\n");
10643 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10644 //ic->lineno, printCLine(ic->filename, ic->lineno));
10646 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10648 //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10649 cline = printCLine (ic->filename, ic->lineno);
10650 if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10651 addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10652 //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10655 if (options.iCodeInAsm) {
10656 emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10658 /* if the result is marked as
10659 spilt and rematerializable or code for
10660 this has already been generated then
10662 if (resultRemat(ic) || ic->generated )
10665 /* depending on the operation */
10684 /* IPOP happens only when trying to restore a
10685 spilt live range, if there is an ifx statement
10686 following this pop then the if statement might
10687 be using some of the registers being popped which
10688 would destory the contents of the register so
10689 we need to check for this condition and handle it */
10691 ic->next->op == IFX &&
10692 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10693 genIfx (ic->next,ic);
10711 genEndFunction (ic);
10731 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10748 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
10752 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10759 /* note these two are xlated by algebraic equivalence
10760 during parsing SDCC.y */
10761 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10762 "got '>=' or '<=' shouldn't have come here");
10766 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10778 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10782 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10786 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10810 genRightShift (ic);
10813 case GET_VALUE_AT_ADDRESS:
10818 if (POINTER_SET(ic))
10845 addSet(&_G.sendSet,ic);
10848 case DUMMY_READ_VOLATILE:
10853 fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10860 /* now we are ready to call the
10861 peep hole optimizer */
10862 if (!options.nopeep) {
10863 peepHole (&lineHead);
10865 /* now do the actual printing */
10866 printLine (lineHead,codeOutFile);
10869 DFPRINTF((stderr,"printing pBlock\n\n"));
10870 printpBlock(stdout,pb);
10876 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10877 * (meaning: representing its own address) or not (referencing its contents).
10878 * This can only be decided based on the operand's type. */
10880 aop_isLitLike (asmop *aop)
10883 if (aop->type == AOP_LIT) return 1;
10884 if (aop->type == AOP_IMMD) return 1;
10885 if ((aop->type == AOP_PCODE) &&
10886 ((aop->aopu.pcop->type == PO_LITERAL)))
10888 /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10889 * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10896 op_isLitLike (operand *op)
10899 if (aop_isLitLike (AOP(op))) return 1;
10900 if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10901 if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;